feature/workspaces: major refactor & various fixes

+ Rewrite projectile integration.
+ Fix per-frame workspaces not cleaning up after itself when an
  frame-associated workspace (or its frame) is destroyed.
+ Alias +workspace-p to perspective-p instead of persp-p (which isn't as
  accurate, because it counts nil as a valid perspective).
+ Extract orphaned-buffer list functionality in +workspace-buffer-list
  into seperate function: +workspace-orphaned-buffer-list.
+ Allow toggle-debug-on-error to catch workspace errors.
+ Remove +workspace/kill-session-and-quit (never used)
+ Ensure persp-mode is loaded as late as possible.
This commit is contained in:
Henrik Lissner 2018-01-20 02:44:12 -05:00
parent 6b164a6103
commit 381a4416ed
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
4 changed files with 159 additions and 170 deletions

View file

@ -34,7 +34,8 @@
;; --- Predicates ------------------------- ;; --- Predicates -------------------------
;;;###autoload ;;;###autoload
(defalias #'+workspace-p #'persp-p "Return t if OBJ is a perspective hash table.") (defalias #'+workspace-p #'perspective-p
"Return t if OBJ is a perspective hash table.")
;;;###autoload ;;;###autoload
(defun +workspace-exists-p (name) (defun +workspace-exists-p (name)
@ -51,48 +52,52 @@
;; --- Getters ---------------------------- ;; --- Getters ----------------------------
;;;###autoload ;;;###autoload
(defun +workspace-get (name &optional noerror) (defalias '+workspace-current #'get-current-persp
"Returns a workspace (perspective struct) named NAME." "Return the currently active workspace.")
(when-let* ((persp (persp-get-by-name name)))
(cond ((+workspace-p persp) persp)
((not noerror) (error "'%s' is an invalid workspace" name)))))
;;;###autoload ;;;###autoload
(defalias '+workspace-current #'get-current-persp) (defun +workspace-get (name &optional noerror)
"Return a workspace named NAME. Unless NOERROR is non-nil, this throws an
error if NAME doesn't exist."
(when-let* ((persp (persp-get-by-name name)))
(cond ((+workspace-p persp) persp)
((not noerror)
(error "No workspace called '%s' was found" name)))))
;;;###autoload ;;;###autoload
(defun +workspace-current-name () (defun +workspace-current-name ()
"Get the name of the current workspace." "Get the name of the current workspace."
(safe-persp-name (get-current-persp))) (safe-persp-name (+workspace-current)))
;;;###autoload ;;;###autoload
(defun +workspace-list () (defun +workspace-list ()
"Return a list of workspace structs." "Return a list of workspace structs (satisifes `+workspace-p')."
(mapcar #'persp-get-by-name (+workspace-list-names))) (cdr (cl-loop for persp being the hash-values of *persp-hash*
collect persp)))
;;;###autoload ;;;###autoload
(defun +workspace-list-names () (defun +workspace-list-names ()
"Return a list of workspace names (strings)." "Return the list of names of open workspaces."
(delete persp-nil-name (persp-names-current-frame-fast-ordered))) (cdr persp-names-cache))
;;;###autoload ;;;###autoload
(defun +workspace-buffer-list (&optional persp) (defun +workspace-buffer-list (&optional persp)
"Return a list of buffers in PERSP (defaults to the current perspective). "Return a list of buffers in PERSP.
The buffer list is ordered by recency (same as `buffer-list'). The buffer list is ordered by recency (same as `buffer-list').
PERSP can be a string (name of a workspace) or a perspective hash (satisfies PERSP can be a string (name of a workspace) or a workspace (satisfies
`+workspace-p'). `+workspace-p'). If nil or omitted, it defaults to the current workspace."
If PERSP is t, then return a list of orphaned buffers associated with no
perspectives."
(let ((persp (or persp (+workspace-current)))) (let ((persp (or persp (+workspace-current))))
(if (eq persp t) (cl-assert (+workspace-p persp) t)
(cl-remove-if #'persp--buffer-in-persps (buffer-list)) (cl-loop for buf in (buffer-list)
(cl-assert (+workspace-p persp) t) if (+workspace-contains-buffer-p buf persp)
(cl-loop for buf in (buffer-list) collect buf)))
if (+workspace-contains-buffer-p buf persp)
collect buf)))) ;;;###autoload
(defun +workspace-orphaned-buffer-list ()
"Return a list of buffers that aren't associated with any perspective."
(cl-remove-if #'persp--buffer-in-persps (buffer-list)))
;; --- Actions ---------------------------- ;; --- Actions ----------------------------
@ -175,7 +180,10 @@ buffers."
;;;###autoload ;;;###autoload
(defun +workspace-switch (name &optional auto-create-p) (defun +workspace-switch (name &optional auto-create-p)
"Switch to another workspace." "Switch to another workspace named NAME (a string).
If AUTO-CREATE-P is non-nil, create the workspace if it doesn't exist, otherwise
throws an error."
(unless (+workspace-exists-p name) (unless (+workspace-exists-p name)
(if auto-create-p (if auto-create-p
(+workspace-new name) (+workspace-new name)
@ -188,35 +196,11 @@ buffers."
(persp-frame-switch name) (persp-frame-switch name)
(equal (+workspace-current-name) name))) (equal (+workspace-current-name) name)))
;;;###autoload
(defun +workspace-on-new-frame (frame &optional _new-frame-p)
"Spawn a perspective for each new frame."
(select-frame frame)
(+workspace/new)
(set-frame-parameter frame 'assoc-persp (+workspace-current-name)))
;; ;;
;; Interactive commands ;; Interactive commands
;; ;;
;;;###autoload
(defun +workspace/load (name)
"Load a workspace and switch to it. If called with C-u, try to reload the
current workspace (by name) from session files."
(interactive
(list
(if current-prefix-arg
(+workspace-current-name)
(completing-read
"Workspace to load: "
(persp-list-persp-names-in-file
(expand-file-name +workspace-data-file persp-save-dir))))))
(if (not (+workspace-load name))
(+workspace-error (format "Couldn't load workspace %s" name))
(+workspace/switch-to name)
(+workspace/display)))
;;;###autoload ;;;###autoload
(defun +workspace/load-session (&optional name) (defun +workspace/load-session (&optional name)
"Load a session and switch to it. If called with C-u, try to load the last "Load a session and switch to it. If called with C-u, try to load the last
@ -234,19 +218,6 @@ session."
(+workspace-message (format "'%s' workspace loaded" name) 'success)) (+workspace-message (format "'%s' workspace loaded" name) 'success))
'(error (+workspace-error (cadr ex) t)))) '(error (+workspace-error (cadr ex) t))))
;;;###autoload
(defun +workspace/save (name)
"Save the current workspace. If called with C-u, autosave the current
workspace."
(interactive
(list
(if current-prefix-arg
(+workspace-current-name)
(completing-read "Workspace to save: " (+workspace-list-names)))))
(if (+workspace-save name)
(+workspace-message (format "'%s' workspace saved" name) 'success)
(+workspace-error (format "Couldn't save workspace %s" name))))
;;;###autoload ;;;###autoload
(defun +workspace/save-session (&optional name) (defun +workspace/save-session (&optional name)
"Save the current session. If called with C-u, prompt you for the name to save "Save the current session. If called with C-u, prompt you for the name to save
@ -257,24 +228,24 @@ the session as."
(completing-read (completing-read
"Save session as: " "Save session as: "
(directory-files persp-save-dir nil "^[^_.]"))))) (directory-files persp-save-dir nil "^[^_.]")))))
(condition-case ex (condition-case-unless-debug ex
(let ((name (or name persp-auto-save-fname))) (let ((name (or name persp-auto-save-fname)))
(if (+workspace-save-session name) (if (+workspace-save-session name)
(+workspace-message (format "Saved session as '%s'" name) 'success) (+workspace-message (format "Saved session as '%s'" name) 'success)
(error "Couldn't save session as '%s'" name))) (error "Couldn't save session as '%s'" name)))
'(error (+workspace-error (cadr ex) t)))) ('error (+workspace-error ex t))))
;;;###autoload ;;;###autoload
(defun +workspace/rename (new-name) (defun +workspace/rename (new-name)
"Rename the current workspace." "Rename the current workspace."
(interactive (list (read-from-minibuffer "New workspace name: "))) (interactive (list (read-from-minibuffer "New workspace name: ")))
(condition-case ex (condition-case-unless-debug ex
(let* ((current-name (+workspace-current-name)) (let* ((current-name (+workspace-current-name))
(old-name (+workspace-rename current-name new-name))) (old-name (+workspace-rename current-name new-name)))
(unless old-name (unless old-name
(error "Failed to rename %s" current-name)) (error "Failed to rename %s" current-name))
(+workspace-message (format "Renamed '%s'->'%s'" old-name new-name) 'success)) (+workspace-message (format "Renamed '%s'->'%s'" old-name new-name) 'success))
('error (+workspace-error (cadr ex) t)))) ('error (+workspace-error ex t))))
;;;###autoload ;;;###autoload
(defun +workspace/delete (name) (defun +workspace/delete (name)
@ -288,7 +259,7 @@ workspace to delete."
(+workspace-list-names) (+workspace-list-names)
nil nil current-name) nil nil current-name)
current-name)))) current-name))))
(condition-case ex (condition-case-unless-debug ex
(+workspace-message (+workspace-message
(let ((workspaces (length (+workspace-list-names)))) (let ((workspaces (length (+workspace-list-names))))
(cond ((> workspaces 1) (cond ((> workspaces 1)
@ -306,45 +277,37 @@ workspace to delete."
(switch-to-buffer (doom-fallback-buffer)) (switch-to-buffer (doom-fallback-buffer))
(format "No workspaces detected! Auto-creating '%s' workspace" +workspaces-main)))) (format "No workspaces detected! Auto-creating '%s' workspace" +workspaces-main))))
'success) 'success)
('error (+workspace-error (cadr ex) t)))) ('error (+workspace-error ex t))))
;;;###autoload ;;;###autoload
(defun +workspace/kill-session () (defun +workspace/kill-session ()
"Delete the current session, clears all workspaces, windows and buffers." "Delete the current session, all workspaces, windows and their buffers."
(interactive) (interactive)
(unless (cl-every #'+workspace-delete (+workspace-list-names)) (unless (cl-every #'+workspace-delete (+workspace-list-names))
(+workspace-error "Could not clear session")) (+workspace-error "Could not clear session"))
(+workspace-switch +workspaces-main t) (+workspace-switch +workspaces-main t)
(doom/kill-all-buffers) (doom/kill-all-buffers)
(let ((fallback-buf (doom-fallback-buffer))) (switch-to-buffer (doom-fallback-buffer))
(switch-to-buffer fallback-buf) (doom/cleanup-session))
(doom/cleanup-session)))
;;;###autoload
(defun +workspace/kill-session-and-quit ()
"Forgets current session and quits."
(interactive)
(+workspace/kill-session)
(save-buffers-kill-terminal))
;;;###autoload ;;;###autoload
(defun +workspace/new (&optional name clone-p) (defun +workspace/new (&optional name clone-p)
"Create a new workspace named NAME. If OVERWRITE-P is non-nil, clear any "Create a new workspace named NAME. If CLONE-P is non-nil, clone the current
pre-existing workspace." workspace, otherwise the new workspace is blank."
(interactive "iP") (interactive "iP")
(unless name (unless name
(setq name (format "#%s" (+workspace--generate-id)))) (setq name (format "#%s" (+workspace--generate-id))))
(condition-case ex (condition-case-unless-debug ex
(let ((exists-p (+workspace-exists-p name))) (if (+workspace-exists-p name)
(if exists-p (error "%s already exists" name)
(error "%s already exists" name) (+workspace-switch name t)
(+workspace-switch name t) (if clone-p
(if clone-p (let ((persp (+workspace-get name)))
(dolist (window (window-list)) (dolist (window (window-list))
(persp-add-buffer (window-buffer window) persp nil)) (persp-add-buffer (window-buffer window) persp nil)))
(delete-other-windows-internal) (delete-other-windows-internal)
(switch-to-buffer (doom-fallback-buffer))) (switch-to-buffer (doom-fallback-buffer)))
(+workspace/display))) (+workspace/display))
('error (+workspace-error (cadr ex) t)))) ('error (+workspace-error (cadr ex) t))))
;;;###autoload ;;;###autoload
@ -390,7 +353,7 @@ end of the workspace list."
(let ((current-name (+workspace-current-name))) (let ((current-name (+workspace-current-name)))
(if (equal current-name persp-nil-name) (if (equal current-name persp-nil-name)
(+workspace-switch +workspaces-main t) (+workspace-switch +workspaces-main t)
(condition-case ex (condition-case-unless-debug ex
(let* ((persps (+workspace-list-names)) (let* ((persps (+workspace-list-names))
(perspc (length persps)) (perspc (length persps))
(index (cl-position current-name persps))) (index (cl-position current-name persps)))
@ -410,8 +373,9 @@ end of the workspace list."
;;;###autoload ;;;###autoload
(defun +workspace/close-window-or-workspace () (defun +workspace/close-window-or-workspace ()
"Close the selected window. If it's the last window in the workspace, close "Close the selected window. If it's the last window in the workspace, either
the workspace and move to the next." close the workspace (as well as its associated frame, if one exists) and move to
the next."
(interactive) (interactive)
(let ((delete-window-fn (if (featurep 'evil) #'evil-window-delete #'delete-window))) (let ((delete-window-fn (if (featurep 'evil) #'evil-window-delete #'delete-window)))
(if (window-dedicated-p) (if (window-dedicated-p)
@ -420,21 +384,14 @@ the workspace and move to the next."
(cond ((or (+workspace--protected-p current-persp-name) (cond ((or (+workspace--protected-p current-persp-name)
(cdr (doom-visible-windows))) (cdr (doom-visible-windows)))
(funcall delete-window-fn)) (funcall delete-window-fn))
((cdr (+workspace-list-names))
(+workspace/delete current-persp-name)))))))
;;;###autoload ((cdr (+workspace-list-names))
(defun +workspace/close-workspace-or-frame () (let ((frame-persp (frame-parameter nil 'workspace)))
"Close the current workspace. If it's the last, delete the frame instead." (if (string= frame-persp (+workspace-current-name))
(interactive) (delete-frame)
(let ((frames (length (frame-list))) (+workspace/delete current-persp-name))))
(workspaces (length (+workspace-list-names))))
(cond ((> workspaces 1) (t (+workspace-error "Can't delete last workspace" t)))))))
(call-interactively #'+workspace/delete))
((> frames 1)
(call-interactively #'delete-frame))
(t
(error "Can't delete last frame.")))))
;; ;;
@ -455,7 +412,7 @@ the workspace and move to the next."
'+workspace-tab-face))) '+workspace-tab-face)))
" "))) " ")))
(defun +workspace--message-body (message &optional type) (defun +workspace--message-body (message &optional type)
(concat (+workspace--tabline) (concat (+workspace--tabline)
(propertize " | " 'face 'font-lock-comment-face) (propertize " | " 'face 'font-lock-comment-face)
(propertize (format "%s" message) (propertize (format "%s" message)
@ -473,7 +430,8 @@ the workspace and move to the next."
;;;###autoload ;;;###autoload
(defun +workspace-error (message &optional noerror) (defun +workspace-error (message &optional noerror)
"Show an 'elegant' error in the echo area next to a listing of workspaces." "Show an 'elegant' error in the echo area next to a listing of workspaces."
(funcall (if noerror #'message #'error) "%s" (+workspace--message-body message 'error))) (funcall (if noerror #'message #'error)
"%s" (+workspace--message-body message 'error)))
;;;###autoload ;;;###autoload
(defun +workspace/display () (defun +workspace/display ()
@ -487,34 +445,56 @@ the workspace and move to the next."
;; ;;
;;;###autoload ;;;###autoload
(defun +workspaces|delete-associated-workspace-maybe (frame) (defun +workspaces|delete-associated-workspace (frame)
"Delete workspace associated with current frame IF it has no real buffers." "Delete workspace associated with current frame.
A workspace gets associated with a frame when a new frame is interactively
created."
(when persp-mode (when persp-mode
(let ((frame-persp (frame-parameter frame 'assoc-persp))) (let ((frame-persp (frame-parameter frame 'workspace)))
(when (and (equal frame-persp (+workspace-current-name)) (when (string= frame-persp (+workspace-current-name))
(not (equal frame-persp +workspaces-main)))
(+workspace/delete frame-persp))))) (+workspace/delete frame-persp)))))
;;;###autoload ;;;###autoload
(defun +workspaces|per-project () (defun +workspaces|cleanup-unassociated-buffers ()
"Open a new workspace when switching to another project. "Kill leftover buffers that are unassociated with any perspective."
Ensures the scratch (or dashboard) buffers are CDed into the project's root."
(when persp-mode (when persp-mode
(let ((cwd default-directory)) (cl-loop for buf in (buffer-list)
(+workspace-switch (projectile-project-name) t) unless (persp--buffer-in-persps buf)
(switch-to-buffer (doom-fallback-buffer)) if (kill-buffer buf)
(setq default-directory cwd) sum 1)))
(+workspace-message
(format "Switched to '%s' in new workspace" (+workspace-current-name))
'success))))
;;;###autoload ;;;###autoload
(defun +workspaces|cleanup-unassociated-buffers () (defun +workspaces|associate-frame (frame &optional _new-frame-p)
(cl-loop for buf in (buffer-list) "Create a blank, new perspective and associate it with FRAME."
unless (persp--buffer-in-persps buf) (when persp-mode
if (kill-buffer buf) (with-selected-frame frame
sum 1)) (+workspace/new)
(set-frame-parameter frame 'workspace (+workspace-current-name))
(+workspace/display))))
(defvar +workspaces--project-dir nil)
;;;###autoload
(defun +workspaces|set-project-action ()
"A `projectile-switch-project-action' that sets the project directory for
`+workspaces|switch-to-project'."
(setq +workspaces--project-dir default-directory))
;;;###autoload
(defun +workspaces|switch-to-project ()
"Creates a workspace dedicated to a new project. Should be hooked to
`projectile-after-switch-project-hook'."
(when (and persp-mode +workspaces--project-dir)
(unwind-protect
(let* ((persp
(let ((default-directory +workspaces--project-dir))
(+workspace-new (projectile-project-name))))
(new-name (persp-name persp)))
(+workspace-switch new-name)
(switch-to-buffer (doom-fallback-buffer))
(+workspace-message
(format "Switched to '%s' in new workspace" new-name)
'success))
(setq +workspaces--project-dir nil))))
;; ;;
@ -523,10 +503,10 @@ Ensures the scratch (or dashboard) buffers are CDed into the project's root."
;;;###autoload ;;;###autoload
(defun +workspaces*autosave-real-buffers (orig-fn &rest args) (defun +workspaces*autosave-real-buffers (orig-fn &rest args)
"Don't autosave if no real buffers are open." "Don't autosave if no real buffers are open."
(when (doom-real-buffer-list) (when (doom-real-buffer-list)
(apply orig-fn args)) (apply orig-fn args))
t) t)
;;;###autoload ;;;###autoload
(defun +workspaces*switch-project-by-name (orig-fn &rest args) (defun +workspaces*switch-project-by-name (orig-fn &rest args)

View file

@ -22,13 +22,39 @@ renamed.")
;; ;;
(def-package! persp-mode (def-package! persp-mode
:defer t
:init
(defun +workspaces|init (&optional frame)
(require 'persp-mode)
(unless persp-mode
(persp-mode +1))
(unless noninteractive
(let (persp-before-switch-functions persp-activated-functions)
;; The default perspective persp-mode makes (defined by
;; `persp-nil-name') is special and doesn't actually represent a real
;; persp object, so buffers can't really be assigned to it, among other
;; quirks. We create a *real* main workspace to fill this role.
(unless (persp-get-by-name +workspaces-main)
(persp-add-new +workspaces-main))
;; Switch to it if we aren't auto-loading the last session
(when (and (equal (safe-persp-name (get-current-persp)) persp-nil-name)
(= persp-auto-resume-time -1))
(persp-frame-switch +workspaces-main)))
;; The warnings buffer gets swallowed by creating `+workspaces-main', so
;; we display it manually, if it exists (fix #319).
(when-let* ((warnings (get-buffer "*Warnings*")))
(save-excursion
(display-buffer-in-side-window
warnings '((window-height . shrink-window-if-larger-than-buffer)))))))
(add-hook 'doom-init-hook #'+workspaces|init)
(add-hook 'after-make-frame-functions #'+workspaces|init)
:config :config
(setq persp-autokill-buffer-on-remove 'kill-weak (setq persp-autokill-buffer-on-remove 'kill-weak
persp-nil-name "nil"
persp-nil-hidden t persp-nil-hidden t
persp-auto-save-fname "autosave" persp-auto-save-fname "autosave"
persp-save-dir (concat doom-etc-dir "workspaces/") persp-save-dir (concat doom-etc-dir "workspaces/")
persp-set-last-persp-for-new-frames nil persp-set-last-persp-for-new-frames t
persp-switch-to-added-buffer nil persp-switch-to-added-buffer nil
persp-remove-buffers-from-nil-persp-behaviour nil persp-remove-buffers-from-nil-persp-behaviour nil
;; Don't restore winconf on new frames ;; Don't restore winconf on new frames
@ -39,53 +65,35 @@ renamed.")
;; auto-save on kill ;; auto-save on kill
persp-auto-save-opt (if noninteractive 0 1)) persp-auto-save-opt (if noninteractive 0 1))
;; Bootstrap
(add-hook 'doom-init-hook #'+workspaces|init)
(add-hook 'after-make-frame-functions #'+workspaces|init)
(add-hook 'persp-mode-hook #'+workspaces|init-persp-mode) (add-hook 'persp-mode-hook #'+workspaces|init-persp-mode)
;; only auto-save when real buffers are present
(advice-add #'persp-asave-on-exit :around #'+workspaces*autosave-real-buffers)
;; Modify `delete-window' to close the workspace if used on the last window ;; Modify `delete-window' to close the workspace if used on the last window
(define-key persp-mode-map [remap delete-window] #'+workspace/close-window-or-workspace) (define-key persp-mode-map [remap delete-window] #'+workspace/close-window-or-workspace)
(define-key persp-mode-map [remap evil-delete-window] #'+workspace/close-window-or-workspace)
;; only auto-save when real buffers are present
(advice-add #'persp-asave-on-exit :around #'+workspaces*autosave-real-buffers)
;; For `doom/cleanup-session' ;; For `doom/cleanup-session'
(add-hook 'doom-cleanup-hook #'+workspaces|cleanup-unassociated-buffers) (add-hook 'doom-cleanup-hook #'+workspaces|cleanup-unassociated-buffers)
;; per-frame workspaces ;; per-frame workspaces
(setq persp-init-new-frame-behaviour-override nil (setq persp-init-new-frame-behaviour-override nil
persp-interactive-init-frame-behaviour-override #'+workspace-on-new-frame) persp-interactive-init-frame-behaviour-override #'+workspaces|associate-frame)
(add-hook 'delete-frame-functions #'+workspaces|delete-associated-workspace-maybe) ;; delete frame associated with workspace, if it exists
;; Per-project workspaces (add-hook 'delete-frame-functions #'+workspaces|delete-associated-workspace)
(setq projectile-switch-project-action #'+workspaces|per-project)
;; per-project workspaces
(setq projectile-switch-project-action #'+workspaces|set-project-action)
(add-hook 'projectile-after-switch-project-hook #'+workspaces|switch-to-project)
;; ;;
(defun +workspaces|init (&optional frame)
(unless persp-mode
(persp-mode +1))
(unless noninteractive
;; The default perspective persp-mode makes (defined by
;; `persp-nil-name') is special and doesn't actually represent a real
;; persp object, so buffers can't really be assigned to it, among other
;; quirks. We create a *real* main workspace to fill this role.
(unless (persp-with-name-exists-p +workspaces-main)
(persp-add-new +workspaces-main))
;; Switch to it if we aren't auto-loading the last session
(when (and (equal (safe-persp-name (get-current-persp)) persp-nil-name)
(= persp-auto-resume-time -1))
(persp-frame-switch +workspaces-main (or frame (selected-frame))))
;; The warnings buffer gets swallowed by creating `+workspaces-main', so
;; we display it manually, if it exists (fix #319).
(when-let* ((warnings (get-buffer "*Warnings*")))
(save-excursion
(display-buffer-in-side-window
warnings '((window-height . shrink-window-if-larger-than-buffer)))))))
(defun +workspaces|init-persp-mode () (defun +workspaces|init-persp-mode ()
;; Remap `buffer-list' to current workspace's buffers in `doom-buffer-list'
(cond (persp-mode (cond (persp-mode
;; Ensure `persp-kill-buffer-query-function' is last in kill-buffer-query-functions ;; Ensure `persp-kill-buffer-query-function' is last in
;; kill-buffer-query-functions
(remove-hook 'kill-buffer-query-functions 'persp-kill-buffer-query-function) (remove-hook 'kill-buffer-query-functions 'persp-kill-buffer-query-function)
(add-hook 'kill-buffer-query-functions 'persp-kill-buffer-query-function t) (add-hook 'kill-buffer-query-functions 'persp-kill-buffer-query-function t)
;; Remap `buffer-list' to current workspace's buffers in
;; `doom-buffer-list'
(advice-add #'switch-to-buffer :after #'+workspaces*auto-add-buffer) (advice-add #'switch-to-buffer :after #'+workspaces*auto-add-buffer)
(advice-add #'display-buffer :after #'+workspaces*auto-add-buffer) (advice-add #'display-buffer :after #'+workspaces*auto-add-buffer)
(advice-add #'doom-buffer-list :override #'+workspace-buffer-list)) (advice-add #'doom-buffer-list :override #'+workspace-buffer-list))

View file

@ -10,6 +10,7 @@
collect `(,bsym (get-buffer-create ,(symbol-name bsym)))))) collect `(,bsym (get-buffer-create ,(symbol-name bsym))))))
`(let ((persp-auto-resume-time -1) `(let ((persp-auto-resume-time -1)
(persp-auto-save-opt 0)) (persp-auto-save-opt 0))
(require 'persp-mode)
(let (noninteractive) (let (noninteractive)
(persp-mode +1)) (persp-mode +1))
(+workspace-switch +workspaces-main t) (+workspace-switch +workspaces-main t)

View file

@ -29,7 +29,7 @@
"M-t" #'+workspace/new "M-t" #'+workspace/new
"M-T" #'+workspace/display "M-T" #'+workspace/display
"M-w" #'delete-window "M-w" #'delete-window
"M-W" #'+workspace/close-workspace-or-frame "M-W" #'delete-frame
"M-n" #'evil-buffer-new "M-n" #'evil-buffer-new
"M-N" #'make-frame "M-N" #'make-frame
"M-1" (λ! (+workspace/switch-to 0)) "M-1" (λ! (+workspace/switch-to 0))