mirror of
https://github.com/SqrtMinusOne/dotfiles.git
synced 2025-12-10 19:23:03 +03:00
feat(emacs): rules for perspective & workspaces
This commit is contained in:
parent
86ed4185e1
commit
71c78397bb
4 changed files with 158 additions and 34 deletions
|
|
@ -1123,6 +1123,44 @@ influence of C1 on the result."
|
|||
"m" #'my/persp-move-window-and-switch
|
||||
"f" #'my/persp-copy-window-and-switch))
|
||||
|
||||
(setq my/perspective-assign-alist '())
|
||||
|
||||
(defun my/perspective-assign ()
|
||||
(when-let* ((rule (alist-get major-mode my/perspective-assign-alist)))
|
||||
(let ((workspace-index (car rule))
|
||||
(persp-name (cadr rule))
|
||||
(buffer (current-buffer)))
|
||||
(if (fboundp #'perspective-exwm-assign-window)
|
||||
(progn
|
||||
(perspective-exwm-assign-window
|
||||
:workspace-index workspace-index
|
||||
:persp-name persp-name)
|
||||
(when workspace-index
|
||||
(exwm-workspace-switch workspace-index))
|
||||
(when persp-name
|
||||
(persp-switch persp-name)))
|
||||
(with-perspective persp-name
|
||||
(persp-set-buffer buffer))
|
||||
(persp-switch-to-buffer buffer)))))
|
||||
|
||||
(add-hook 'after-change-major-mode-hook #'my/perspective-assign)
|
||||
|
||||
(defmacro my/persp-add-rule (&rest body)
|
||||
(declare (indent 0))
|
||||
(unless (= (% (length body) 3) 0)
|
||||
(error "Malformed body in my/persp-add-rule"))
|
||||
(let (result)
|
||||
(while body
|
||||
(let ((major-mode (pop body))
|
||||
(workspace-index (pop body))
|
||||
(persp-name (pop body)))
|
||||
(push
|
||||
`(add-to-list 'my/perspective-assign-alist
|
||||
'(,major-mode . (,workspace-index ,persp-name)))
|
||||
result)))
|
||||
`(progn
|
||||
,@result)))
|
||||
|
||||
(defmacro my/command-in-persp (command-name persp-name workspace-index &rest args)
|
||||
`'((lambda ()
|
||||
(interactive)
|
||||
|
|
@ -4118,7 +4156,11 @@ With ARG, repeats or can move backward if negative."
|
|||
:if (not my/remote-server)
|
||||
:commands (elfeed)
|
||||
:init
|
||||
(my-leader-def "ae" (my/command-in-persp "elfeed" "elfeed" 0 (elfeed-summary)))
|
||||
(my-leader-def "ae" #'elfeed-summary)
|
||||
(my/persp-add-rule
|
||||
elfeed-summary-mode 0 "elfeed"
|
||||
elfeed-search-mode 0 "elfeed"
|
||||
elfeed-show-mode 0 "elfeed")
|
||||
(setq shr-max-image-proportion 0.5)
|
||||
:config
|
||||
(setq elfeed-db-directory "~/.elfeed")
|
||||
|
|
@ -4702,16 +4744,19 @@ by the `my/elfeed-youtube-subtitles' function."
|
|||
(my-leader-def
|
||||
:infix "as"
|
||||
"" '(:which-key "emms")
|
||||
"s" (my/command-in-persp "emms" "EMMS" 0 (emms-smart-browse))
|
||||
"b" 'emms-browser
|
||||
"p" 'emms-pause
|
||||
"q" 'emms-stop
|
||||
"h" 'emms-previous
|
||||
"l" 'emms-next
|
||||
"u" 'emms-player-mpd-connect
|
||||
"ww" 'emms-lyrics
|
||||
"wb" 'emms-lyrics-toggle-display-on-minibuffer
|
||||
"wm" 'emms-lyrics-toggle-display-on-modeline)
|
||||
"s" #'emms-smart-browse
|
||||
"b" #'emms-browser
|
||||
"p" #'emms-pause
|
||||
"q" #'emms-stop
|
||||
"h" #'emms-previous
|
||||
"l" #'emms-next
|
||||
"u" #'emms-player-mpd-connect
|
||||
"ww" #'emms-lyrics
|
||||
"wb" #'emms-lyrics-toggle-display-on-minibuffer
|
||||
"wm" #'emms-lyrics-toggle-display-on-modeline)
|
||||
(my/persp-add-rule
|
||||
emms-browser-mode 0 "EMMS"
|
||||
emms-playlist-mode 0 "EMMS")
|
||||
(setq emms-mode-line-icon-enabled-p nil)
|
||||
:config
|
||||
(require 'emms-setup)
|
||||
|
|
@ -4975,7 +5020,9 @@ by the `my/elfeed-youtube-subtitles' function."
|
|||
:straight t
|
||||
:commands (znc-erc)
|
||||
:init
|
||||
(my-leader-def "ai" (my/command-in-persp "erc" "ERC" 0 (znc-erc)))
|
||||
(my-leader-def "ai" #'znc-erc)
|
||||
(my/persp-add-rule
|
||||
erc-mode 0 "ERC")
|
||||
:config
|
||||
(setq znc-servers
|
||||
`(("sqrtminusone.xyz" 6697 t
|
||||
|
|
@ -5159,10 +5206,7 @@ by the `my/elfeed-youtube-subtitles' function."
|
|||
:straight t
|
||||
:commands (prodigy)
|
||||
:init
|
||||
(my-leader-def "aP" (my/command-in-persp
|
||||
"deploy" "prodigy" nil
|
||||
(prodigy)
|
||||
(delete-other-windows)))
|
||||
(my-leader-def "aP" #'prodigy)
|
||||
:config
|
||||
(general-define-key
|
||||
:states '(normal)
|
||||
|
|
|
|||
|
|
@ -49,6 +49,12 @@
|
|||
"" '(:which-key "notmuch")
|
||||
"m" (my/command-in-persp "notmuch" "mail" 0 (notmuch)))
|
||||
|
||||
(my/persp-add-rule
|
||||
notmuch-hello-mode 0 "mail"
|
||||
notmuch-search-mode 0 "mail"
|
||||
notmuch-tree-mode 0 "mail"
|
||||
notmuch-message-mode 0 "mail")
|
||||
|
||||
(setq notmuch-saved-searches
|
||||
'((:name "drafts" :query "tag:draft")
|
||||
(:name "main (inbox)" :query "tag:main AND tag:inbox")
|
||||
|
|
|
|||
102
Emacs.org
102
Emacs.org
|
|
@ -1783,9 +1783,67 @@ Add keybindings to the default map.
|
|||
"f" #'my/persp-copy-window-and-switch))
|
||||
#+end_src
|
||||
*** Automating perspectives
|
||||
I'd like to have various Emacs apps open up in their designated perspectives (also in their designated workspaces when I'm using EXWM).
|
||||
One thing I don't like about =perspective.el= is that it doesn't feature much (or any) capacity for automation. So out-of-the-box we're supposed to manually assign buffers to perspectives we want.
|
||||
|
||||
But we can cook some automation ourselves. First, let's define a variable with "rules":
|
||||
#+begin_src emacs-lisp
|
||||
(setq my/perspective-assign-alist '())
|
||||
#+end_src
|
||||
|
||||
One rule looks as follows:
|
||||
#+begin_example
|
||||
(major-mode workspace-index persp-name)
|
||||
#+end_example
|
||||
|
||||
And a function to act on these rules.
|
||||
#+begin_src emacs-lisp
|
||||
(defun my/perspective-assign ()
|
||||
(when-let* ((rule (alist-get major-mode my/perspective-assign-alist)))
|
||||
(let ((workspace-index (car rule))
|
||||
(persp-name (cadr rule))
|
||||
(buffer (current-buffer)))
|
||||
(if (fboundp #'perspective-exwm-assign-window)
|
||||
(progn
|
||||
(perspective-exwm-assign-window
|
||||
:workspace-index workspace-index
|
||||
:persp-name persp-name)
|
||||
(when workspace-index
|
||||
(exwm-workspace-switch workspace-index))
|
||||
(when persp-name
|
||||
(persp-switch persp-name)))
|
||||
(with-perspective persp-name
|
||||
(persp-set-buffer buffer))
|
||||
(persp-switch-to-buffer buffer)))))
|
||||
#+end_src
|
||||
|
||||
If EXWM is available, then so is mine =perspective-exwm= package that features a convenient procedure called =perspective-exwm-assign-window=. If not, we just work with perspectives.
|
||||
|
||||
Now, we have to put this function somewhere, and =after-change-major-mode-hook= seems like a perfect place for it.
|
||||
#+begin_src emacs-lisp
|
||||
(add-hook 'after-change-major-mode-hook #'my/perspective-assign)
|
||||
#+end_src
|
||||
|
||||
And here is a simple macro to add rules to the list.
|
||||
#+begin_src emacs-lisp
|
||||
(defmacro my/persp-add-rule (&rest body)
|
||||
(declare (indent 0))
|
||||
(unless (= (% (length body) 3) 0)
|
||||
(error "Malformed body in my/persp-add-rule"))
|
||||
(let (result)
|
||||
(while body
|
||||
(let ((major-mode (pop body))
|
||||
(workspace-index (pop body))
|
||||
(persp-name (pop body)))
|
||||
(push
|
||||
`(add-to-list 'my/perspective-assign-alist
|
||||
'(,major-mode . (,workspace-index ,persp-name)))
|
||||
result)))
|
||||
`(progn
|
||||
,@result)))
|
||||
#+end_src
|
||||
|
||||
Also, the logic above works only for cases when the buffer is created. Occasionally, the packages themselves run =switch-to-buffer=, which screws both EXWM workspaces and perspectives; to work around that, I define a macro that runs a command in a given perspective and workspace.
|
||||
|
||||
So, here is a macro to run something in a given perspective in a given workspace. This is meant to be used in general.el keybindings.
|
||||
#+begin_src emacs-lisp
|
||||
(defmacro my/command-in-persp (command-name persp-name workspace-index &rest args)
|
||||
`'((lambda ()
|
||||
|
|
@ -1797,6 +1855,8 @@ So, here is a macro to run something in a given perspective in a given workspace
|
|||
,@args)
|
||||
:wk ,command-name))
|
||||
#+end_src
|
||||
|
||||
This is meant to be used in the definitions of =general.el=.
|
||||
* Programming
|
||||
** General setup
|
||||
*** Treemacs
|
||||
|
|
@ -5832,7 +5892,11 @@ Using my own fork until the modifications are merged into master.
|
|||
:if (not my/remote-server)
|
||||
:commands (elfeed)
|
||||
:init
|
||||
(my-leader-def "ae" (my/command-in-persp "elfeed" "elfeed" 0 (elfeed-summary)))
|
||||
(my-leader-def "ae" #'elfeed-summary)
|
||||
(my/persp-add-rule
|
||||
elfeed-summary-mode 0 "elfeed"
|
||||
elfeed-search-mode 0 "elfeed"
|
||||
elfeed-show-mode 0 "elfeed")
|
||||
(setq shr-max-image-proportion 0.5)
|
||||
:config
|
||||
(setq elfeed-db-directory "~/.elfeed")
|
||||
|
|
@ -6595,16 +6659,19 @@ References:
|
|||
(my-leader-def
|
||||
:infix "as"
|
||||
"" '(:which-key "emms")
|
||||
"s" (my/command-in-persp "emms" "EMMS" 0 (emms-smart-browse))
|
||||
"b" 'emms-browser
|
||||
"p" 'emms-pause
|
||||
"q" 'emms-stop
|
||||
"h" 'emms-previous
|
||||
"l" 'emms-next
|
||||
"u" 'emms-player-mpd-connect
|
||||
"ww" 'emms-lyrics
|
||||
"wb" 'emms-lyrics-toggle-display-on-minibuffer
|
||||
"wm" 'emms-lyrics-toggle-display-on-modeline)
|
||||
"s" #'emms-smart-browse
|
||||
"b" #'emms-browser
|
||||
"p" #'emms-pause
|
||||
"q" #'emms-stop
|
||||
"h" #'emms-previous
|
||||
"l" #'emms-next
|
||||
"u" #'emms-player-mpd-connect
|
||||
"ww" #'emms-lyrics
|
||||
"wb" #'emms-lyrics-toggle-display-on-minibuffer
|
||||
"wm" #'emms-lyrics-toggle-display-on-modeline)
|
||||
(my/persp-add-rule
|
||||
emms-browser-mode 0 "EMMS"
|
||||
emms-playlist-mode 0 "EMMS")
|
||||
(setq emms-mode-line-icon-enabled-p nil)
|
||||
:config
|
||||
(require 'emms-setup)
|
||||
|
|
@ -7003,7 +7070,9 @@ ZNC support. Seems to provide a few nice features for ZNC.
|
|||
:straight t
|
||||
:commands (znc-erc)
|
||||
:init
|
||||
(my-leader-def "ai" (my/command-in-persp "erc" "ERC" 0 (znc-erc)))
|
||||
(my-leader-def "ai" #'znc-erc)
|
||||
(my/persp-add-rule
|
||||
erc-mode 0 "ERC")
|
||||
:config
|
||||
(setq znc-servers
|
||||
`(("sqrtminusone.xyz" 6697 t
|
||||
|
|
@ -7257,10 +7326,7 @@ The actual service definitions are in my =~/.emacs.d/private.org=, which is encr
|
|||
:straight t
|
||||
:commands (prodigy)
|
||||
:init
|
||||
(my-leader-def "aP" (my/command-in-persp
|
||||
"deploy" "prodigy" nil
|
||||
(prodigy)
|
||||
(delete-other-windows)))
|
||||
(my-leader-def "aP" #'prodigy)
|
||||
:config
|
||||
(general-define-key
|
||||
:states '(normal)
|
||||
|
|
|
|||
8
Mail.org
8
Mail.org
|
|
@ -440,6 +440,14 @@ Root keybindings:
|
|||
"m" (my/command-in-persp "notmuch" "mail" 0 (notmuch)))
|
||||
#+end_src
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(my/persp-add-rule
|
||||
notmuch-hello-mode 0 "mail"
|
||||
notmuch-search-mode 0 "mail"
|
||||
notmuch-tree-mode 0 "mail"
|
||||
notmuch-message-mode 0 "mail")
|
||||
#+end_src
|
||||
|
||||
#+NAME: root_tags
|
||||
| Root tag | Prefix | Keybinding description |
|
||||
|-----------+--------+------------------------|
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue