diff --git a/modules/ui/workspaces/autoload/workspaces.el b/modules/ui/workspaces/autoload/workspaces.el index 10dd85bb6..1f91854fd 100644 --- a/modules/ui/workspaces/autoload/workspaces.el +++ b/modules/ui/workspaces/autoload/workspaces.el @@ -441,7 +441,7 @@ the next." ;;; Hooks ;;;###autoload -(defun +workspaces|delete-associated-workspace (&optional frame) +(defun +workspaces-delete-associated-workspace-h (&optional frame) "Delete workspace associated with current frame. A workspace gets associated with a frame when a new frame is interactively created." @@ -453,17 +453,7 @@ created." (+workspace/delete frame-persp))))) ;;;###autoload -(defun +workspaces|cleanup-unassociated-buffers () - "Kill leftover buffers that are unassociated with any perspective." - (when persp-mode - (cl-loop for buf in (buffer-list) - unless (or (persp--buffer-in-persps buf) - (get-buffer-window buf)) - if (kill-buffer buf) - sum 1))) - -;;;###autoload -(defun +workspaces|associate-frame (frame &optional _new-frame-p) +(defun +workspaces-associate-frame-fn (frame &optional _new-frame-p) "Create a blank, new perspective and associate it with FRAME." (when persp-mode (if (not (persp-frame-list-without-daemon)) @@ -479,13 +469,13 @@ created." (defvar +workspaces--project-dir nil) ;;;###autoload -(defun +workspaces|set-project-action () +(defun +workspaces-set-project-action-fn () "A `projectile-switch-project-action' that sets the project directory for -`+workspaces|switch-to-project'." +`+workspaces-switch-to-project-h'." (setq +workspaces--project-dir default-directory)) ;;;###autoload -(defun +workspaces|switch-to-project (&optional dir) +(defun +workspaces-switch-to-project-h (&optional dir) "Creates a workspace dedicated to a new project. If one already exists, switch to it. If in the main workspace and it's empty, recycle that workspace, without renaming it. @@ -527,7 +517,7 @@ This be hooked to `projectile-after-switch-project-hook'." ;;; Advice ;;;###autoload -(defun +workspaces*autosave-real-buffers (orig-fn &rest args) +(defun +workspaces-autosave-real-buffers-a (orig-fn &rest args) "Don't autosave if no real buffers are open." (when (doom-real-buffer-list) (apply orig-fn args)) diff --git a/modules/ui/workspaces/config.el b/modules/ui/workspaces/config.el index 56431578e..c03b0c585 100644 --- a/modules/ui/workspaces/config.el +++ b/modules/ui/workspaces/config.el @@ -37,17 +37,17 @@ stored in `persp-save-dir'.") ;; Packages (def-package! persp-mode - :commands (persp-switch-to-buffer) + :commands persp-switch-to-buffer :init - (defun +workspaces|init () - ;; Remove default buffer predicate so persp-mode can put in its own - (delq! 'buffer-predicate default-frame-alist 'assq) - (require 'persp-mode) - (if (daemonp) - (add-hook 'after-make-frame-functions #'persp-mode-start-and-remove-from-make-frame-hook) - (persp-mode +1))) - (unless noninteractive - (add-hook 'doom-init-modules-hook #'+workspaces|init)) + (add-hook 'doom-init-modules-hook + (defun +workspaces-init-h () + (unless noninteractive + ;; Remove default buffer predicate so persp-mode can put in its own + (delq! 'buffer-predicate default-frame-alist 'assq) + (require 'persp-mode) + (if (daemonp) + (add-hook 'after-make-frame-functions #'persp-mode-start-and-remove-from-make-frame-hook) + (persp-mode +1))))) :config (setq persp-autokill-buffer-on-remove 'kill-weak persp-nil-hidden t @@ -59,50 +59,49 @@ stored in `persp-save-dir'.") persp-auto-resume-time -1 ; Don't auto-load on startup persp-auto-save-opt (if noninteractive 0 1)) ; auto-save on kill - (advice-add #'persp-asave-on-exit :around #'+workspaces*autosave-real-buffers) + (advice-add #'persp-asave-on-exit :around #'+workspaces-autosave-real-buffers-a) - (defun +workspaces|ensure-main-workspace (&rest _) - "Ensure the main workspace exists and the nil workspace is never active." - (when persp-mode - (let (persp-before-switch-functions) - ;; The default perspective persp-mode creates (`persp-nil-name') is - ;; special and doesn't 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're in the nil perspective - (dolist (frame (frame-list)) - (when (string= (safe-persp-name (get-current-persp frame)) persp-nil-name) - (persp-frame-switch +workspaces-main frame) - ;; Fix #319: the warnings buffer gets swallowed by creating - ;; `+workspaces-main', so we display it manually, if it exists. - (when-let (warnings (get-buffer "*Warnings*")) - (save-excursion - (display-buffer-in-side-window - warnings '((window-height . shrink-window-if-larger-than-buffer)))))))))) - (add-hook 'persp-mode-hook #'+workspaces|ensure-main-workspace) - (add-hook 'persp-after-load-state-functions #'+workspaces|ensure-main-workspace) + (add-hook! '(persp-mode-hook persp-after-load-state-functions) + (defun +workspaces-ensure-main-workspace-h (&rest _) + "Ensure the main workspace exists and the nil workspace is never active." + (when persp-mode + (let (persp-before-switch-functions) + ;; The default perspective persp-mode creates (`persp-nil-name') is + ;; special and doesn't 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're in the nil perspective + (dolist (frame (frame-list)) + (when (string= (safe-persp-name (get-current-persp frame)) persp-nil-name) + (persp-frame-switch +workspaces-main frame) + ;; Fix #319: the warnings buffer gets swallowed by creating + ;; `+workspaces-main', so we display it manually, if it exists. + (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 () - (cond (persp-mode - ;; `uniquify' breaks persp-mode. It renames old buffers, which causes - ;; errors when switching between perspective (their buffers are - ;; serialized by name and persp-mode expects them to have the same - ;; name when restored). - (when uniquify-buffer-name-style - (setq +workspace--old-uniquify-style uniquify-buffer-name-style)) - (setq uniquify-buffer-name-style nil) - ;; Ensure `persp-kill-buffer-query-function' is last - (remove-hook 'kill-buffer-query-functions #'persp-kill-buffer-query-function) - (add-hook 'kill-buffer-query-functions #'persp-kill-buffer-query-function t) - ;; Restrict buffer list to workspace - (advice-add #'doom-buffer-list :override #'+workspace-buffer-list)) - (t - (when +workspace--old-uniquify-style - (setq uniquify-buffer-name-style +workspace--old-uniquify-style)) - (advice-remove #'doom-buffer-list #'+workspace-buffer-list)))) - (add-hook 'persp-mode-hook #'+workspaces|init-persp-mode) + (add-hook 'persp-mode-hook + (defun +workspaces-init-persp-mode-h () + (cond (persp-mode + ;; `uniquify' breaks persp-mode. It renames old buffers, which causes + ;; errors when switching between perspective (their buffers are + ;; serialized by name and persp-mode expects them to have the same + ;; name when restored). + (when uniquify-buffer-name-style + (setq +workspace--old-uniquify-style uniquify-buffer-name-style)) + (setq uniquify-buffer-name-style nil) + ;; Ensure `persp-kill-buffer-query-function' is last + (remove-hook 'kill-buffer-query-functions #'persp-kill-buffer-query-function) + (add-hook 'kill-buffer-query-functions #'persp-kill-buffer-query-function t) + ;; Restrict buffer list to workspace + (advice-add #'doom-buffer-list :override #'+workspace-buffer-list)) + (t + (when +workspace--old-uniquify-style + (setq uniquify-buffer-name-style +workspace--old-uniquify-style)) + (advice-remove #'doom-buffer-list #'+workspace-buffer-list))))) ;; We don't rely on the built-in mechanism for auto-registering a buffer to ;; the current workspace; some buffers slip through the cracks. Instead, we @@ -110,26 +109,27 @@ stored in `persp-save-dir'.") (setq persp-add-buffer-on-find-file nil persp-add-buffer-on-after-change-major-mode nil) - (defun +workspaces|add-current-buffer () - "Add current buffer to focused perspective." - (when persp-mode - (persp-add-buffer (current-buffer) (get-current-persp)))) - (add-hook 'doom-switch-buffer-hook #'+workspaces|add-current-buffer) + (add-hook 'doom-switch-buffer-hook + (defun +workspaces-add-current-buffer-h () + "Add current buffer to focused perspective." + (when persp-mode + (persp-add-buffer (current-buffer) (get-current-persp))))) (add-to-list 'persp-add-buffer-on-after-change-major-mode-filter-functions #'doom-unreal-buffer-p) - (defun +workspaces*evil-alternate-buffer (&optional window) + (def-advice! +workspaces-evil-alternate-buffer-a (&optional window) "Make `evil-alternate-buffer' ignore buffers outside the current workspace." - (let* ((prev-buffers (if persp-mode - (cl-remove-if-not #'persp-contain-buffer-p (window-prev-buffers) - :key #'car) - (window-prev-buffers))) + :override #'evil-alternate-buffer + (let* ((prev-buffers + (if persp-mode + (cl-remove-if-not #'persp-contain-buffer-p (window-prev-buffers) + :key #'car) + (window-prev-buffers))) (head (car prev-buffers))) (if (eq (car head) (window-buffer window)) (cadr prev-buffers) head))) - (advice-add #'evil-alternate-buffer :override #'+workspaces*evil-alternate-buffer) ;; Delete the current workspace if closing the last open window (define-key! persp-mode-map @@ -139,14 +139,14 @@ stored in `persp-save-dir'.") ;; per-frame workspaces (setq persp-init-frame-behaviour t persp-init-new-frame-behaviour-override nil - persp-interactive-init-frame-behaviour-override #'+workspaces|associate-frame - persp-emacsclient-init-frame-behaviour-override #'+workspaces|associate-frame) - (add-hook 'delete-frame-functions #'+workspaces|delete-associated-workspace) + persp-interactive-init-frame-behaviour-override #'+workspaces-associate-frame-fn + persp-emacsclient-init-frame-behaviour-override #'+workspaces-associate-frame-fn) + (add-hook 'delete-frame-functions #'+workspaces-delete-associated-workspace-h) ;; per-project workspaces, but reuse current workspace if empty - (setq projectile-switch-project-action #'+workspaces|set-project-action + (setq projectile-switch-project-action #'+workspaces-set-project-action-fn counsel-projectile-switch-project-action - '(1 ("o" +workspaces|switch-to-project "open project in new workspace") + '(1 ("o" +workspaces-switch-to-project-h "open project in new workspace") ("O" counsel-projectile-switch-project-action "jump to a project buffer or file") ("f" counsel-projectile-switch-project-action-find-file "jump to a project file") ("d" counsel-projectile-switch-project-action-find-dir "jump to a project directory") @@ -166,7 +166,7 @@ stored in `persp-save-dir'.") ("xt" counsel-projectile-switch-project-action-run-term "invoke term from project root") ("X" counsel-projectile-switch-project-action-org-capture "org-capture into project"))) - (add-hook 'projectile-after-switch-project-hook #'+workspaces|switch-to-project) + (add-hook 'projectile-after-switch-project-hook #'+workspaces-switch-to-project-h) ;; In some scenarios, persp-mode throws error when Emacs tries to die, ;; preventing its death and trapping us in Emacs. @@ -176,9 +176,9 @@ stored in `persp-save-dir'.") ;; Fix #1017: stop session persistence from restoring a broken posframe (after! posframe - (defun +workspaces|delete-all-posframes (&rest _) - (posframe-delete-all)) - (add-hook 'persp-after-load-state-functions #'+workspaces|delete-all-posframes)) + (add-hook 'persp-after-load-state-functions + (defun +workspaces-delete-all-posframes-h (&rest _) + (posframe-delete-all)))) ;; ;; eshell @@ -204,12 +204,12 @@ stored in `persp-save-dir'.") (push (cons buf-name base-buf-name) +workspaces--indirect-buffers-to-restore) nil))) - (defun +workspaces|reload-indirect-buffers (&rest _) - (dolist (ibc +workspaces--indirect-buffers-to-restore) - (cl-destructuring-bind (buffer-name . base-buffer-name) ibc - (when (buffer-live-p (get-buffer base-buffer-name)) - (when (get-buffer buffer-name) - (setq buffer-name (generate-new-buffer-name buffer-name))) - (make-indirect-buffer bb buffer-name t)))) - (setq +workspaces--indirect-buffers-to-restore nil)) - (add-hook 'persp-after-load-state-functions #'+workspaces|reload-indirect-buffers)) + (add-hook 'persp-after-load-state-functions + (defun +workspaces-reload-indirect-buffers-h (&rest _) + (dolist (ibc +workspaces--indirect-buffers-to-restore) + (cl-destructuring-bind (buffer-name . base-buffer-name) ibc + (when (buffer-live-p (get-buffer base-buffer-name)) + (when (get-buffer buffer-name) + (setq buffer-name (generate-new-buffer-name buffer-name))) + (make-indirect-buffer bb buffer-name t)))) + (setq +workspaces--indirect-buffers-to-restore nil))))