From 7419450c9d1917ddecf12057fba43463efd22aac Mon Sep 17 00:00:00 2001 From: Kiana Sheibani Date: Mon, 26 Aug 2024 19:52:24 -0400 Subject: [PATCH] feat!: switch to fork of `winum` for numbering windows --- config.org | 152 ++++++++++++++++++++++++++++++++++++++++++++--------- pkgs/winum | 1 + 2 files changed, 128 insertions(+), 25 deletions(-) create mode 160000 pkgs/winum diff --git a/config.org b/config.org index 0702a9a..ad4d32b 100644 --- a/config.org +++ b/config.org @@ -948,7 +948,6 @@ We'll also enable a dedicated spell checking module using ~aspell~, as that seem Most of these are either defaults that come with Doom Emacs or just recommended, but here are the highlights: - ~vi-tilde-fringe~ because I like how it looks -- ~(window-select +numbers)~ because multiple windows are too inconvenient without an easy way to switch between them - ~file-templates~ and ~snippets~ because typing is hard - ~(format +onsave)~ because I don't want to have to remember to run a formatter - ~direnv~ because I'm a nix user @@ -977,7 +976,7 @@ ophints unicode (vc-gutter +pretty) vi-tilde-fringe -(window-select +numbers) +;;(window-select +numbers) workspaces ;;zen #+end_src @@ -1196,30 +1195,9 @@ The =auth-source-pass= module lets you use [[*Password Management][pass]] as a s #+call: confpkg() -*** Windows & Workspaces +*** Workspaces -I like using window numbers to navigate between splitscreen windows, but having to type =SPC w <#>= every time is annoying. Let's shorten that key sequence by 33%, and also throw in a convenient binding for switching to =treemacs=. - -#+begin_src emacs-lisp -(map! :leader - ;; Bind "SPC 0" to treemacs - ;; Map window bindings to "SPC 1" through "SPC 9" - "w 0" #'treemacs-select-window - :desc "Select project tree window" "0" #'treemacs-select-window - :desc "Select window 1" "1" #'winum-select-window-1 - :desc "Select window 2" "2" #'winum-select-window-2 - :desc "Select window 3" "3" #'winum-select-window-3 - :desc "Select window 4" "4" #'winum-select-window-4 - :desc "Select window 5" "5" #'winum-select-window-5 - :desc "Select window 6" "6" #'winum-select-window-6 - :desc "Select window 7" "7" #'winum-select-window-7 - :desc "Select window 8" "8" #'winum-select-window-8 - :desc "Select window 9" "9" #'winum-select-window-9) -#+end_src - -Now =SPC 1= will work equivalently to =SPC w 1=. Efficiency! - -I like to reorganize my workspaces, so we can also add bindings to change the workspace order. +I like to reorganize my workspaces, so we can add bindings to change the workspace order. #+begin_src emacs-lisp (map! :leader @@ -1591,6 +1569,8 @@ Now that we've enabled our preferred modules and done some basic configuration, corfu-min-width 25)) #+end_src +*** Omnicomplete Bindings + Before switching to Corfu, I got really used to Doom's omnicomplete bindings for various company backends. Doom unfortunately doesn't do this for CAPFs, so we'll have to do the work ourselves. #+begin_src emacs-lisp @@ -1605,6 +1585,15 @@ Before switching to Corfu, I got really used to Doom's omnicomplete bindings for :i "\\" #'cape-tex) #+end_src +*** Window Numbers + +Corfu's posframe buffer shouldn't be numbered by =winum=: + +#+begin_src emacs-lisp +(after! (corfu winum) + (push " *corfu*" winum-ignored-buffers)) +#+end_src + ** Eldoc #+call: confpkg("Pkg: eldoc") @@ -2398,6 +2387,119 @@ I've set my default Emacs shell to =bash=, since pointing Emacs to a non-POSIX s (setq-default vterm-shell (executable-find "fish"))) #+end_src +** Window Numbering + +#+call: confpkg("Pkg: winum") + +Emacs comes with a few standard commands for selecting different windows. These are mostly directional, allowing you to move your selection up, right, left or down from the current window. This is rather inconvenient when working with large amounts of windows, so the =winum= package allows you to assign a number to each window to make navigation easier. + +There's just one problem with =winum= for my purposes: Doom Emacs's popup management system. In Doom Emacs, popups are treated as separate from "real" windows, usually displayed on the edge of the frame and without a modeline. =winum= has no knowledge of popup windows, and assigns them numbers exactly the same as any other window, which is very confusing when popups are otherwise treated as separate. + +To solve this issue, I've written my own fork of =winum=: + +#+begin_src emacs-lisp :tangle packages.el +(package! winum :recipe (:local-repo "pkgs/winum")) +#+end_src + +This fork generalizes the window numbering system to support indexing windows with any Lisp object, instead of just integers. We can then index regular windows with integers ~N~, and popup windows with cons cells ~(popup . N)~, allowing us to number them separately. + +*** Configuration + +#+begin_src emacs-lisp +(use-package! winum + :after-call doom-switch-window-hook + :config + (setq winum-auto-setup-mode-line nil) + (winum-mode +1) + (map! :map evil-window-map + "0" #'winum-select-window-0-or-10 + "1" #'winum-select-window-1 + "2" #'winum-select-window-2 + "3" #'winum-select-window-3 + "4" #'winum-select-window-4 + "5" #'winum-select-window-5 + "6" #'winum-select-window-6 + "7" #'winum-select-window-7 + "8" #'winum-select-window-8 + "9" #'winum-select-window-9) + (map! :leader + :desc "Select window 1" "1" #'winum-select-window-1 + :desc "Select window 2" "2" #'winum-select-window-2 + :desc "Select window 3" "3" #'winum-select-window-3 + :desc "Select window 4" "4" #'winum-select-window-4 + :desc "Select window 5" "5" #'winum-select-window-5 + :desc "Select window 6" "6" #'winum-select-window-6 + :desc "Select window 7" "7" #'winum-select-window-7 + :desc "Select window 8" "8" #'winum-select-window-8 + :desc "Select window 9" "9" #'winum-select-window-9)) +#+end_src + +*** Popup Management + +With the basic config out of the way, we can implement popup-aware numbering by changing the ~winum-auto-assign-function~. + +#+begin_src emacs-lisp +(after! winum + (defun ~/winum-auto-assign (windows) + "Assign indices to windows, handling popup windows separately." + (let ((index 1) (popup-index 1)) + (dolist (w windows) + (if (+popup-window-p w) + (progn + (while (member (cons 'popup popup-index) + winum--assigned-indices) + (setq popup-index (1+ popup-index))) + (winum--assign w (cons 'popup popup-index)) + (setq popup-index (1+ popup-index))) + (while (member index winum--assigned-indices) + (setq index (1+ index))) + (winum--assign w index) + (setq index (1+ index)))))) + (setq winum-auto-assign-function #'~/winum-auto-assign)) +#+end_src + +For convenience, we can add functions to select a particular popup window: + +#+begin_src emacs-lisp +(map! :leader + "~" nil + :prefix ("~" . "popup") + :desc "Toggle last popup" + "~" #'+popup/toggle) + +(dolist (n (number-sequence 1 9)) + (let ((function (intern (format "+winum-select-popup-%s" n)))) + (eval + `(progn + (defun ,function (&optional arg) + ,(format "Jump to popup window %s. +If prefix ARG is given, delete the window instead of selecting it." n) + (interactive "P") + (if arg + (winum-delete-window-by-index '(popup . ,n)) + (winum-select-window-by-index '(popup . ,n)))) + (map! :leader + :desc ,(format "Select popup %s" n) + ,(format "M-%s" n) #',function + :desc ,(format "Select popup %s" n) + ,(format "~ %s" n) #',function))))) + +(defun +winum-select-popup-0-or-10 (&optional arg) + "Jump to popup window 0, or popup 10 if 0 is not assigned. +If prefix ARG is given, delete the window instead of selecting it." + (interactive "P") + (let ((n (if (winum-get-window-by-index '(popup . 0)) '(popup . 0) '(popup . 10)))) + (if arg + (winum-delete-window-by-index n) + (winum-select-window-by-index n)))) + +(map! :leader + :desc "Select popup 0 or 10" + "M-0" #'+winum-select-popup-0-or-10 + :desc "Select popup 0 or 10" + "~ 0" #'+winum-select-popup-0-or-10) +#+end_src + * Applications ** Calculator diff --git a/pkgs/winum b/pkgs/winum new file mode 160000 index 0000000..aca0f74 --- /dev/null +++ b/pkgs/winum @@ -0,0 +1 @@ +Subproject commit aca0f74f3a442b1b1a6f4315303c340f7c1005b8