Fix emacs window behavior

This commit is contained in:
Ian Keane 2026-08-06 17:18:08 -04:00
parent fd97cd17cf
commit 5d7833426e

View file

@ -252,6 +252,13 @@ Setting this in the :init of evil doesn't work for some reason. It has to be ear
#+end_src #+end_src
** Buffers ** Buffers
=TODO:= Make this use currently selected buffer =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 #+begin_src emacs-lisp
;; Generate buffers in last window ;; Generate buffers in last window
(setq display-buffer-base-action (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 ;; Update files when changed on disk
(global-auto-revert-mode 1) (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 ;; If a popup does happen, don't resize windows to be equal-sized
(setq even-window-sizes nil) (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 ** Windows and Workspaces
[[https://github.com/abo-abo/ace-window/issues/216][Credit]] for manual dispatch function. [[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 <left>= / =C-c <right>= undo/redo window layouts via winner
=TODO:= Window width controls =TODO:= Window width controls
#+begin_src emacs-lisp #+begin_src emacs-lisp
(use-package winner (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) (ace-window arg)
)) ))
#+end_src #+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 ** 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 #+begin_src emacs-lisp
(use-package popper (use-package popper
:after (shackle projectile) :after projectile
:init :init
(setq popper-reference-buffers (setq popper-reference-buffers
'(("\\*Messages\\*" . hide) '(("\\*Messages\\*" . hide)
"\\*Error\\*" "\\*Error\\*"
"Output\\*$" "Output\\*$"
("\\*Warnings\\*" . hide) ("\\*Warnings\\*" . hide)
"\\*scratch*\\*" "\\*scratch\\*"
;; "\\*lsp-bridge\\*"
"\\*Async Shell Command\\*" "\\*Async Shell Command\\*"
"^\\*eshell.*\\*$" eshell-mode ;eshell as a popup "^\\*eshell.*\\*$" eshell-mode
"^\\*shell.*\\*$" shell-mode ;shell as a popup "^\\*shell.*\\*$" shell-mode
"^\\*term.*\\*$" term-mode ;term as a popup "^\\*term.*\\*$" term-mode
"^\\*vterm.*\\*$" vterm-mode ;vterm as a popup "^\\*vterm.*\\*$" vterm-mode
helpful-mode helpful-mode
help-mode
compilation-mode compilation-mode
inferior-python-mode inferior-python-mode
consult-flymake-mode)) consult-flymake-mode))
:config :config
(setq popper-display-control nil) (setq popper-display-control t)
(setq popper-group-function #'popper-group-by-projectile)
(popper-mode +1) (popper-mode +1)
(popper-echo-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 #+end_src
** Dired ** Dired
#+begin_src emacs-lisp #+begin_src emacs-lisp