diff --git a/emacs-config.org b/emacs-config.org index 9abc2f4..9e22dc6 100644 --- a/emacs-config.org +++ b/emacs-config.org @@ -252,6 +252,13 @@ Setting this in the :init of evil doesn't work for some reason. It has to be ear #+end_src ** Buffers =TODO:= Make this use currently selected buffer + +The base display action tries to reuse an existing window showing the same +mode or buffer before opening a new one, falling back to the same window. +This is the default for buffers not covered by =display-buffer-alist= in the +Popper section. The goal is to avoid gratuitous window splits for ordinary +buffer switching — splits should be intentional. + #+begin_src emacs-lisp ;; Generate buffers in last window (setq display-buffer-base-action @@ -277,7 +284,13 @@ Setting this in the :init of evil doesn't work for some reason. It has to be ear ;; Update files when changed on disk (global-auto-revert-mode 1) - (use-package helpful) ; Slightly more helpful help + (use-package helpful + :ensure t + :bind + ([remap describe-function] . helpful-callable) + ([remap describe-variable] . helpful-variable) + ([remap describe-key] . helpful-key) + ([remap describe-command] . helpful-command)) ;; If a popup does happen, don't resize windows to be equal-sized (setq even-window-sizes nil) @@ -369,6 +382,16 @@ Setting this in the :init of evil doesn't work for some reason. It has to be ear ** Windows and Workspaces [[https://github.com/abo-abo/ace-window/issues/216][Credit]] for manual dispatch function. +General window management uses =ace-window= for jumping and splitting, with +=winner-mode= for undo/redo of window layouts. The philosophy here is to keep +manual window control lightweight — ace-window covers most navigation needs +with single keypresses, and winner catches mistakes. Workspaces are handled +at the tab level rather than with a dedicated workspace package. + +- =SPC w= jumps to a window by label +- =SPC W= opens the full ace-window dispatch menu for splits, swaps, etc. +- =C-c = / =C-c = undo/redo window layouts via winner + =TODO:= Window width controls #+begin_src emacs-lisp (use-package winner @@ -405,51 +428,88 @@ Setting this in the :init of evil doesn't work for some reason. It has to be ear (ace-window arg) )) #+end_src -** Shackle -#+begin_src emacs-lisp - (use-package shackle - :config - (shackle-mode)) - - (setq shackle-rules - '( - (helpful-mode :align right :select t :size 0.3 :popup t) - (help-mode :align right :select t :size 0.3 :popup t) - (compilation-mode :align right :select t :size 0.3 :popup t) - ("*shell*" :align below :select t :size 0.3 :popup t) - ("*eshell*" :align below :select t :size 0.3 :popup t) - ("*vterm*" :align below :select t :size 0.3 :popup t) - ("*scratch*" :align left :select t :size 0.25 :popup t) - (treemacs-mode :align left :select t :size 0.40 :popup t) - ("*Messages*" :align right :select t :size 0.25 :popup t)) - default-shackle-rule '(:select t)) ;; Always select newly created windows -#+end_src ** Popper +Transient/popup buffers — terminals, help, compilation, messages — are managed +by popper, which tracks them as a group and lets you cycle or dismiss them +together. Popper's display control is enabled, meaning it defers to +=display-buffer-alist= (below) for the actual placement logic rather than +using its own defaults. Buffers are grouped by projectile project so popup +state is workspace-local. + +- Popper decides /what/ is a popup +- =display-buffer-alist= decides /where/ it goes +- Terminals always go to the bottom +- Help and compilation go to the bottom unless the window is too narrow (<65 + columns), in which case they replace the current buffer instead +- Messages appear at the bottom without stealing focus + #+begin_src emacs-lisp (use-package popper - :after (shackle projectile) + :after projectile :init (setq popper-reference-buffers - '(("\\*Messages\\*" . hide) - "\\*Error\\*" - "Output\\*$" - ("\\*Warnings\\*" . hide) - "\\*scratch*\\*" - ;; "\\*lsp-bridge\\*" - "\\*Async Shell Command\\*" - "^\\*eshell.*\\*$" eshell-mode ;eshell as a popup - "^\\*shell.*\\*$" shell-mode ;shell as a popup - "^\\*term.*\\*$" term-mode ;term as a popup - "^\\*vterm.*\\*$" vterm-mode ;vterm as a popup - helpful-mode - compilation-mode - inferior-python-mode - consult-flymake-mode)) + '(("\\*Messages\\*" . hide) + "\\*Error\\*" + "Output\\*$" + ("\\*Warnings\\*" . hide) + "\\*scratch\\*" + "\\*Async Shell Command\\*" + "^\\*eshell.*\\*$" eshell-mode + "^\\*shell.*\\*$" shell-mode + "^\\*term.*\\*$" term-mode + "^\\*vterm.*\\*$" vterm-mode + helpful-mode + help-mode + compilation-mode + inferior-python-mode + consult-flymake-mode)) :config - (setq popper-display-control nil) + (setq popper-display-control t) + (setq popper-group-function #'popper-group-by-projectile) (popper-mode +1) (popper-echo-mode +1)) - (setq popper-group-function #'popper-group-by-projectile) + + ;; display-buffer-alist rules (replaces shackle) + (setq display-buffer-alist + `(;; Help buffers: bottom split, fall back to same window if narrow + ((or (derived-mode . help-mode) + (derived-mode . helpful-mode)) + (display-buffer-reuse-window + ,(lambda (buf alist) + (when (< (window-width) 65) + (display-buffer-same-window buf alist))) + display-buffer-in-side-window) + (side . bottom) + (slot . 0) + (window-height . 0.35) + (select . t)) + + ;; Compilation: bottom split + ((derived-mode . compilation-mode) + (display-buffer-in-side-window) + (side . bottom) + (slot . 1) + (window-height . 0.35) + (select . t)) + + ;; Messages: bottom, no focus steal + ("\\*Messages\\*" + (display-buffer-in-side-window) + (side . bottom) + (slot . 2) + (window-height . 0.25) + (select . nil)) + + ;; Terminals: always bottom + ((or "^\\*eshell.*\\*$" + "^\\*shell.*\\*$" + "^\\*term.*\\*$" + "^\\*vterm.*\\*$") + (display-buffer-in-side-window) + (side . bottom) + (slot . 3) + (window-height . 0.35) + (select . t)))) #+end_src ** Dired #+begin_src emacs-lisp