From 6a3e87950132a322bd382444ee35dfb1be0c286b Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sat, 11 Feb 2017 00:52:25 -0500 Subject: [PATCH] feature/workspaces: refactor; more reliable session/popup persistence --- modules/feature/workspaces/autoload.el | 25 ++++++++-------- modules/feature/workspaces/config.el | 40 +++++++++++++++++++------- 2 files changed, 43 insertions(+), 22 deletions(-) diff --git a/modules/feature/workspaces/autoload.el b/modules/feature/workspaces/autoload.el index 6419bfb33..782ae68a4 100644 --- a/modules/feature/workspaces/autoload.el +++ b/modules/feature/workspaces/autoload.el @@ -1,8 +1,5 @@ ;;; feature/workspaces/autoload.el -(defvar +workspace-session-file "_sessions" - "The file basename in which to store entire perspective sessions.") - (defvar +workspace-workspace-file "_workspaces" "The file basename in which to store single workspace perspectives.") @@ -173,7 +170,8 @@ session." "Session to load: " (-map 'f-filename (f--files persp-save-dir - (not (string-prefix-p "_" (f-filename it))))))))) + (not (string-prefix-p "_" (f-filename it))))) + nil t)))) (+workspace-load-session name) (+workspace/display)) @@ -203,9 +201,10 @@ the session as." (f--files persp-save-dir (not (string-prefix-p "_" (f-filename it))))))))) (condition-case ex - (if (+workspace-save-session name) - (+workspace-message (format "Saved session as %s" name) 'success) - (error "Couldn't save session as %s" name)) + (let ((name (or name (+workspace-current-name)))) + (if (+workspace-save-session name) + (+workspace-message (format "Saved session as %s" name) 'success) + (error "Couldn't save session as %s" name))) '(error (+workspace-error (cadr ex) t)))) ;;;###autoload @@ -247,9 +246,9 @@ workspace to delete." (+workspace-switch persp-nil-name) (delete-other-windows-internal) (switch-to-buffer doom-fallback-buffer) - (--each (unless (eq (buffer-name it) doom-fallback-buffer) - (kill-buffer it)) - (buffer-list))) + (--each (buffer-list) + (unless (eq (buffer-name it) doom-fallback-buffer) + (kill-buffer it)))) ;;;###autoload (defun +workspace/new (&optional name clone-p) @@ -328,8 +327,10 @@ the workspace and move to the next." (doom/popup-close) (let ((current-persp-name (+workspace-current-name))) (cond ((or (equal current-persp-name persp-nil-name) - (not (one-window-p t))) - (delete-window)) + (= (length (doom-visible-windows)) 1)) + (if (bound-and-true-p evil-mode) + (evil-window-delete) + (delete-window))) ((> (length (+workspace-list)) 1) (let* ((names (+workspace-list)) (index (--find-index (equal current-persp-name it) names))) diff --git a/modules/feature/workspaces/config.el b/modules/feature/workspaces/config.el index 189a743fd..756c9826e 100644 --- a/modules/feature/workspaces/config.el +++ b/modules/feature/workspaces/config.el @@ -1,17 +1,25 @@ ;;; feature/workspaces/config.el ;; `persp-mode' gives me workspaces, a workspace-restricted `buffer-list', and -;; file-based session persistence. The switch from workgroups2 was motivated by -;; performance. Workgroups2 wasn't entirely stable either. +;; file-based session persistence. I had used workgroups2 for this, but +;; abandoned it because of its instability and impact on performance. +;; `persp-mode' has proven faster and more reliable (and it's still maintained). +;; +;; Note: persp-mode requires `workgroups' for file persistence in Emacs 24.4. + +(defvar +workspaces-load-session-hook nil + "A hook that runs when persp loads a new session.") + (@use-package persp-mode :demand t :init (setq persp-autokill-buffer-on-remove 'kill-weak persp-nil-name "main" - persp-auto-save-fname "_autosave" + persp-auto-save-fname "autosave" persp-save-dir (concat doom-cache-dir "workspaces/") persp-set-last-persp-for-new-frames nil persp-auto-resume-time (if (display-graphic-p) 0.01 -1) + persp-auto-save-opt 0 persp-switch-to-added-buffer nil) :config @@ -24,13 +32,13 @@ persp-common-buffer-filter-functions) ;; Auto-add buffers when opening them. Allows a perspective-specific buffer list. - (defun doom*persp-auto-add-buffer (buffer &rest _) + (defun +workspaces*auto-add-buffer (buffer &rest _) (when (and persp-mode (not persp-temporarily-display-buffer)) (persp-add-buffer buffer (get-current-persp) nil))) - (advice-add 'switch-to-buffer :after 'doom*persp-auto-add-buffer) - (advice-add 'display-buffer :after 'doom*persp-auto-add-buffer) + (advice-add 'switch-to-buffer :after '+workspaces*auto-add-buffer) + (advice-add 'display-buffer :after '+workspaces*auto-add-buffer) - ;; TODO Integration with projectile + ;; TODO Integration with projectile? ;; ;; Create a new workspace on project switch ;; (defun doom|new-workspace-on-project-change () ;; (+workspace-new (f-filename (doom-project-root)))) @@ -38,12 +46,24 @@ ;; TODO Test per-frame perspectives + ;; We use this instead of persp's native autosave. Why? So the "Wrote + ;; .../_autosave" message appears AFTER the quit confirmation prompt! + ;; + ;; ...I need help. + (defun +workspace|save-on-quit () + (when persp-mode (@quiet (persp-save-state-to-file)))) + (add-hook 'kill-emacs-hook '+workspace|save-on-quit) + + (defun +workspaces*reinit-popups (&rest _) + (run-hook-with-args '+workspaces-load-session-hook (window-list))) + (advice-add 'persp-load-state-from-file :after '+workspaces*reinit-popups) + ;; Restore popups on load - (defun +workspaces*reinit-popups () - (dolist (window (window-list)) + (defun +workspaces|restore-popups (windows) + (dolist (window windows) (let ((plist (window-parameter window 'popup))) (when plist (doom-popup--init window plist))))) - (advice-add 'persp-load-state-from-file :after '+workspaces*reinit-popups)) + (add-hook '+workspaces-load-session-hook '+workspaces|restore-popups)) (@after ivy (defun +workspaces|ivy-ignore-non-persp-buffers (b)