config-windows.el (7972B)
1 ;;; config-windows.el --- -*- lexical-binding: t; -*- 2 ;; Commentary: 3 ;;; Windows configuration 4 ;; Code: 5 6 (setq switch-to-buffer-obey-display-actions t) 7 8 (defun vde/save-desktop-no-ask () 9 "Save the desktop without asking questions by modifying the modtime." 10 (interactive) 11 (require 'desktop) 12 (desktop--get-file-modtime) 13 (desktop-save (concat desktop-dirname))) 14 (defun vde/desktop-load () 15 "Load saved desktop" 16 (interactive) 17 (require 'desktop) 18 (desktop-read desktop-dirname)) 19 20 (bind-key "C-c d s" #'vde/save-desktop-no-ask) 21 (bind-key "C-c d l" #'vde/desktop-load) 22 23 ;; Winner 24 (use-package winner 25 :unless noninteractive 26 :defer 5 27 :config 28 (winner-mode 1)) 29 ;; -UseWinner 30 31 (defun toggle-maximize-buffer () 32 "Maximize buffer" 33 (interactive) 34 (if (one-window-p) 35 (winner-undo) 36 (delete-other-windows))) 37 38 ;; UseAceWindow 39 (use-package ace-window 40 :unless noninteractive 41 :commands (ace-window ace-swap-window) 42 :bind (("C-x o" . ace-window) 43 ("C-c w w" . ace-window) 44 ("C-c w s" . ace-swap-window)) 45 :config 46 (setq-default aw-keys '(?a ?u ?i ?e ?, ?c ?t ?r ?m) 47 aw-scope 'frame 48 aw-dispatch-always t 49 aw-dispatch-alist 50 '((?s aw-swap-window "Swap Windows") 51 (?2 aw-split-window-vert "Split Window Vertically") 52 (?3 aw-split-window-horz "Split Window Horizontally") 53 (?? aw-show-dispatch-help)) 54 aw-minibuffer-flag t 55 aw-ignore-current nil 56 aw-display-mode-overlay t 57 aw-background t)) 58 ;; -UseAceWindow 59 60 ;; UseWindmove 61 (use-package windmove 62 :unless noninteractive 63 :commands (windmove-left windmove-right windmove-down windmove-up) 64 :bind (("C-M-<up>" . windmove-up) 65 ("C-M-<right>" . windmove-right) 66 ("C-M-<down>" . windmove-down) 67 ("C-M-<left>" . windmove-left))) 68 ;; -UseWindmove 69 70 ;; UseWindow 71 (use-package window 72 :unless noninteractive 73 :commands (shrink-window-horizontally shrink-window enlarge-window-horizontally enlarge-window) 74 :bind (("S-C-<left>" . shrink-window-horizontally) 75 ("S-C-<right>" . enlarge-window-horizontally) 76 ("S-C-<down>" . shrink-window) 77 ("S-C-<up>" . enlarge-window))) 78 ;; -UseWindow 79 80 ;;;###autoload 81 (defun prot-common-window-small-p () 82 "Return non-nil if window is small. 83 Check if the `window-width' or `window-height' is less than 84 `split-width-threshold' and `split-height-threshold', 85 respectively." 86 (or (and (numberp split-width-threshold) 87 (< (window-total-width) split-width-threshold)) 88 (and (numberp split-height-threshold) 89 (> (window-total-height) split-height-threshold)))) 90 91 (defun prot-common-three-or-more-windows-p (&optional frame) 92 "Return non-nil if three or more windows occupy FRAME. 93 If FRAME is non-nil, inspect the current frame." 94 (>= (length (window-list frame :no-minibuffer)) 3)) 95 96 (defun prot-window--get-display-buffer-below-or-pop () 97 "Return list of functions for `prot-window-display-buffer-below-or-pop'." 98 (list 99 #'display-buffer-reuse-mode-window 100 (if (or (prot-common-window-small-p) 101 (prot-common-three-or-more-windows-p)) 102 #'display-buffer-below-selected 103 #'display-buffer-pop-up-window))) 104 105 (defun prot-window-display-buffer-below-or-pop (&rest args) 106 "Display buffer below current window or pop a new window. 107 The criterion for choosing to display the buffer below the 108 current one is a non-nil return value for 109 `prot-common-window-small-p'. 110 111 Apply ARGS expected by the underlying `display-buffer' functions. 112 113 This as the action function in a `display-buffer-alist' entry." 114 (let ((functions (prot-window--get-display-buffer-below-or-pop))) 115 (catch 'success 116 (dolist (fn functions) 117 (when (apply fn args) 118 (throw 'success fn)))))) 119 120 (defvar prot-window-window-sizes 121 '( :max-height (lambda () (floor (frame-height) 3)) 122 :min-height 10 123 :max-width (lambda () (floor (frame-width) 4)) 124 :min-width 20) 125 "Property list of maximum and minimum window sizes. 126 The property keys are `:max-height', `:min-height', `:max-width', 127 and `:min-width'. They all accept a value of either a 128 number (integer or floating point) or a function.") 129 130 (defun prot-window--get-window-size (key) 131 "Extract the value of KEY from `prot-window-window-sizes'." 132 (when-let ((value (plist-get prot-window-window-sizes key))) 133 (cond 134 ((functionp value) 135 (funcall value)) 136 ((numberp value) 137 value) 138 (t 139 (error "The value of `%s' is neither a number nor a function" key))))) 140 141 (defun prot-window-select-fit-size (window &rest _) 142 "Select WINDOW and resize it. 143 The resize pertains to the maximum and minimum values for height 144 and width, per `prot-window-window-sizes'. 145 146 Use this as the `body-function' in a `display-buffer-alist' entry." 147 (select-window window) 148 (fit-window-to-buffer 149 window 150 (prot-window--get-window-size :max-height) 151 (prot-window--get-window-size :min-height) 152 (prot-window--get-window-size :max-width) 153 (prot-window--get-window-size :min-width))) 154 155 (defun prot-window-shell-or-term-p (buffer &rest _) 156 "Check if BUFFER is a shell or terminal. 157 This is a predicate function for `buffer-match-p', intended for 158 use in `display-buffer-alist'." 159 (when (string-match-p "\\*.*\\(e?shell\\|v?term\\).*" (buffer-name (get-buffer buffer))) 160 (with-current-buffer buffer 161 ;; REVIEW 2022-07-14: Is this robust? 162 (and (not (derived-mode-p 'message-mode 'text-mode)) 163 (derived-mode-p 'eshell-mode 'shell-mode 'comint-mode 'fundamental-mode))))) 164 165 (setq display-buffer-alist 166 `(;; Default to no window 167 ("\\`\\*Async Shell Command\\*\\'" 168 (display-buffer-no-window)) 169 ("\\`\\*\\(Warnings\\|Compile-Log\\|Org Links\\)\\*\\'" 170 (display-buffer-no-window) 171 (allow-no-window . t)) 172 ;; bottom side window 173 ("\\*Org \\(Select\\|Note\\)\\*" ; the `org-capture' key selection and `org-add-log-note' 174 (display-buffer-in-side-window) 175 (dedicated . t) 176 (side . bottom) 177 (slot . 0) 178 (window-parameters . ((mode-line-format . none)))) 179 ;; bottom buffer (NOT side window) 180 ((or . ((derived-mode . flymake-diagnostics-buffer-mode) 181 (derived-mode . flymake-project-diagnostics-mode) 182 (derived-mode . messages-buffer-mode) 183 (derived-mode . backtrace-mode))) 184 (display-buffer-reuse-mode-window display-buffer-at-bottom) 185 (window-height . 0.3) 186 (dedicated . t) 187 (preserve-size . (t . t))) 188 ;; ((or . ((derived-mode . Man-mode) 189 ;; (derived-mode . woman-mode) 190 ;; "\\*\\(Man\\|woman\\).*")) 191 ;; (display-buffer-reuse-mode-window display-buffer-below-selected) 192 ;; (window-height . 0.3) ; note this is literal lines, not relative 193 ;; (dedicated . t) 194 ;; (preserve-size . (t . t))) 195 ;; below current window 196 ("\\(\\*Capture\\*\\|CAPTURE-.*\\)" 197 (display-buffer-reuse-mode-window display-buffer-below-selected)) 198 ((derived-mode . reb-mode) ; M-x re-builder 199 (display-buffer-reuse-mode-window display-buffer-below-selected) 200 (window-height . 4) ; note this is literal lines, not relative 201 (dedicated . t) 202 (preserve-size . (t . t))) 203 ((or . ((derived-mode . occur-mode) 204 (derived-mode . grep-mode) 205 (derived-mode . Buffer-menu-mode) 206 (derived-mode . log-view-mode) 207 (derived-mode . helpful-mode) 208 (derived-mode . help-mode) ; See the hooks for `visual-line-mode' 209 "\\*\\(|Buffer List\\|Occur\\|vc-change-log\\).*" 210 prot-window-shell-or-term-p 211 ,world-clock-buffer-name)) 212 (prot-window-display-buffer-below-or-pop) 213 (dedicated . t) 214 (body-function . prot-window-select-fit-size)) 215 )) 216 217 ;; TODO: Move display-buffer-alist here 218 219 (provide 'config-windows) 220 ;;; config-windows ends here