dotfiles/.config/emacs/lisp/init-persp.el
2023-05-20 01:57:20 +09:00

109 lines
4.4 KiB
EmacsLisp

;;; init-persp.el -*- lexical-binding: t -*-
(require 'init-const)
(require 'init-funcs)
;; Windows/buffers sets shared among frames + save/load.
(use-package persp-mode
:diminish
:autoload (get-current-persp persp-contain-buffer-p)
:hook (after-init . persp-mode)
:init (setq persp-keymap-prefix (kbd "C-x p")
persp-nil-name "default"
persp-set-last-persp-for-new-frames nil
persp-kill-foreign-buffer-behaviour 'kill
persp-auto-resume-time 0)
:config
(with-no-warnings
;; Don't save if the state is not loaded
(defvar persp-state-loaded nil
"Whether the state is loaded.")
(defun my-persp-after-load-state (&rest _)
(setq persp-state-loaded t))
(advice-add #'persp-load-state-from-file :after #'my-persp-after-load-state)
(add-hook 'emacs-startup-hook
(lambda ()
(add-hook 'find-file-hook #'my-persp-after-load-state)))
(defun my-persp-asave-on-exit (fn &optional interactive-query opt)
(if persp-state-loaded
(funcall fn interactive-query opt)
t))
(advice-add #'persp-asave-on-exit :around #'my-persp-asave-on-exit))
;; Don't save dead or temporary buffers
(add-hook 'persp-filter-save-buffers-functions
(lambda (b)
"Ignore dead and unneeded buffers."
(or (not (buffer-live-p b))
(string-prefix-p " *" (buffer-name b)))))
(add-hook 'persp-filter-save-buffers-functions
(lambda (b)
"Ignore temporary buffers."
(let ((bname (file-name-nondirectory (buffer-name b))))
(or (string-prefix-p ".newsrc" bname)
(string-prefix-p "magit" bname)
(string-prefix-p "COMMIT_EDITMSG" bname)
(string-prefix-p "Pfuture-Callback" bname)
(string-prefix-p "treemacs-persist" bname)
(string-match-p "\\.elc\\|\\.tar\\|\\.gz\\|\\.zip\\'" bname)
(string-match-p "\\.bin\\|\\.so\\|\\.dll\\|\\.exe\\'" bname)))))
;; Don't save persp configs in `recentf'
(with-eval-after-load 'recentf
(push persp-save-dir recentf-exclude))
;; Eshell integration
(persp-def-buffer-save/load
:mode 'eshell-mode :tag-symbol 'def-eshell-buffer
:save-vars '(major-mode default-directory))
;; Shell integration
(persp-def-buffer-save/load
:mode 'shell-mode :tag-symbol 'def-shell-buffer
:mode-restore-function (lambda (_) (shell))
:save-vars '(major-mode default-directory)))
;; Project integration
(use-package persp-mode-project-bridge
:autoload (persp-mode-project-bridge-find-perspectives-for-all-buffers
persp-mode-project-bridge-kill-perspectives)
:hook
(persp-mode-project-bridge-mode . (lambda ()
(if persp-mode-project-bridge-mode
(persp-mode-project-bridge-find-perspectives-for-all-buffers)
(persp-mode-project-bridge-kill-perspectives))))
(persp-mode . persp-mode-project-bridge-mode)
:init (when (icons-displayable-p)
(setq persp-mode-project-bridge-persp-name-prefix ""))
:config
(with-no-warnings
;; HACK: Allow saving to files
(defun my-persp-mode-project-bridge-add-new-persp (name)
(let ((persp (persp-get-by-name name *persp-hash* :nil)))
(if (eq :nil persp)
(prog1
(setq persp (persp-add-new name))
(when persp
(set-persp-parameter 'persp-mode-project-bridge t persp)
(persp-add-buffer (cl-remove-if-not #'get-file-buffer (project-files (project-current)))
persp nil nil)))
persp)))
(advice-add #'persp-mode-project-bridge-add-new-persp
:override #'my-persp-mode-project-bridge-add-new-persp)
;; HACK: Switch to buffer after switching perspective
(defun my-persp-mode-project-bridge-hook-switch (fn &rest _args)
"Switch to a perspective when hook is activated."
(let ((buf (current-buffer)))
(funcall fn)
(when (buffer-live-p buf)
(switch-to-buffer buf))))
(advice-add #'persp-mode-project-bridge-hook-switch
:around #'my-persp-mode-project-bridge-hook-switch)))
(provide 'init-persp)
;;; init-persp.el ends here