fedora-csb-system-manager
  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/window-delete-popup-frame (&rest _)
  9  "Kill selected selected frame if it has parameter `prot-window-popup-frame'.
 10Use this function via a hook."
 11  (when (frame-parameter nil 'vde/window-popup-frame)
 12    (delete-frame)))
 13
 14(defun vde/save-desktop-no-ask ()
 15  "Save the desktop without asking questions by modifying the modtime."
 16  (interactive)
 17  (require 'desktop)
 18  (desktop--get-file-modtime)
 19  (desktop-save (concat desktop-dirname)))
 20(defun vde/desktop-load ()
 21  "Load saved desktop"
 22  (interactive)
 23  (require 'desktop)
 24  (desktop-read desktop-dirname))
 25
 26(bind-key "C-c d s" #'vde/save-desktop-no-ask)
 27(bind-key "C-c d l" #'vde/desktop-load)
 28
 29;; Winner
 30(use-package winner
 31  :unless noninteractive
 32  :defer 5
 33  :config
 34  (winner-mode 1))
 35;; -UseWinner
 36
 37(defun toggle-maximize-buffer ()
 38  "Maximize buffer"
 39  (interactive)
 40  (if (one-window-p)
 41      (winner-undo)
 42    (delete-other-windows)))
 43
 44;; UseAceWindow
 45(use-package ace-window
 46  :unless noninteractive
 47  :commands (ace-window ace-swap-window)
 48  :bind (("C-x o"   . ace-window)
 49         ("C-c w w" . ace-window)
 50         ("C-c w s" . ace-swap-window))
 51  :config
 52  (setq-default aw-keys '(?a ?u ?i ?e ?, ?c ?t ?r ?m)
 53                aw-scope 'frame
 54                aw-dispatch-always t
 55                aw-dispatch-alist
 56                '((?s aw-swap-window "Swap Windows")
 57                  (?2 aw-split-window-vert "Split Window Vertically")
 58                  (?3 aw-split-window-horz "Split Window Horizontally")
 59                  (?? aw-show-dispatch-help))
 60                aw-minibuffer-flag t
 61                aw-ignore-current nil
 62                aw-display-mode-overlay t
 63                aw-background t))
 64;; -UseAceWindow
 65
 66;; UseWindmove
 67(use-package windmove
 68  :unless noninteractive
 69  :commands (windmove-left windmove-right windmove-down windmove-up)
 70  :custom
 71  (windmove-allow-all-windows t)
 72  :bind (("C-M-<up>" . windmove-up)
 73         ("C-M-<right>" . windmove-right)
 74         ("C-M-<down>" . windmove-down)
 75         ("C-M-<left>" . windmove-left)))
 76;; -UseWindmove
 77
 78;; UseWindow
 79(use-package window
 80  :unless noninteractive
 81  :commands (shrink-window-horizontally shrink-window enlarge-window-horizontally enlarge-window)
 82  :bind (("S-C-<left>" . shrink-window-horizontally)
 83         ("S-C-<right>" . enlarge-window-horizontally)
 84         ("S-C-<down>" . shrink-window)
 85         ("S-C-<up>" . enlarge-window)))
 86;; -UseWindow
 87
 88;;;###autoload
 89(defun prot-common-window-small-p ()
 90  "Return non-nil if window is small.
 91Check if the `window-width' or `window-height' is less than
 92`split-width-threshold' and `split-height-threshold',
 93respectively."
 94  (or (and (numberp split-width-threshold)
 95           (< (window-total-width) split-width-threshold))
 96      (and (numberp split-height-threshold)
 97           (> (window-total-height) split-height-threshold))))
 98
 99(defun prot-common-three-or-more-windows-p (&optional frame)
100  "Return non-nil if three or more windows occupy FRAME.
101If FRAME is non-nil, inspect the current frame."
102  (>= (length (window-list frame :no-minibuffer)) 3))
103
104(defun prot-window--get-display-buffer-below-or-pop ()
105  "Return list of functions for `prot-window-display-buffer-below-or-pop'."
106  (list
107   #'display-buffer-reuse-mode-window
108   (if (or (prot-common-window-small-p)
109           (prot-common-three-or-more-windows-p))
110       #'display-buffer-below-selected
111     #'display-buffer-pop-up-window)))
112
113(defun prot-window-display-buffer-below-or-pop (&rest args)
114  "Display buffer below current window or pop a new window.
115The criterion for choosing to display the buffer below the
116current one is a non-nil return value for
117`prot-common-window-small-p'.
118
119Apply ARGS expected by the underlying `display-buffer' functions.
120
121This as the action function in a `display-buffer-alist' entry."
122  (let ((functions (prot-window--get-display-buffer-below-or-pop)))
123    (catch 'success
124      (dolist (fn functions)
125        (when (apply fn args)
126          (throw 'success fn))))))
127
128(defvar prot-window-window-sizes
129  '( :max-height (lambda () (floor (frame-height) 3))
130     :min-height 10
131     :max-width (lambda () (floor (frame-width) 4))
132     :min-width 20)
133  "Property list of maximum and minimum window sizes.
134The property keys are `:max-height', `:min-height', `:max-width',
135and `:min-width'.  They all accept a value of either a
136number (integer or floating point) or a function.")
137
138(defun prot-window--get-window-size (key)
139  "Extract the value of KEY from `prot-window-window-sizes'."
140  (when-let ((value (plist-get prot-window-window-sizes key)))
141    (cond
142     ((functionp value)
143      (funcall value))
144     ((numberp value)
145      value)
146     (t
147      (error "The value of `%s' is neither a number nor a function" key)))))
148
149(defun prot-window-select-fit-size (window &rest _)
150  "Select WINDOW and resize it.
151The resize pertains to the maximum and minimum values for height
152and width, per `prot-window-window-sizes'.
153
154Use this as the `body-function' in a `display-buffer-alist' entry."
155  (select-window window)
156  (fit-window-to-buffer
157   window
158   (prot-window--get-window-size :max-height)
159   (prot-window--get-window-size :min-height)
160   (prot-window--get-window-size :max-width)
161   (prot-window--get-window-size :min-width)))
162
163(defun prot-window-shell-or-term-p (buffer &rest _)
164  "Check if BUFFER is a shell or terminal.
165This is a predicate function for `buffer-match-p', intended for
166use in `display-buffer-alist'."
167  (when (string-match-p "\\*.*\\(e?shell\\|v?term\\).*" (buffer-name (get-buffer buffer)))
168    (with-current-buffer buffer
169      ;; REVIEW 2022-07-14: Is this robust?
170      (and (not (derived-mode-p 'message-mode 'text-mode))
171           (derived-mode-p 'eshell-mode 'shell-mode 'comint-mode 'fundamental-mode)))))
172
173;; (setq display-buffer-alist
174;;       `(;; Default to no window
175;; 	("\\`\\*Async Shell Command\\*\\'"
176;; 	 (display-buffer-no-window))
177;; 	("\\`\\*Warnings\\*\\'"
178;;          (display-buffer-no-window)
179;; 	 (allow-no-window . t))
180;; 	("\\`\\*\\(Compile-Log\\|Org Links\\)\\*\\'"
181;;          (display-buffer-no-window))
182;; 	;; bottom side window
183;;         ("\\*Org \\(Select\\|Note\\)\\*" ; the `org-capture' key selection and `org-add-log-note'
184;;          (display-buffer-in-side-window)
185;;          (dedicated . t)
186;;          (side . bottom)
187;;          (slot . 0)
188;;          (window-parameters . ((mode-line-format . none))))
189;; 	;; bottom buffer (NOT side window)
190;;         ((or . ((derived-mode . flymake-diagnostics-buffer-mode)
191;;                 (derived-mode . flymake-project-diagnostics-mode)
192;;                 (derived-mode . messages-buffer-mode)
193;;                 (derived-mode . backtrace-mode)))
194;;          (display-buffer-reuse-mode-window display-buffer-at-bottom)
195;;          (window-height . 0.3)
196;;          (dedicated . t)
197;;          (preserve-size . (t . t)))
198;; 	;; ((or . ((derived-mode . Man-mode)
199;; 	;; 	(derived-mode . woman-mode)
200;; 	;; 	"\\*\\(Man\\|woman\\).*"))
201;; 	;;  (display-buffer-reuse-mode-window display-buffer-below-selected)
202;;         ;;  (window-height . 0.3) ; note this is literal lines, not relative
203;;         ;;  (dedicated . t)
204;;         ;;  (preserve-size . (t . t)))
205;; 	;; below current window
206;; 	("\\(\\*Capture\\*\\|CAPTURE-.*\\)"
207;;          (display-buffer-reuse-mode-window display-buffer-below-selected))
208;; 	((derived-mode . reb-mode) ; M-x re-builder
209;;          (display-buffer-reuse-mode-window display-buffer-below-selected)
210;;          (window-height . 4) ; note this is literal lines, not relative
211;;          (dedicated . t)
212;;          (preserve-size . (t . t)))
213;; 	((or . ((derived-mode . occur-mode)
214;;                 (derived-mode . grep-mode)
215;;                 (derived-mode . Buffer-menu-mode)
216;;                 (derived-mode . log-view-mode)
217;; 		(derived-mode . helpful-mode)
218;;                 (derived-mode . help-mode) ; See the hooks for `visual-line-mode'
219;;                 "\\*\\(|Buffer List\\|Occur\\|vc-change-log\\).*"
220;;                 prot-window-shell-or-term-p
221;;                 ,world-clock-buffer-name))
222;;          (prot-window-display-buffer-below-or-pop)
223;;          (dedicated . t)
224;;          (body-function . prot-window-select-fit-size))
225;; 	))
226
227(use-package auto-side-windows
228  :custom
229  ;; Top side window configurations
230  (auto-side-windows-top-buffer-names
231   '("^\\*Backtrace\\*$" "^\\*Compile-Log\\*$" "^COMMIT_EDITMSG$"
232     "^\\*Org Src.*\\*" "^\\*Agenda Commands\\*$" "^\\*Org Agenda\\*$"
233     "^\\*Quick Help\\*$" "^\\*Multiple Choice Help\\*$" "^\\*TeX Help\\*$"
234     "^\\*TeX errors\\*$" "^\\*Warnings\\*$" "^\\*diff-hl\\*$"
235     "^\\*Process List\\*$"))
236  (auto-side-windows-top-buffer-modes
237   '(flymake-diagnostics-buffer-mode locate-mode occur-mode grep-mode
238                                     xref--xref-buffer-mode))
239
240  ;; Bottom side window configurations
241  (auto-side-windows-bottom-buffer-names
242   '("^\\*.*eshell.*\\*$" "^\\*.*shell.*\\*$" "^\\*.*term.*\\*$"
243     "^\\*.*vterm.*\\*$" "^\\*.*eat.*\\*$"))
244  (auto-side-windows-bottom-buffer-modes
245   '(eshell-mode shell-mode term-mode vterm-mode comint-mode compilation-mode debugger-mode))
246
247  ;; Right side window configurations
248  (auto-side-windows-right-buffer-names
249   '("^\\*eldoc.*\\*$" "^\\*info\\*$" "^\\*Metahelp\\*$"))
250  (auto-side-windows-right-buffer-modes
251   '(Info-mode TeX-output-mode pdf-view-mode eldoc-mode help-mode
252               helpful-mode shortdoc-mode))
253
254  ;; Example: Custom parameters for top windows (e.g., fit height to buffer)
255  ;; (auto-side-windows-top-alist '((window-height . fit-window-to-buffer)))
256  ;; (auto-side-windows-top-window-parameters '((mode-line-format . ...))) ;; Adjust mode-line
257
258  ;; Maximum number of side windows on the left, top, right and bottom
259  (window-sides-slots '(1 1 1 1)) ; Example: Allow one window per side
260
261  ;; Force left and right side windows to occupy full frame height
262  (window-sides-vertical t)
263  (window-combination-resize t)
264
265  ;; Make changes to tab-/header- and mode-line-format persistent when toggleling windows visibility
266  (window-persistent-parameters
267   (append window-persistent-parameters
268           '((tab-line-format . t)
269             (header-line-format . t)
270             (mode-line-format . t))))
271  :bind ;; Example keybindings (adjust prefix as needed)
272  (:map global-map ; Or your preferred keymap prefix
273        ("C-c w t" . auto-side-windows-display-buffer-top)
274        ("C-c w b" . auto-side-windows-display-buffer-bottom)
275        ("C-c w l" . auto-side-windows-display-buffer-left)
276        ("C-c w r" . auto-side-windows-display-buffer-right)
277        ("C-c w T" . auto-side-windows-toggle-side-window)) ; Toggle current buffer in/out of side window
278  :hook
279  (after-init . auto-side-windows-mode)) ; Activate the mode
280
281(use-package popper
282  :after auto-side-windows ; Ensure auto-side-windows variables are defined
283  :hook (auto-side-windows-mode . popper-mode) ; Activate popper alongside
284  :custom
285  ;; Tell Popper to consider buffers matching auto-side-windows rules as popups
286  (popper-reference-buffers
287   (append auto-side-windows-top-buffer-names auto-side-windows-top-buffer-modes
288           auto-side-windows-left-buffer-names auto-side-windows-left-buffer-modes
289           auto-side-windows-right-buffer-names auto-side-windows-right-buffer-modes
290           auto-side-windows-bottom-buffer-names auto-side-windows-bottom-buffer-modes))
291  ;; Optional: Don't let Popper decide where to display, auto-side-windows handles that
292  (popper-display-control nil) ; Or 'user if you prefer popper commands for display
293  :config
294  (require 'popper-echo)
295  (popper-mode +1) ; Enable popper-mode
296  (popper-echo-mode +1) ; Optional: echo area notifications
297  :bind
298  (("C-`" . popper-toggle)
299   ("C-M-`" . popper-toggle-type)
300   ("M-`" . popper-cycle)))
301;; TODO: Move display-buffer-alist here
302
303(provide 'config-windows)
304;;; config-windows ends here