aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorMartin Rudalics2019-05-19 11:03:05 +0200
committerMartin Rudalics2019-05-19 11:03:05 +0200
commit8783becbba410581c6384ee021e7e83ad5236a29 (patch)
tree96cb1f85d83a836f9823acac0e16a89b7a0d9769 /lisp
parentb87e5eea1dd7c7345d0a9f82759eedfd7c9a8099 (diff)
downloademacs-8783becbba410581c6384ee021e7e83ad5236a29.tar.gz
emacs-8783becbba410581c6384ee021e7e83ad5236a29.zip
New buffer display action function 'display-buffer-in-direction'
* lisp/window.el (windows-sharing-edge) (window--try-to-split-window-in-direction) (display-buffer-in-direction): New functions. * doc/lispref/windows.texi (Buffer Display Action Functions): Describe new action function 'display-buffer-in-direction'. (Buffer Display Action Alists): Describe new entry 'direction'. Amend description of 'window' entry. * etc/NEWS: Mention 'display-buffer-in-direction' and 'direction' and 'window' action alist entries.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/window.el148
1 files changed, 148 insertions, 0 deletions
diff --git a/lisp/window.el b/lisp/window.el
index b4f5ac5cc44..2c9d177d0a2 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -7534,6 +7534,152 @@ be added to ALIST."
7534 (unless (cdr (assq 'inhibit-switch-frame alist)) 7534 (unless (cdr (assq 'inhibit-switch-frame alist))
7535 (window--maybe-raise-frame frame))))) 7535 (window--maybe-raise-frame frame)))))
7536 7536
7537(defun windows-sharing-edge (&optional window edge within)
7538 "Return list of live windows sharing the same edge with WINDOW.
7539WINDOW must be a valid window and defaults to the selected one.
7540EDGE stands for the edge to share and must be either 'left',
7541'above', 'right' or 'below'. Omitted or nil, EDGE defaults to
7542'left'.
7543
7544WITHIN nil means to find a live window that shares the opposite
7545EDGE with WINDOW. For example, if EDGE equals 'left', WINDOW has
7546to share (part of) the right edge of any window returned. WITHIN
7547non-nil means to find all live windows that share the same EDGE
7548with WINDOW (Window must be internal in this case). So if EDGE
7549equals 'left', WINDOW's left edge has to fully encompass the left
7550edge of any window returned."
7551 (setq window (window-normalize-window window))
7552 (setq edge (or edge 'left))
7553 (when (and within (window-live-p window))
7554 (error "Cannot share edge from within live window %s" window))
7555 (let ((window-edges (window-edges window nil nil t))
7556 (horizontal (memq edge '(left right)))
7557 (n (pcase edge
7558 ('left 0) ('above 1) ('right 2) ('below 3))))
7559 (unless (numberp n)
7560 (error "Invalid EDGE %s" edge))
7561 (let ((o (mod (+ 2 n) 4))
7562 (p (if horizontal 1 0))
7563 (q (if horizontal 3 2))
7564 windows)
7565 (walk-window-tree
7566 (lambda (other)
7567 (let ((other-edges (window-edges other nil nil t)))
7568 (when (and (not (eq window other))
7569 (= (nth n window-edges)
7570 (nth (if within n o) other-edges))
7571 (cond
7572 ((= (nth p window-edges) (nth p other-edges)))
7573 ((< (nth p window-edges) (nth p other-edges))
7574 (< (nth p other-edges) (nth q window-edges)))
7575 (t
7576 (< (nth p window-edges) (nth q other-edges)))))
7577 (setq windows (cons other windows)))))
7578 (window-frame window) nil 'nomini)
7579 (reverse windows))))
7580
7581(defun window--try-to-split-window-in-direction (window direction alist)
7582 "Try to split WINDOW in DIRECTION.
7583DIRECTION is passed as SIDE argument to `split-window-no-error'.
7584ALIST is a buffer display alist."
7585 (and (not (frame-parameter (window-frame window) 'unsplittable))
7586 (let* ((window-combination-limit
7587 ;; When `window-combination-limit' equals
7588 ;; `display-buffer' or equals `resize-window' and a
7589 ;; `window-height' or `window-width' alist entry are
7590 ;; present, bind it to t so resizing steals space
7591 ;; preferably from the window that was split.
7592 (if (or (eq window-combination-limit 'display-buffer)
7593 (and (eq window-combination-limit 'window-size)
7594 (or (cdr (assq 'window-height alist))
7595 (cdr (assq 'window-width alist)))))
7596 t
7597 window-combination-limit))
7598 (new-window (split-window-no-error window nil direction)))
7599 (and (window-live-p new-window) new-window))))
7600
7601(defun display-buffer-in-direction (buffer alist)
7602 "Try to display BUFFER in a direction specified by ALIST.
7603ALIST has to contain a 'direction' entry whose value should be
7604one of 'left', 'above' (or 'up'), 'right', and 'below' (or
7605'down'). Other values are usually interpreted as 'below'.
7606
7607If ALIST also contains a 'window' entry, its value specifies a
7608reference window. That value can be a special symbol like
7609'main' (which stands for the selected frame's main window) or
7610'root' (standings for the selected frame's root window) or an
7611arbitrary valid window. Any other value (or omitting the
7612'window' entry) means to use the selected window as reference
7613window.
7614
7615This function tries to reuse or split a window such that the
7616window produced this way is on the side of the reference window
7617specified by the 'direction' entry.
7618
7619Four special values for 'direction' entries allow to implicitly
7620specify the selected frame's main window as reference window:
7621'leftmost', 'top', 'rightmost' and 'bottom'. Hence, instead of
7622'(direction . left) (window . main)' one can simply write
7623'(direction . leftmost)'."
7624 (let ((direction (cdr (assq 'direction alist))))
7625 (when direction
7626 (let ((window (cdr (assq 'window alist)))
7627 within windows other-window-shows-buffer other-window)
7628 ;; Sanitize WINDOW.
7629 (cond
7630 ((or (eq window 'main)
7631 (memq direction '(top bottom leftmost rightmost)))
7632 (setq window (window-main-window)))
7633 ((eq window 'root)
7634 (setq window (frame-root-window)))
7635 ((window-valid-p window))
7636 (t
7637 (setq window (selected-window))))
7638 (setq within (not (window-live-p window)))
7639 ;; Sanitize DIRECTION
7640 (cond
7641 ((memq direction '(left above right below)))
7642 ((eq direction 'leftmost)
7643 (setq direction 'left))
7644 ((memq direction '(top up))
7645 (setq direction 'above))
7646 ((eq direction 'rightmost)
7647 (setq direction 'right))
7648 ((memq direction '(bottom down))
7649 (setq direction 'below))
7650 (t
7651 (setq direction 'below)))
7652
7653 (setq alist
7654 (append alist
7655 `(,(if temp-buffer-resize-mode
7656 '(window-height . resize-temp-buffer-window)
7657 '(window-height . fit-window-to-buffer))
7658 ,(when temp-buffer-resize-mode
7659 '(preserve-size . (nil . t))))))
7660
7661 (setq windows (windows-sharing-edge window direction within))
7662 (dolist (other windows)
7663 (cond
7664 ((and (not other-window-shows-buffer)
7665 (eq buffer (window-buffer other)))
7666 (setq other-window-shows-buffer t)
7667 (setq other-window other))
7668 ((not other-window)
7669 (setq other-window other))))
7670 (or (and other-window-shows-buffer
7671 (window--display-buffer buffer other-window 'reuse alist))
7672 (and (setq other-window
7673 (window--try-to-split-window-in-direction
7674 window direction alist))
7675 (window--display-buffer buffer other-window 'window alist))
7676 (and (setq window other-window)
7677 (not (window-dedicated-p other-window))
7678 (not (window-minibuffer-p other-window))
7679 (window--display-buffer buffer other-window 'reuse alist)))))))
7680
7681;; This should be rewritten as
7682;; (display-buffer-in-direction buffer (cons '(direction . below) alist))
7537(defun display-buffer-below-selected (buffer alist) 7683(defun display-buffer-below-selected (buffer alist)
7538 "Try displaying BUFFER in a window below the selected window. 7684 "Try displaying BUFFER in a window below the selected window.
7539If there is a window below the selected one and that window 7685If there is a window below the selected one and that window
@@ -7589,6 +7735,8 @@ must also contain a 'window-height' entry with the same value."
7589 (display-buffer--maybe-pop-up-frame buffer alist) 7735 (display-buffer--maybe-pop-up-frame buffer alist)
7590 (display-buffer-at-bottom buffer alist)))) 7736 (display-buffer-at-bottom buffer alist))))
7591 7737
7738;; This should be rewritten as
7739;; (display-buffer-in-direction buffer (cons '(direction . bottom) alist))
7592(defun display-buffer-at-bottom (buffer alist) 7740(defun display-buffer-at-bottom (buffer alist)
7593 "Try displaying BUFFER in a window at the bottom of the selected frame. 7741 "Try displaying BUFFER in a window at the bottom of the selected frame.
7594This either reuses such a window provided it shows BUFFER 7742This either reuses such a window provided it shows BUFFER