diff options
| -rw-r--r-- | modules/custom-buffer-file.el | 21 | ||||
| -rw-r--r-- | modules/ui-navigation.el | 33 | ||||
| -rw-r--r-- | tests/test-ui-navigation--window-resize.el | 51 |
3 files changed, 98 insertions, 7 deletions
diff --git a/modules/custom-buffer-file.el b/modules/custom-buffer-file.el index 7fe412ee..f4401d1f 100644 --- a/modules/custom-buffer-file.el +++ b/modules/custom-buffer-file.el @@ -17,6 +17,9 @@ ;; ;; Keybindings under ~C-; b~: ;; - ~C-; b k~ kill buffer and window (delete window, kill/bury buffer) +;; - ~C-; b <arrow>~ move the active window's divider that way (via windsize); +;; bare arrows keep nudging until any other key (cj/window-resize-sticky in +;; ui-navigation.el) ;; - Copy buffer content submenu at ~C-; b c~ ;; - ~C-; b c w~ copy whole buffer ;; - ~C-; b c t~ copy from beginning to point @@ -37,6 +40,9 @@ ;; cj/kill-buffer-and-window defined in undead-buffers.el (declare-function cj/kill-buffer-and-window "undead-buffers") +;; cj/window-resize-sticky (C-; b <arrow>) defined in ui-navigation.el +(declare-function cj/window-resize-sticky "ui-navigation") + ;; ------------------------- Print Buffer As Postscript ------------------------ (defvar cj/print-spooler-command 'auto @@ -454,7 +460,14 @@ Signals an error if: "w" #'cj/view-buffer-in-eww "E" #'cj/view-email-in-buffer "o" #'cj/xdg-open - "O" #'cj/open-this-file-with) + "O" #'cj/open-this-file-with + ;; Window resize (cj/window-resize-sticky in ui-navigation.el, on `windsize'): + ;; the arrow moves the active window's divider that way, then bare arrows + ;; keep nudging until any other key. + "<left>" #'cj/window-resize-sticky + "<right>" #'cj/window-resize-sticky + "<up>" #'cj/window-resize-sticky + "<down>" #'cj/window-resize-sticky) (when (boundp 'cj/custom-keymap) (keymap-set cj/custom-keymap "b" cj/buffer-and-file-map)) @@ -484,7 +497,11 @@ Signals an error if: "C-; b w" "view in EWW" "C-; b E" "view email" "C-; b o" "open with default app" - "C-; b O" "open with program...")) + "C-; b O" "open with program..." + "C-; b <left>" "resize divider left" + "C-; b <right>" "resize divider right" + "C-; b <up>" "resize divider up" + "C-; b <down>" "resize divider down")) (provide 'custom-buffer-file) diff --git a/modules/ui-navigation.el b/modules/ui-navigation.el index b99a9cac..23e38c0a 100644 --- a/modules/ui-navigation.el +++ b/modules/ui-navigation.el @@ -42,16 +42,39 @@ ;; ------------------------------ Window Resizing ------------------------------ +;; windsize moves the divider between the active window and a neighbor in the +;; arrow's direction (preferring the right/bottom border). Its commands have +;; no repeat mechanism; `cj/window-resize-sticky' below adds one. windsize was +;; on C-s-<arrow> (Ctrl+Super), which a tiling WM eats, so the keys live under +;; C-; b instead (bound there in custom-buffer-file.el). (use-package windsize - :bind - ("C-s-<left>" . windsize-left) - ("C-s-<right>" . windsize-right) - ("C-s-<up>" . windsize-up) - ("C-s-<down>" . windsize-down)) + :commands (windsize-left windsize-right windsize-up windsize-down) + :custom + (windsize-cols 2) ; default 8 is too jumpy for a held nudge loop + (windsize-rows 2)) ; default 4, same reason ;; M-shift = to balance multiple split windows (keymap-global-set "M-+" #'balance-windows) +(defvar-keymap cj/window-resize-map + :doc "Bare arrows that keep resizing the split after a `C-; b <arrow>' +resize -- each moves the active window's divider in the arrow's direction +(via `windsize'). Any other key (or `C-g' / `<escape>') ends the loop." + "<left>" #'windsize-left + "<right>" #'windsize-right + "<up>" #'windsize-up + "<down>" #'windsize-down) + +(defun cj/window-resize-sticky () + "Resize the active window's divider in the just-pressed arrow's direction +(via `windsize'), then keep `cj/window-resize-map' active so bare arrows keep +nudging until any other key. Bound to `C-; b <left>/<right>/<up>/<down>'." + (interactive) + (let ((cmd (keymap-lookup cj/window-resize-map + (key-description (vector last-command-event))))) + (when cmd (call-interactively cmd))) + (set-transient-map cj/window-resize-map t)) + ;; ------------------------------ Window Splitting ----------------------------- (defun cj/split-and-follow-right () diff --git a/tests/test-ui-navigation--window-resize.el b/tests/test-ui-navigation--window-resize.el new file mode 100644 index 00000000..3be0313b --- /dev/null +++ b/tests/test-ui-navigation--window-resize.el @@ -0,0 +1,51 @@ +;;; test-ui-navigation--window-resize.el --- Tests for the C-; b <arrow> resize keys -*- lexical-binding: t; -*- + +;;; Commentary: +;; `C-; b <left>/<right>/<up>/<down>' moves the active window's divider in the +;; arrow's direction (via `windsize'), then keeps `cj/window-resize-map' active +;; so bare arrows keep nudging until any other key. We own the dispatch +;; (`cj/window-resize-sticky' -- pick the matching `windsize-*' command, run it, +;; arm the loop) and the keymaps; the resize math is `windsize's job and isn't +;; tested here. + +;;; Code: + +(require 'ert) +(require 'cl-lib) + +(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory)) +(require 'ui-navigation) + +(ert-deftest test-ui-navigation-window-resize-map-bindings () + "Normal: the sticky-resize map maps the four arrows to the `windsize' commands." + (should (eq (keymap-lookup cj/window-resize-map "<left>") #'windsize-left)) + (should (eq (keymap-lookup cj/window-resize-map "<right>") #'windsize-right)) + (should (eq (keymap-lookup cj/window-resize-map "<up>") #'windsize-up)) + (should (eq (keymap-lookup cj/window-resize-map "<down>") #'windsize-down))) + +(ert-deftest test-ui-navigation-window-resize-sticky-dispatches-and-arms () + "Normal: `cj/window-resize-sticky' runs the `windsize' command matching the +arrow key that triggered it, then arms the sticky-repeat map." + (dolist (case '((left . windsize-left) + (right . windsize-right) + (up . windsize-up) + (down . windsize-down))) + (let ((ran nil) + (overriding-terminal-local-map nil) + (pre-command-hook nil)) + (cl-letf (((symbol-function (cdr case)) + (lambda (&rest _) (interactive) (setq ran t)))) + (let ((last-command-event (car case))) + (cj/window-resize-sticky))) + (should ran) ; dispatched to the right command + (should overriding-terminal-local-map)))) ; loop armed + +(ert-deftest test-ui-navigation-window-resize-bound-under-c-semicolon-b () + "Normal: `C-; b <arrow>' (each direction) reaches the sticky-resize command." + (require 'custom-buffer-file) + (dolist (arrow '("<left>" "<right>" "<up>" "<down>")) + (should (eq (keymap-lookup cj/buffer-and-file-map arrow) + #'cj/window-resize-sticky)))) + +(provide 'test-ui-navigation--window-resize) +;;; test-ui-navigation--window-resize.el ends here |
