feature/workspaces: refactor persp-mode init
This commit is contained in:
parent
73fa9ceab3
commit
f3562eb038
3 changed files with 118 additions and 66 deletions
|
@ -187,6 +187,13 @@ buffers."
|
||||||
+workspaces-main)))
|
+workspaces-main)))
|
||||||
(persp-frame-switch name))
|
(persp-frame-switch 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
|
||||||
|
@ -473,12 +480,10 @@ the workspace and move to the next."
|
||||||
(interactive)
|
(interactive)
|
||||||
(message "%s" (+workspace--tabline)))
|
(message "%s" (+workspace--tabline)))
|
||||||
|
|
||||||
;;;###autoload
|
|
||||||
(defun +workspace-on-new-frame (frame &optional _new-frame-p)
|
;;
|
||||||
"Spawn a perspective for each new frame."
|
;; Hooks
|
||||||
(select-frame frame)
|
;;
|
||||||
(+workspace/new)
|
|
||||||
(set-frame-parameter frame 'assoc-persp (+workspace-current-name)))
|
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun +workspaces|delete-associated-workspace-maybe (frame)
|
(defun +workspaces|delete-associated-workspace-maybe (frame)
|
||||||
|
@ -489,6 +494,32 @@ the workspace and move to the next."
|
||||||
(not (equal frame-persp +workspaces-main)))
|
(not (equal frame-persp +workspaces-main)))
|
||||||
(+workspace/delete frame-persp)))))
|
(+workspace/delete frame-persp)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun +workspaces|per-project (&optional root)
|
||||||
|
"Open a new workspace when switching to another project.
|
||||||
|
|
||||||
|
Ensures the scratch (or dashboard) buffers are CDed into the project's root."
|
||||||
|
(when persp-mode
|
||||||
|
(let ((cwd default-directory))
|
||||||
|
(+workspace-switch (projectile-project-name) t)
|
||||||
|
(switch-to-buffer (doom-fallback-buffer))
|
||||||
|
(setq default-directory cwd)
|
||||||
|
(+workspace-message
|
||||||
|
(format "Switched to '%s' in new workspace" (+workspace-current-name))
|
||||||
|
'success))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun +workspaces|cleanup-unassociated-buffers ()
|
||||||
|
(cl-loop for buf in (buffer-list)
|
||||||
|
unless (persp--buffer-in-persps buf)
|
||||||
|
if (kill-buffer buf)
|
||||||
|
do (cl-incf n)))
|
||||||
|
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; Advice
|
||||||
|
;;
|
||||||
|
|
||||||
;;;###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."
|
||||||
|
|
|
@ -42,56 +42,51 @@ renamed.")
|
||||||
;; Bootstrap
|
;; Bootstrap
|
||||||
(add-hook 'doom-post-init-hook #'+workspaces|init)
|
(add-hook 'doom-post-init-hook #'+workspaces|init)
|
||||||
(add-hook 'after-make-frame-functions #'+workspaces|init)
|
(add-hook 'after-make-frame-functions #'+workspaces|init)
|
||||||
|
(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
|
||||||
(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)
|
||||||
|
;; For `doom/cleanup-session'
|
||||||
|
(add-hook 'doom-cleanup-hook #'+workspaces|cleanup-unassociated-buffers)
|
||||||
|
|
||||||
;; per-frame and per-project 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 #'+workspace-on-new-frame)
|
||||||
(add-hook 'delete-frame-functions #'+workspaces|delete-associated-workspace-maybe)
|
(add-hook 'delete-frame-functions #'+workspaces|delete-associated-workspace-maybe)
|
||||||
|
;; Per-project workspaces
|
||||||
(defun +workspaces|per-project (&optional root)
|
|
||||||
"Open a new workspace when switching to another project.
|
|
||||||
|
|
||||||
Ensures the scratch (or dashboard) buffers are CDed into the project's root."
|
|
||||||
(when persp-mode
|
|
||||||
(let ((cwd default-directory))
|
|
||||||
(+workspace-switch (projectile-project-name) t)
|
|
||||||
(switch-to-buffer (doom-fallback-buffer))
|
|
||||||
(setq default-directory cwd)
|
|
||||||
(+workspace-message
|
|
||||||
(format "Switched to '%s' in new workspace" (+workspace-current-name))
|
|
||||||
'success))))
|
|
||||||
(setq projectile-switch-project-action #'+workspaces|per-project)
|
(setq projectile-switch-project-action #'+workspaces|per-project)
|
||||||
|
|
||||||
;; only auto-save when real buffers are present
|
;;
|
||||||
(advice-add #'persp-asave-on-exit :around #'+workspaces*autosave-real-buffers)
|
|
||||||
|
|
||||||
(defun +workspaces|on-persp-mode ()
|
|
||||||
;; Remap `buffer-list' to current workspace's buffers in `doom-buffer-list'
|
|
||||||
(if persp-mode
|
|
||||||
(advice-add #'doom-buffer-list :override #'+workspace-buffer-list)
|
|
||||||
(advice-remove #'doom-buffer-list #'+workspace-buffer-list)))
|
|
||||||
(add-hook 'persp-mode-hook #'+workspaces|on-persp-mode)
|
|
||||||
|
|
||||||
(defun +workspaces|init (&optional frame)
|
(defun +workspaces|init (&optional frame)
|
||||||
(unless persp-mode
|
(unless persp-mode
|
||||||
(persp-mode +1)
|
(persp-mode +1))
|
||||||
;; Ensure `persp-kill-buffer-query-function' is last in kill-buffer-query-functions
|
(unless noninteractive
|
||||||
(remove-hook 'kill-buffer-query-functions 'persp-kill-buffer-query-function)
|
;; The default perspective persp-mode makes (defined by
|
||||||
(add-hook 'kill-buffer-query-functions 'persp-kill-buffer-query-function t))
|
;; `persp-nil-name') is special and doesn't actually represent a real
|
||||||
(let ((frame (or frame (selected-frame))))
|
;; persp object, so buffers can't really be assigned to it, among other
|
||||||
(unless noninteractive
|
;; quirks. We create a *real* main workspace to fill this role.
|
||||||
;; The default perspective persp-mode makes (defined by
|
(unless (persp-with-name-exists-p +workspaces-main)
|
||||||
;; `persp-nil-name') is special and doesn't actually represent a real
|
(persp-add-new +workspaces-main))
|
||||||
;; persp object, so buffers can't really be assigned to it, among other
|
;; Switch to it if we aren't auto-loading the last session
|
||||||
;; quirks. We create a *real* main workspace to fill this role.
|
(when (and (equal (safe-persp-name (get-current-persp)) persp-nil-name)
|
||||||
(unless (persp-with-name-exists-p +workspaces-main)
|
(= persp-auto-resume-time -1))
|
||||||
(persp-add-new +workspaces-main))
|
(persp-frame-switch +workspaces-main (or frame (selected-frame))))))
|
||||||
;; Switch to it if we aren't auto-loading the last session
|
|
||||||
(when (and (equal (safe-persp-name (get-current-persp)) persp-nil-name)
|
(defun +workspaces|init-persp-mode ()
|
||||||
(= persp-auto-resume-time -1))
|
;; Remap `buffer-list' to current workspace's buffers in `doom-buffer-list'
|
||||||
(persp-frame-switch +workspaces-main frame)))))
|
(cond (persp-mode
|
||||||
|
;; Ensure `persp-kill-buffer-query-function' is last in kill-buffer-query-functions
|
||||||
|
(remove-hook 'kill-buffer-query-functions 'persp-kill-buffer-query-function)
|
||||||
|
(add-hook 'kill-buffer-query-functions 'persp-kill-buffer-query-function t)
|
||||||
|
|
||||||
|
(advice-add #'switch-to-buffer :after #'+workspaces*auto-add-buffer)
|
||||||
|
(advice-add #'display-buffer :after #'+workspaces*auto-add-buffer)
|
||||||
|
(advice-add #'doom-buffer-list :override #'+workspace-buffer-list))
|
||||||
|
(t
|
||||||
|
(advice-remove #'switch-to-buffer #'+workspaces*auto-add-buffer)
|
||||||
|
(advice-remove #'display-buffer #'+workspaces*auto-add-buffer)
|
||||||
|
(advice-remove #'doom-buffer-list #'+workspace-buffer-list))))
|
||||||
|
|
||||||
(defun +workspaces*auto-add-buffer (buffer &rest _)
|
(defun +workspaces*auto-add-buffer (buffer &rest _)
|
||||||
"Auto-associate buffers with perspectives upon opening them.
|
"Auto-associate buffers with perspectives upon opening them.
|
||||||
|
@ -101,7 +96,5 @@ Allows a perspective-specific buffer list via `+workspaces-buffer-list'."
|
||||||
(not persp-temporarily-display-buffer)
|
(not persp-temporarily-display-buffer)
|
||||||
(doom-real-buffer-p buffer))
|
(doom-real-buffer-p buffer))
|
||||||
(persp-add-buffer buffer (get-current-persp) nil)
|
(persp-add-buffer buffer (get-current-persp) nil)
|
||||||
(force-mode-line-update t)))
|
(force-mode-line-update t))))
|
||||||
(advice-add #'switch-to-buffer :after #'+workspaces*auto-add-buffer)
|
|
||||||
(advice-add #'display-buffer :after #'+workspaces*auto-add-buffer))
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
;; -*- no-byte-compile: t; -*-
|
;; -*- no-byte-compile: t; -*-
|
||||||
;;; feature/workspaces/test/autoload-workspaces.el
|
;;; feature/workspaces/test/autoload-workspaces.el
|
||||||
|
|
||||||
|
(load "persp-mode.el" nil t)
|
||||||
(require! :feature workspaces)
|
(require! :feature workspaces)
|
||||||
|
|
||||||
(defmacro with-workspace!! (buffer-args &rest body)
|
(defmacro with-workspace!! (buffer-args &rest body)
|
||||||
|
@ -8,28 +9,30 @@
|
||||||
(let ((buffers
|
(let ((buffers
|
||||||
(cl-loop for bsym in buffer-args
|
(cl-loop for bsym in buffer-args
|
||||||
collect `(,bsym (get-buffer-create ,(symbol-name bsym))))))
|
collect `(,bsym (get-buffer-create ,(symbol-name bsym))))))
|
||||||
`(let (noninteractive)
|
`(let ((persp-auto-resume-time -1)
|
||||||
|
(persp-auto-save-opt 0)
|
||||||
|
persp-autokill-buffer-on-remove
|
||||||
|
persp-names-cache
|
||||||
|
noninteractive)
|
||||||
(+workspaces|init)
|
(+workspaces|init)
|
||||||
(save-window-excursion
|
(let* (,@buffers)
|
||||||
(let* (,@buffers)
|
(cl-loop with persp = (get-current-persp)
|
||||||
(cl-loop with persp = (get-current-persp)
|
for buf in (list ,@(mapcar #'car buffers))
|
||||||
for buf in (list ,@(mapcar #'car buffers))
|
do (persp-add-buffer buf persp)
|
||||||
do (persp-add-buffer buf persp)
|
do (with-current-buffer buf
|
||||||
do (with-current-buffer buf
|
(setq buffer-file-name (make-temp-file "workspaces-test-"))))
|
||||||
(setq buffer-file-name (make-temp-file "workspaces-test-"))))
|
,@body
|
||||||
,@body
|
(+workspace-delete +workspaces-main)
|
||||||
(dolist (buf (list ,@(mapcar #'car buffers)))
|
(let (kill-buffer-query-functions kill-buffer-hook)
|
||||||
(persp-remove-buffer buf)
|
(mapc #'kill-buffer (list ,@(mapcar #'car buffers)))))
|
||||||
(kill-buffer buf))))
|
(persp-mode -1))))
|
||||||
(persp-mode -1)
|
|
||||||
(setq *persp-hash* nil
|
|
||||||
persp-buffer-props-hash nil))))
|
|
||||||
|
|
||||||
;;
|
;; `+workspaces|init'
|
||||||
(def-test! init
|
(def-test! init
|
||||||
(with-workspace!! ()
|
(with-workspace!! ()
|
||||||
(should (equal (+workspace-current-name) +workspaces-main))))
|
(should (equal (+workspace-current-name) +workspaces-main))))
|
||||||
|
|
||||||
|
;; `+workspaces*auto-add-buffer'
|
||||||
(def-test! auto-add-buffer-to-persp
|
(def-test! auto-add-buffer-to-persp
|
||||||
(let ((a (generate-new-buffer "a")))
|
(let ((a (generate-new-buffer "a")))
|
||||||
(doom-set-buffer-real a t)
|
(doom-set-buffer-real a t)
|
||||||
|
@ -38,6 +41,8 @@
|
||||||
(switch-to-buffer a)
|
(switch-to-buffer a)
|
||||||
(should (+workspace-contains-buffer-p a)))))
|
(should (+workspace-contains-buffer-p a)))))
|
||||||
|
|
||||||
|
;; `+workspace-current'
|
||||||
|
;; `+workspace-current-name'
|
||||||
(def-test! current
|
(def-test! current
|
||||||
(with-workspace!! ()
|
(with-workspace!! ()
|
||||||
(should (equal (+workspace-current-name) +workspaces-main))
|
(should (equal (+workspace-current-name) +workspaces-main))
|
||||||
|
@ -49,6 +54,8 @@
|
||||||
(should (+workspace-p current-workspace))
|
(should (+workspace-p current-workspace))
|
||||||
(should (equal workspace current-workspace)))))
|
(should (equal workspace current-workspace)))))
|
||||||
|
|
||||||
|
;; `+workspace-list'
|
||||||
|
;; `+workspace-list-names'
|
||||||
(def-test! workspace-list
|
(def-test! workspace-list
|
||||||
(with-workspace!! ()
|
(with-workspace!! ()
|
||||||
(should (equal (+workspace-list-names)
|
(should (equal (+workspace-list-names)
|
||||||
|
@ -56,6 +63,9 @@
|
||||||
(should (equal (+workspace-list)
|
(should (equal (+workspace-list)
|
||||||
(list (+workspace-current))))))
|
(list (+workspace-current))))))
|
||||||
|
|
||||||
|
;; `+workspace-new'
|
||||||
|
;; `+workspace-rename'
|
||||||
|
;; `+workspace-delete'
|
||||||
(def-test! workspace-crud
|
(def-test! workspace-crud
|
||||||
"Creating, reading, updating and deleting workspaces."
|
"Creating, reading, updating and deleting workspaces."
|
||||||
(with-workspace!! ()
|
(with-workspace!! ()
|
||||||
|
@ -71,6 +81,7 @@
|
||||||
(+workspace-delete renamed-workspace-name)
|
(+workspace-delete renamed-workspace-name)
|
||||||
(should (= (length (+workspace-list-names)) 1)))))
|
(should (= (length (+workspace-list-names)) 1)))))
|
||||||
|
|
||||||
|
;; `+workspace-switch'
|
||||||
(def-test! workspace-switch
|
(def-test! workspace-switch
|
||||||
(with-workspace!! ()
|
(with-workspace!! ()
|
||||||
(let ((new-workspace-name "*new-test*"))
|
(let ((new-workspace-name "*new-test*"))
|
||||||
|
@ -78,6 +89,8 @@
|
||||||
(should (+workspace-switch new-workspace-name t))
|
(should (+workspace-switch new-workspace-name t))
|
||||||
(should (equal (+workspace-current-name) new-workspace-name)))))
|
(should (equal (+workspace-current-name) new-workspace-name)))))
|
||||||
|
|
||||||
|
;; `+workspace-buffer-list'
|
||||||
|
;; `+workspace-contains-buffer-p'
|
||||||
(def-test! buffer-list
|
(def-test! buffer-list
|
||||||
(with-workspace!! (a b)
|
(with-workspace!! (a b)
|
||||||
(let ((c (get-buffer-create "c"))
|
(let ((c (get-buffer-create "c"))
|
||||||
|
@ -93,3 +106,18 @@
|
||||||
(switch-to-buffer "d")
|
(switch-to-buffer "d")
|
||||||
(should-not (+workspace-contains-buffer-p d)))))
|
(should-not (+workspace-contains-buffer-p d)))))
|
||||||
|
|
||||||
|
;; `+workspace/close-window-or-workspace'
|
||||||
|
(def-test! close-window-or-workspace
|
||||||
|
(with-workspace!! (a b)
|
||||||
|
(let ((ws (+workspace-current-name))
|
||||||
|
(inhibit-message t))
|
||||||
|
(+workspace-switch "test" t)
|
||||||
|
(split-window)
|
||||||
|
(should (equal (+workspace-current-name) "test"))
|
||||||
|
(should (= (length (doom-visible-windows)) 2))
|
||||||
|
;; kill window if more than one
|
||||||
|
(+workspace/close-window-or-workspace)
|
||||||
|
(should (= (length (doom-visible-windows)) 1))
|
||||||
|
;; kill workspace on last window
|
||||||
|
(+workspace/close-window-or-workspace)
|
||||||
|
(should (equal (+workspace-current-name) "main")))))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue