ui/workspaces: general refactor

- Fixes #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.
This commit is contained in:
Henrik Lissner 2019-06-25 11:21:39 +02:00
parent 86ebe08593
commit 9823881d47
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395

View file

@ -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 "The basename of the file to store single workspace perspectives. Will be
stored in `persp-save-dir'.") stored in `persp-save-dir'.")
(defvar +workspace--old-uniquify-style nil)
;; ;;
;; Packages ;; Packages
@ -39,43 +41,14 @@ stored in `persp-save-dir'.")
:init :init
(defun +workspaces|init () (defun +workspaces|init ()
;; Remove default buffer predicate so persp-mode can put in its own ;; Remove default buffer predicate so persp-mode can put in its own
(setq default-frame-alist (delq! 'buffer-predicate default-frame-alist 'assq)
(delq (assq 'buffer-predicate default-frame-alist) (persp-mode +1)
default-frame-alist)) ;; Fix #319: the warnings buffer gets swallowed by creating
(add-hook 'after-make-frame-functions #'+workspaces|init-frame) ;; `+workspaces-main', so we display it manually, if it exists.
(require 'persp-mode) (when-let (warnings (get-buffer "*Warnings*"))
(unless (daemonp) (save-excursion
(+workspaces|init-frame (selected-frame)))) (display-buffer-in-side-window
warnings '((window-height . shrink-window-if-larger-than-buffer))))))
(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)))))))))))
(add-hook 'doom-init-modules-hook #'+workspaces|init t) (add-hook 'doom-init-modules-hook #'+workspaces|init t)
:config :config
@ -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) (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 () (defun +workspaces|init-persp-mode ()
(cond (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) (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)
;; Restrict buffer list to workspace ;; Restrict buffer list to workspace
(advice-add #'doom-buffer-list :override #'+workspace-buffer-list)) (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) (add-hook 'persp-mode-hook #'+workspaces|init-persp-mode)
(defun +workspaces|leave-nil-perspective (&rest _) (defun +workspaces|ensure-main-workspace (&rest _)
"Ensure that Doom is never in the nil perspective." "Ensure the main workspace exists and the nil workspace is never active."
(when (string= (+workspace-current-name) persp-nil-name) (let (persp-before-switch-functions)
(+workspace-switch (or (if (+workspace-p +workspace--last) +workspace--last) ;; The default perspective persp-mode creates (`persp-nil-name') is
(car (+workspace-list-names)) ;; special and doesn't represent a real persp object, so buffers can't
+workspaces-main) ;; really be assigned to it, among other quirks. We create a *real* main
'auto-create))) ;; workspace to fill this role.
(add-hook 'persp-after-load-state-functions #'+workspaces|leave-nil-perspective) (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) (defun +workspaces*evil-alternate-buffer (&optional window)
"Make `evil-alternate-buffer' ignore buffers outside the current workspace." "Make `evil-alternate-buffer' ignore buffers outside the current workspace."