Skip to content

Instantly share code, notes, and snippets.

@Bad-ptr
Last active July 31, 2022 11:52
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Bad-ptr/1aca1ec54c3bdb2ee80996eb2b68ad2d to your computer and use it in GitHub Desktop.
Save Bad-ptr/1aca1ec54c3bdb2ee80996eb2b68ad2d to your computer and use it in GitHub Desktop.
persp-mode stuff
(with-eval-after-load "persp-mode"
(with-eval-after-load "helm-mode"
(defvar helm-mini-tail-sources (cdr helm-mini-default-sources))
(defvar helm-persp-completing-read-handlers
'((switch-to-buffer . helm-persp-buffer-list-bridge)
(kill-buffer . helm-persp-buffer-list-bridge)
(persp-kill-buffer . helm-persp-buffer-list-bridge)
(persp-temporarily-display-buffer . helm-persp-buffer-list-bridge)
(persp-add-buffer . helm-persp-buffer-list-bridge)
(persp-remove-buffer . helm-persp-buffer-list-bridge)))
(defclass helm-persp-free-buffers-source (helm-source-buffers)
((buffer-list
:initarg :buffer-list
:initform #'(lambda () (mapcar #'buffer-name (persp-buffer-list-restricted nil 3)))
:custom function
:documentation
" A function with no arguments to create buffer list.")))
(defvar helm-source-persp-free-buffers
(helm-make-source "Free buffers"
'helm-persp-free-buffers-source
:fuzzy-match t))
(defun helm-persp-buffers-list--init ()
(let* ((buffers (funcall (helm-attr 'buffer-list)))
(result (cl-loop for b in buffers
maximize (length b) into len-buf
maximize (length (with-current-buffer b
(format-mode-line mode-name)))
into len-mode
finally return (cons len-buf len-mode))))
(unless (default-value 'helm-buffer-max-length)
(helm-set-local-variable 'helm-buffer-max-length (car result)))
(unless (default-value 'helm-buffer-max-len-mode)
(helm-set-local-variable 'helm-buffer-max-len-mode (cdr result)))
(helm-attrset 'candidates buffers)))
(defclass helm-persp-buffers-source (helm-source-buffers)
((buffer-list
:initarg :buffer-list
:initform #'(lambda () (mapcar #'buffer-name (persp-buffers (helm-attr 'persp))))
:custom function
:documentation
" A function with no arguments to create buffer list.")
(persp
:initarg :persp
:initform (get-current-persp))
(init :initform #'helm-persp-buffers-list--init)))
(defvar helm-persp-sources-list '(helm-source-persp-free-buffers))
(defvar helm-persp-source-name-prefix "helm-source-persp-buffers-list-")
(defmacro persp-helm--liftup-source (source-name)
`(progn
(setq helm-persp-sources-list
(cons ,source-name
(cl-delete ,source-name helm-persp-sources-list)))
(setq helm-mini-default-sources
(append helm-persp-sources-list
helm-mini-tail-sources))))
(defmacro persp-helm--soure-name-from-persp-name (pn)
`(intern (concat helm-persp-source-name-prefix ,pn)))
(add-hook 'persp-created-functions
#'(lambda (p ph)
(when (and (eq ph *persp-hash*) p)
(let* ((pn (persp-name p))
(source-name (persp-helm--soure-name-from-persp-name pn)))
(eval
`(defvar ,source-name
(helm-make-source ,(concat pn " buffers")
'helm-persp-buffers-source :persp ,p)))
(setq helm-persp-sources-list
(append helm-persp-sources-list (list source-name))))
(setq helm-mini-default-sources
(append helm-persp-sources-list
helm-mini-tail-sources)))))
;; (add-hook 'persp-before-switch-functions
;; #'(lambda (next-pn)
;; (let ((p (get-current-persp)))
;; (when p
;; (persp-helm--liftup-source 'helm-source-persp-free-buffers)))))
;; (add-hook 'persp-activated-hook
;; #'(lambda ()
;; (let ((p (get-current-persp)))
;; (when p
;; (let* ((pn (persp-name p))
;; (source-name (intern (concat helm-persp-source-name-prefix pn))))
;; (persp-helm--liftup-source source-name))))))
(add-hook 'persp-before-kill-functions
#'(lambda (p)
(when p
(let* ((pn (persp-name p))
(source-name (persp-helm--soure-name-from-persp-name pn)))
(setq helm-persp-sources-list
(cl-delete source-name helm-persp-sources-list))
(setq helm-mini-default-sources
(append helm-persp-sources-list
helm-mini-tail-sources))
(makunbound source-name)))))
(add-hook 'persp-mode-hook #'(lambda ()
(if persp-mode
(persp-helm-setup-bridge)
(persp-helm-destroy-bridge))))
(defun helm-persp-mini ()
(interactive)
(persp-helm--liftup-source 'helm-source-persp-free-buffers)
(let* ((cbuf (current-buffer))
(cbn (buffer-name cbuf)))
(let ((persp (get-current-persp)))
(when (and persp (persp-contain-buffer-p cbuf persp))
(let ((source-name (persp-helm--soure-name-from-persp-name (persp-name persp))))
(persp-helm--liftup-source source-name))))
(or
(helm :sources helm-mini-default-sources
:ff-transformer-show-only-basename nil
:fuzzy-match helm-mode-fuzzy-match
:buffer "*helm persp mini*"
:keymap helm-buffer-map
:truncate-lines helm-buffers-truncate-lines
:default cbn
:preselect (substring cbn 0 (min (string-width cbn) helm-buffer-max-length)))
(helm-mode--keyboard-quit))))
(defun helm-persp-buffer-list-bridge
(prompt _collection &optional test _require-match init hist default _inherit-im name buffer)
(persp-helm--liftup-source 'helm-source-persp-free-buffers)
(let ((persp (get-current-persp)))
(when (and persp (persp-contain-buffer-p (current-buffer) persp))
(let ((source-name (persp-helm--soure-name-from-persp-name (persp-name persp))))
(persp-helm--liftup-source source-name))))
(let ((deflt (or default "")))
(or
(helm :sources helm-persp-sources-list
:fuzzy-match helm-mode-fuzzy-match
:prompt prompt
:buffer buffer
:input init
:history hist
:resume 'noresume
:keymap helm-buffer-map
:truncate-lines helm-buffers-truncate-lines
:default deflt
:preselect (substring deflt 0 (min (string-width deflt) helm-buffer-max-length)))
(helm-mode--keyboard-quit))))
(defun persp-helm-setup-bridge ()
(setq helm-completing-read-handlers-alist
(append helm-persp-completing-read-handlers
helm-completing-read-handlers-alist))
(global-set-key (kbd "C-x b") #'helm-persp-mini))
(defun persp-helm-destroy-bridge ()
(setq helm-mini-default-sources
(cons
'helm-source-buffers-list
helm-mini-tail-sources))
(dolist (it helm-persp-completing-read-handlers)
(setq helm-completing-read-handlers-alist
(delete it helm-completing-read-handlers-alist)))
(global-set-key (kbd "C-x b") #'helm-mini))
(when (bound-and-true-p persp-mode)
(persp-helm-setup-bridge))))
(with-eval-after-load "persp-mode"
(with-eval-after-load "helm-mode"
(defun helm-buffers-toggle-persp-filter ()
(interactive)
(with-helm-alive-p
(let ((filter-attrs (helm-attr 'candidate-transformer
helm-source-persp-buffers)))
(if (memq #'helm-persp-buffers-filter-transformer filter-attrs)
(progn
(helm-attrset 'candidate-transformer
(delq #'helm-persp-buffers-filter-transformer
filter-attrs)
helm-source-persp-buffers t)
(helm-attrset 'name
"Buffers"
helm-source-persp-buffers t)
(setq helm-persp-filtered-buffers-cache nil))
(helm-attrset 'candidate-transformer
(cons #'helm-persp-buffers-filter-transformer
filter-attrs)
helm-source-persp-buffers t)
(helm-attrset 'name
"Current perspective buffers"
helm-source-persp-buffers t))
(helm-force-update))))
(put 'helm-buffers-toggle-persp-filter 'helm-only t)
(define-key helm-buffer-map
persp-toggle-read-persp-filter-keys #'helm-buffers-toggle-persp-filter)
(defvar helm-persp-filtered-buffers-cache nil)
(defun helm-persp-buffers-filter-transformer (candidates)
(setq helm-persp-filtered-buffers-cache nil)
(let* ((persp (get-current-persp))
(ret
(cl-remove-if-not #'(lambda (bn)
(let* ((ret (persp-contain-buffer-p (get-buffer bn) persp)))
(unless ret
(push bn helm-persp-filtered-buffers-cache))
ret))
candidates)))
ret))
(defclass helm-persp-buffers-source (helm-source-buffers)
((buffer-list
:initarg :buffer-list
:initform #'(lambda () (mapcar #'buffer-name (buffer-list)))
:custom function
:documentation
" A function with no arguments to create buffer list.")
(cleanup :initform #'(lambda () (setq helm-persp-filtered-buffers-cache nil
helm-buffers-list-cache nil)))
(candidate-transformer :initform '(helm-persp-buffers-filter-transformer))))
(defvar helm-source-persp-buffers
(helm-make-source "Current perspective buffers"
'helm-persp-buffers-source
:fuzzy-match t))
(defclass helm-persp-filtered-buffers-source (helm-source-buffers)
((candidates :initform #'(lambda ()
(if helm-persp-filtered-buffers-cache
helm-persp-filtered-buffers-cache
(setq helm-persp-filtered-buffers-cache
(mapcar #'buffer-name (persp-buffer-list-restricted nil 1))))))
(cleanup :initform #'(lambda () (setq helm-persp-filtered-buffers-cache nil)))))
(defvar helm-source-persp-filtered-buffers
(helm-make-source "Other buffers"
'helm-persp-filtered-buffers-source
:fuzzy-match t))
(defun helm-persp-buffer-list-bridge
(prompt _collection &optional test _require-match init hist default _inherit-im name buffer)
(let ((dflt (or default ""))
(cbuf (current-buffer))
helm-candidate-number-limit)
(or
(helm :sources (cond
((eq this-command 'persp-add-buffer) '(helm-source-persp-filtered-buffers))
((eq this-command 'persp-remove-buffer) '(helm-source-persp-buffers))
(t '(helm-source-persp-buffers helm-source-persp-filtered-buffers)))
:fuzzy-match helm-mode-fuzzy-match
:prompt prompt
:buffer buffer
:input init
:history hist
:resume 'noresume
:keymap helm-buffer-map
:truncate-lines helm-buffers-truncate-lines
:default dflt
:preselect #'(lambda ()
(if (and (eq this-command 'persp-temporarily-display-buffer)
(persp-contain-buffer-p cbuf))
(helm-next-source)
(helm-mark-current-line)
(let ((buffer-name-truncated-regexp (helm-buffers--quote-truncated-buffer cbuf))
(start (point)) mp)
(helm-awhile (re-search-forward buffer-name-truncated-regexp nil t)
(when (helm-pos-header-line-p) (forward-line 1))
(helm-mark-current-line)
(when (eq cbuf (helm-get-selection)) (cl-return (setq mp it))))
(goto-char (or mp start))
(helm-mark-current-line)))))
(helm-mode--keyboard-quit))))
(defvar helm-persp-mini-default-sources
(cons 'helm-source-persp-buffers
(cons 'helm-source-persp-filtered-buffers
(remove 'helm-source-buffers-list helm-mini-default-sources))))
(defun helm-persp-mini ()
(interactive)
(let* ((cbuf (current-buffer))
(cbuf-name (buffer-name cbuf))
helm-candidate-number-limit)
(or
(helm :sources helm-persp-mini-default-sources
:ff-transformer-show-only-basename nil
:fuzzy-match helm-mode-fuzzy-match
:buffer "*helm persp mini*"
:keymap helm-buffer-map
:truncate-lines helm-buffers-truncate-lines
:default cbuf-name
:preselect #'(lambda ()
(let ((buffer-name-truncated-regexp (helm-buffers--quote-truncated-buffer cbuf))
(start (point)) mp)
(helm-awhile (re-search-forward buffer-name-truncated-regexp nil t)
(when (helm-pos-header-line-p) (forward-line 1))
(helm-mark-current-line)
(when (eq cbuf (helm-get-selection)) (cl-return (setq mp it))))
(goto-char (or mp start))
(helm-mark-current-line))))
(helm-mode--keyboard-quit))))
(global-set-key (kbd "C-x b") #'helm-persp-mini)
(setq helm-completing-read-handlers-alist
(append '((switch-to-buffer . helm-persp-buffer-list-bridge)
(persp-switch-to-buffer . helm-persp-buffer-list-bridge)
(kill-buffer . helm-persp-buffer-list-bridge)
(persp-kill-buffer . helm-persp-buffer-list-bridge)
(persp-temporarily-display-buffer . helm-persp-buffer-list-bridge)
(persp-add-buffer . helm-persp-buffer-list-bridge)
(persp-remove-buffer . helm-persp-buffer-list-bridge))
helm-completing-read-handlers-alist))))
(with-eval-after-load "persp-mode"
(defun persp-remove-killed-buffers ()
(interactive)
(mapc #'(lambda (p)
(when p
(setf (persp-buffers p)
(delete-if-not #'buffer-live-p
(persp-buffers p)))))
(persp-persps)))
(defvar persp-trace-buffers-hash (make-hash-table :test #'equal))
(add-hook 'persp-renamed-functions
#'(lambda (persp old-name new-name)
(let ((bufs (gethash old-name persp-trace-buffers-hash)))
(remhash old-name persp-trace-buffers-hash)
(puthash new-name bufs persp-trace-buffers-hash))))
(add-hook 'persp-before-kill-functions
#'(lambda (persp)
(remhash (safe-persp-name persp) persp-trace-buffers-hash)))
(add-hook 'persp-created-functions
#'(lambda (persp phash)
(when (eq phash *persp-hash*)
(puthash (safe-persp-name persp) nil persp-trace-buffers-hash))))
(defun persp--check-for-killed-buffers (&optional persp)
(when persp-mode
(if persp
(let ((known-buffers (append (gethash (persp-name persp) persp-trace-buffers-hash) nil)))
(dolist (buf (persp-buffers persp))
(if (not (buffer-live-p buf))
(message "[persp-mode] Warning: Found killed buffer in the %s perspective."
(persp-name persp))
(setq known-buffers (delete (buffer-name buf) known-buffers))))
(when known-buffers
(message "[persp-mode] Warning: These %s buffers was killed, but not removed from the %s perspective"
known-buffers (persp-name persp))))
(mapc #'persp--check-for-killed-buffers (delq nil (persp-persps))))))
(defun* persp-add-buffer-after-adv (buff-or-name &optional persp &rest _rargs)
(when persp
(let* ((buf (get-buffer buff-or-name))
(buf-name (buffer-name buf))
(known-buffers (gethash (persp-name persp) persp-trace-buffers-hash)))
(when (and (memq buf (persp-buffers persp))
(not (member buf-name known-buffers)))
(puthash (persp-name persp) (cons buf-name known-buffers) persp-trace-buffers-hash)))
(persp--check-for-killed-buffers)))
(defun* persp-remove-buffer-after-adv (buff-or-name &optional persp &rest _rargs)
(when persp
(puthash (persp-name persp)
(delete (buffer-name (get-buffer buff-or-name))
(gethash (persp-name persp) persp-trace-buffers-hash))
persp-trace-buffers-hash)
(persp--check-for-killed-buffers)))
(advice-add #'persp-add-buffer :after #'persp-add-buffer-after-adv)
(advice-add #'#'persp--remove-buffer-1 :after #'persp-remove-buffer-after-adv)
(run-at-time t 30 #'persp--check-for-killed-buffers))
(with-eval-after-load "persp-mode"
(require 'erc)
(with-eval-after-load "erc"
(def-persp-buffer-save/load :mode 'erc-mode :tag-symbol 'def-erc-server
:save-vars '("^erc-session-.+" "^erc-server-.+")
:save-function #'(lambda (buffer tag lvars)
(if (get-buffer-process buffer)
(progn
(push (cons 'persp-erc-chans
(mapcar #'buffer-name
(erc-channel-list (get-buffer-process buffer))))
lvars)
(push (cons 'persp-erc-persp-name (car (buffer-local-value
'persp-buffer-in-persps
buffer)))
lvars)
(list tag (buffer-name buffer) lvars))
'skip))
:after-load-function
#'(lambda (erc-buf &rest _other)
(lexical-let (chans erc-persp-name erc-persp
(erc-buf erc-buf) initial-persp erc-window
persp-erc-after-connect-lambda persp-erc-join-lambda)
(setq persp-erc-after-connect-lambda
#'(lambda (ntwrk nck)
(if (and (window-live-p erc-window) (eq erc-buf (window-buffer erc-window)))
(select-window erc-window)
(setq erc-window (selected-window))
(set-window-buffer erc-window erc-buf))
(add-hook 'erc-server-JOIN-functions persp-erc-join-lambda t)
(mapc #'(lambda (chan)
(with-current-buffer erc-buf
(persp-add-buffer (erc-join-channel chan nil) erc-persp)))
chans)
(remove-hook 'erc-after-connect persp-erc-after-connect-lambda)
nil)
persp-erc-join-lambda
#'(lambda (proc parsed)
(if chans
(when (eq proc (get-buffer-process erc-buf))
(let ((chan (erc-response.contents parsed)))
(when (member chan chans)
(setq chans (delete chan chans))
(when erc-persp (persp-add-buffer chan erc-persp))
(unless chans
(remove-hook 'erc-server-JOIN-functions persp-erc-join-lambda)
;; (persp-frame-switch (safe-persp-name initial-persp))
))))
(remove-hook 'erc-server-JOIN-functions persp-erc-join-lambda))
nil))
(with-current-buffer erc-buf
(setq chans persp-erc-chans
erc-persp-name persp-erc-persp-name))
(when erc-persp-name
(setq erc-persp (persp-get-by-name erc-persp-name))
(setq initial-persp (get-current-persp))
(persp-frame-switch erc-persp-name))
(setq erc-window (get-buffer-window erc-buf (selected-frame)))
(if (window-live-p erc-window)
(select-window erc-window)
(setq erc-window (selected-window))
(set-window-buffer erc-window erc-buf))
(add-hook 'erc-after-connect persp-erc-after-connect-lambda t)
(with-current-buffer erc-buf
(erc-server-reconnect)
(persp-special-last-buffer-make-current)))))))
(with-eval-after-load "persp"
(add-to-list 'persp-save-buffer-functions
#'(lambda (b)
(when (eq 'inferior-python-mode (buffer-local-value 'major-mode b))
`(def-inferior-python-buffer ,(buffer-name b)
,(let ((process (get-buffer-process b)))
(if process
(progn
(python-shell-send-string "import os" process)
(python-shell-send-string-no-output "os.getcwd()" process))
(concat "'" (buffer-local-value 'default-directory b) "'")))))))
(add-to-list 'persp-load-buffer-functions
#'(lambda (savelist)
(when (eq (car savelist) 'def-inferior-python-buffer)
(destructuring-bind (bname dir) (cdr savelist)
(run-python nil nil nil)
(with-current-buffer (python-shell-get-buffer)
(rename-buffer bname)
(cd dir)
(python-shell-send-string "import os")
(python-shell-send-string (format "os.chdir(%s)" dir))
(current-buffer)))))))
(with-eval-after-load "persp-mode"
(defun persp-iswitchb-completing-read
(prompt choices
&optional predicate require-match
initial-input hist def inherit-input-method)
"Support for the `iswitchb-mode'."
(let ((iswitchb-make-buflist-hook
#'(lambda () (setq iswitchb-temp-buflist choices))))
(iswitchb-read-buffer prompt def require-match initial-input nil)))
(defun persp-iswitchb-setup ()
(setq persp-disable-buffer-restriction-once nil))
(defun persp-iswitchb-define-mode-map ()
(define-key
iswitchb-mode-map
persp-toggle-read-persp-filter-keys
#'iswitchb-toggle-persp-filter))
(defun persp-iswitchb-filter-buflist ()
"Support for the `iswitchb-mode'."
(setq iswitchb-temp-buflist
(if persp-disable-buffer-restriction-once
(persp-buffer-list-restricted nil -1 nil)
(persp-buffer-list-restricted))))
(defun iswitchb-toggle-persp-filter ()
(interactive)
(setq persp-disable-buffer-restriction-once
(not persp-disable-buffer-restriction-once))
(iswitchb-make-buflist iswitchb-default)
(setq iswitchb-rescan t))
(defun persp-set-iswitchb-hooks (&optional opt)
(if opt
(progn
(add-hook 'iswitchb-minibuffer-setup-hook #'persp-iswitchb-setup)
(add-hook 'iswitchb-make-buflist-hook #'persp-iswitchb-filter-buflist)
(add-hook 'iswitchb-define-mode-map-hook #'persp-iswitchb-define-mode-map))
(remove-hook 'iswitchb-minibuffer-setup-hook #'persp-iswitchb-setup)
(remove-hook 'iswitchb-make-buflist-hook #'persp-iswitchb-filter-buflist)
(remove-hook 'iswitchb-define-mode-map-hook #'persp-iswitchb-define-mode-map)))
(persp-set-iswitchb-hooks t)
(setq persp-interactive-completion-function #'persp-iswitchb-completing-read))
(with-eval-after-load "persp-mode"
(with-eval-after-load "ivy"
(add-hook 'ivy-ignore-buffers
#'(lambda (b)
(when persp-mode
(let ((persp (get-current-persp)))
(if persp
(not (persp-contain-buffer-p b persp))
nil)))))
(setq ivy-sort-functions-alist
(append ivy-sort-functions-alist
'((persp-kill-buffer . nil)
(persp-remove-buffer . nil)
(persp-add-buffer . nil)
(persp-switch . nil)
(persp-window-switch . nil)
(persp-frame-switch . nil))))))
;; Simplified variant. Add only current perspective group.
(with-eval-after-load "ibuffer"
(require 'ibuf-ext)
(define-ibuffer-filter persp
"Toggle current view to buffers of current perspective."
(:description "persp-mode"
:reader (persp-prompt nil nil (safe-persp-name (get-frame-persp)) t))
(find buf (safe-persp-buffers (persp-get-by-name qualifier))))
(defun persp-add-ibuffer-group ()
(let ((perspslist (list
(list (safe-persp-name (get-frame-persp))
(cons 'persp (safe-persp-name (get-frame-persp)))))))
(setq ibuffer-saved-filter-groups
(delete* "persp-mode" ibuffer-saved-filter-groups
:test 'string= :key 'car))
(push
(cons "persp-mode" perspslist)
ibuffer-saved-filter-groups)))
(add-hook 'ibuffer-mode-hook
#'(lambda ()
(persp-add-ibuffer-group)
(ibuffer-switch-to-saved-filter-groups "persp-mode"))))
;; Shows groups for all perspectives. But can't show same buffer in multiple groups.
(with-eval-after-load "ibuffer"
(require 'ibuf-ext)
(define-ibuffer-filter persp
"Toggle current view to buffers of current perspective."
(:description "persp-mode"
:reader (persp-prompt nil nil (safe-persp-name (get-frame-persp)) t))
(find buf (safe-persp-buffers (persp-get-by-name qualifier))))
(defun persp-add-ibuffer-group ()
(let ((perspslist (mapcar #'(lambda (pn)
(list pn (cons 'persp pn)))
(nconc
(delete* persp-nil-name
(persp-names-current-frame-fast-ordered)
:test 'string=)
(list persp-nil-name)))))
(setq ibuffer-saved-filter-groups
(delete* "persp-mode" ibuffer-saved-filter-groups
:test 'string= :key 'car))
(push
(cons "persp-mode" perspslist)
ibuffer-saved-filter-groups)))
(defun persp-ibuffer-visit-buffer ()
(let ((buf (ibuffer-current-buffer t))
(persp-name (get-text-property
(line-beginning-position) 'ibuffer-filter-group)))
(persp-switch persp-name)
(switch-to-buffer buf)))
(define-key ibuffer-mode-map (kbd "RET") 'persp-ibuffer-visit-buffer)
(add-hook 'ibuffer-mode-hook
#'(lambda ()
(persp-add-ibuffer-group)
(ibuffer-switch-to-saved-filter-groups "persp-mode"))))
(with-eval-after-load "persp-mode"
(add-hook 'persp-before-switch-functions
#'(lambda (new-persp-name w-or-f)
(let ((cur-persp-name (safe-persp-name (get-current-persp))))
(when (member cur-persp-name persp-names-cache)
(setq persp-names-cache
(cons cur-persp-name
(delete cur-persp-name persp-names-cache)))))))
(add-hook 'persp-renamed-functions
#'(lambda (persp old-name new-name)
(setq persp-names-cache
(cons new-name (delete old-name persp-names-cache)))))
(add-hook 'persp-before-kill-functions
#'(lambda (persp)
(setq persp-names-cache
(delete (safe-persp-name persp) persp-names-cache))))
(add-hook 'persp-created-functions
#'(lambda (persp phash)
(when (and (eq phash *persp-hash*)
(not (member (safe-persp-name persp)
persp-names-cache)))
(setq persp-names-cache
(cons (safe-persp-name persp) persp-names-cache))))))
(with-eval-after-load "persp-mode"
(require 'multi-term)
(with-eval-after-load "multi-term"
(persp-def-buffer-save/load
:mode 'term-mode :tag-symbol 'def-multiterm-buffer
:predicate #'(lambda (b) (memq b multi-term-buffer-list))
:save-vars '(default-directory)
:save-function #'(lambda (b tag lvars)
(let ((bname (buffer-name b)))
(push
(cons 'multi-term-dedicated-bufferp
(eq b multi-term-dedicated-buffer))
lvars)
(push
(cons 'multi-term-buffer-shell
(car (last (process-command
(get-buffer-process b)))))
lvars)
(list tag bname lvars)))
:after-load-function
#'(lambda (b &rest _)
(with-current-buffer b
(let ((shell-name (or multi-term-buffer-shell
multi-term-program
(getenv "SHELL")
(getenv "ESHELL")
"/bin/sh"))
(term-name (buffer-name (current-buffer))))
(cd (or default-directory
(expand-file-name multi-term-default-dir)))
(if multi-term-program-switches
(term-ansi-make-term term-name shell-name nil
multi-term-program-switches)
(term-ansi-make-term term-name shell-name)))
(setq multi-term-buffer-list (nconc multi-term-buffer-list (list b)))
(multi-term-internal))))))
(with-eval-after-load "olivetti"
(with-eval-after-load "persp-mode"
(defvar persp-olivetti-buffers-backup nil)
(add-hook 'persp-before-deactivate-functions
#'(lambda (fow)
(dolist (b (mapcar #'window-buffer
(window-list (selected-frame)
'no-minibuf)))
(with-current-buffer b
(when (eq 'olivetti-split-window-sensibly
split-window-preferred-function)
(push b persp-olivetti-buffers-backup)
(remove-hook 'window-configuration-change-hook
#'olivetti-set-environment t)
(setq-local split-window-preferred-function nil)
(olivetti-reset-all-windows))))))
(add-hook 'persp-activated-functions
#'(lambda (fow)
(dolist (b persp-olivetti-buffers-backup)
(with-current-buffer b
(setq-local split-window-preferred-function
'olivetti-split-window-sensibly)
(add-hook 'window-configuration-change-hook
#'olivetti-set-environment nil t)))
(setq persp-olivetti-buffers-backup nil)))))
(with-eval-after-load "persp-mode"
(defvar persp-mode-projectile-bridge-before-switch-selected-window-buffer nil)
;; (setq persp-add-buffer-on-find-file 'if-not-autopersp)
(persp-def-auto-persp "projectile"
:parameters '((dont-save-to-file . t)
(persp-mode-projectile-bridge . t))
:hooks '(projectile-before-switch-project-hook
projectile-after-switch-project-hook
projectile-find-file-hook
find-file-hook)
:dyn-env '((after-switch-to-buffer-adv-suspend t))
:switch 'frame
:predicate
#'(lambda (buffer &optional state)
(if (eq 'projectile-before-switch-project-hook
(alist-get 'hook state))
state
(and
projectile-mode
(buffer-live-p buffer)
(buffer-file-name buffer)
;; (not git-commit-mode)
(projectile-project-p)
(or state t))))
:get-name
#'(lambda (state)
(if (eq 'projectile-before-switch-project-hook
(alist-get 'hook state))
state
(push (cons 'persp-name
(concat "p) "
(with-current-buffer (alist-get 'buffer state)
(projectile-project-name))))
state)
state))
:on-match
#'(lambda (state)
(let ((hook (alist-get 'hook state))
(persp (alist-get 'persp state))
(buffer (alist-get 'buffer state)))
(case hook
(projectile-before-switch-project-hook
(let ((win (if (minibuffer-window-active-p (selected-window))
(minibuffer-selected-window)
(selected-window))))
(when (window-live-p win)
(setq persp-mode-projectile-bridge-before-switch-selected-window-buffer
(window-buffer win)))))
(projectile-after-switch-project-hook
(when (buffer-live-p
persp-mode-projectile-bridge-before-switch-selected-window-buffer)
(let ((win (selected-window)))
(unless (eq (window-buffer win)
persp-mode-projectile-bridge-before-switch-selected-window-buffer)
(set-window-buffer
win persp-mode-projectile-bridge-before-switch-selected-window-buffer)))))
(find-file-hook
(setcdr (assq :switch state) nil)))
(if (case hook
(projectile-before-switch-project-hook nil)
(t t))
(persp--auto-persp-default-on-match state)
(setcdr (assq :after-match state) nil)))
state)
:after-match
#'(lambda (state)
(when (eq 'find-file-hook (alist-get 'hook state))
(run-at-time 0.5 nil
#'(lambda (buf persp)
(when (and (eq persp (get-current-persp))
(not (eq buf (window-buffer (selected-window)))))
;; (switch-to-buffer buf)
(persp-add-buffer buf persp t nil)))
(alist-get 'buffer state)
(get-current-persp)))
(persp--auto-persp-default-after-match state)))
;; (add-hook 'persp-after-load-state-functions
;; #'(lambda (&rest args) (persp-auto-persps-pickup-buffers)) t)
)
(persp-def-buffer-save/load
:mode 'shell-mode
:mode-restore-function #'(lambda (_mode) (shell)) ; or #'identity if you do not want to start shell process
:tag-symbol 'def-shell
:save-vars '(major-mode default-directory))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment