Skip to content

Commit

Permalink
ui/workspaces: general refactor
Browse files Browse the repository at this point in the history
- Fixes doomemacs#1506: unsets uniquify-buffer-name-style to work around breakage
  in persp-mode having to do with buffers being retrospectively renamed.
  See Bad-ptr/persp-mode.el#104.
- Move creation of main workspace into persp-mode-hook, to ensure main
  workspace always exists and nil workspace is never active.
- Remove +workspaces|init-frame and significantly reduce LOC in
  +workspaces|init to the bare essentials. This _may_ break persp-mode
  in daemon Emacs, but I'll deal with that next.
  • Loading branch information
hlissner authored and uelei committed Aug 9, 2019
1 parent 355b994 commit 4f1ab82
Showing 1 changed file with 50 additions and 57 deletions.
107 changes: 50 additions & 57 deletions modules/ui/workspaces/config.el
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ nil Never create a new workspace on project switch.")
"The basename of the file to store single workspace perspectives. Will be
stored in `persp-save-dir'.")

(defvar +workspace--old-uniquify-style nil)


;;
;; Packages
Expand All @@ -39,43 +41,14 @@ stored in `persp-save-dir'.")
:init
(defun +workspaces|init ()
;; Remove default buffer predicate so persp-mode can put in its own
(setq default-frame-alist
(delq (assq 'buffer-predicate default-frame-alist)
default-frame-alist))
(add-hook 'after-make-frame-functions #'+workspaces|init-frame)
(require 'persp-mode)
(unless (daemonp)
(+workspaces|init-frame (selected-frame))))

(defun +workspaces|init-frame (frame)
"Ensure a main workspace exists and is switched to, if FRAME isn't in any
workspace. Also ensures that the *Warnings* buffer will be visible in main.
Uses `+workspaces-main' to determine the name of the main workspace."
(unless persp-mode
(persp-mode +1)
(unless noninteractive
(let (persp-before-switch-functions)
(with-selected-frame frame
;; 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 aren't auto-loading the last session
(when (and (string= (safe-persp-name (get-current-persp)) persp-nil-name)
(= persp-auto-resume-time -1))
(persp-frame-switch +workspaces-main frame)
;; We want to know where we are in every new daemon frame
(when (daemonp)
(run-at-time 0.1 nil #'+workspace/display))
;; 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)))))))))))
(delq! 'buffer-predicate default-frame-alist 'assq)
(persp-mode +1)
;; 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 'doom-init-modules-hook #'+workspaces|init t)
:config
Expand All @@ -91,34 +64,54 @@ Uses `+workspaces-main' to determine the name of the main workspace."

(advice-add #'persp-asave-on-exit :around #'+workspaces*autosave-real-buffers)

;; Don't rely on the built-in mechanism for auto-registering a buffer to the
;; current workspace. Instead, we add buffers when they are switched to.
(setq persp-add-buffer-on-find-file nil
persp-add-buffer-on-after-change-major-mode nil)
(add-hook 'persp-add-buffer-on-after-change-major-mode-filter-functions #'doom-unreal-buffer-p)

(defun +workspaces|add-current-buffer ()
(persp-add-buffer (current-buffer) (get-current-persp)))
(add-hook 'doom-switch-buffer-hook #'+workspaces|add-current-buffer)

(defun +workspaces|init-persp-mode ()
(cond (persp-mode
;; `persp-kill-buffer-query-function' must be last
;; `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))
((advice-remove #'doom-buffer-list #'+workspace-buffer-list))))
(t
(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)

(defun +workspaces|leave-nil-perspective (&rest _)
"Ensure that Doom is never in the nil perspective."
(when (string= (+workspace-current-name) persp-nil-name)
(+workspace-switch (or (if (+workspace-p +workspace--last) +workspace--last)
(car (+workspace-list-names))
+workspaces-main)
'auto-create)))
(add-hook 'persp-after-load-state-functions #'+workspaces|leave-nil-perspective)
(defun +workspaces|ensure-main-workspace (&rest _)
"Ensure the main workspace exists and the nil workspace is never active."
(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 aren't auto-loading the last session
(when (and (string= (safe-persp-name (get-current-persp)) persp-nil-name)
(or after-init-time (= persp-auto-resume-time -1)))
(persp-frame-switch +workspaces-main))))
(add-hook 'persp-mode-hook #'+workspaces|ensure-main-workspace)
(add-hook 'persp-after-load-state-functions #'+workspaces|ensure-main-workspace)

;; 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
;; add buffers when they are switched to.
(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."
(persp-add-buffer (current-buffer) (get-current-persp)))
(add-hook 'doom-switch-buffer-hook #'+workspaces|add-current-buffer)

(add-to-list 'persp-add-buffer-on-after-change-major-mode-filter-functions
#'doom-unreal-buffer-p)

(defun +workspaces*evil-alternate-buffer (&optional window)
"Make `evil-alternate-buffer' ignore buffers outside the current workspace."
Expand Down

0 comments on commit 4f1ab82

Please sign in to comment.