diff options
Diffstat (limited to 'lisp/window.el')
-rw-r--r-- | lisp/window.el | 324 |
1 files changed, 145 insertions, 179 deletions
diff --git a/lisp/window.el b/lisp/window.el index 88675c0862..91412cd549 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -4498,53 +4498,44 @@ BUFFER-OR-NAME and return that buffer." buffer)) (current-buffer))) -(defvar display-buffer-alist nil +(defvar display-buffer-alist + '(("\\`\\*\\(scheme\\|ielm\\|shell\\|\\(unsent \\)?mail\\|inferior-lisp\ +\\|Customiz.*\\|info\\|rlogin-.*\\|telnet-.*\\|rsh-.*\\|gud-.*\\)\\*\\(<[0-9]+>\\)?" + . (display-buffer-same-window))) "Alist of conditional actions for `display-buffer'. This is a list of elements (CONDITION . ACTION), where: CONDITION is either a regexp matching buffer names, or a function that takes a buffer and returns a boolean. - ACTION is a cons cell (FUNCTION . ALIST), where FUNCTION is - either a function or a list of functions. Each such function - should accept 2 arguments: a buffer to display and an alist of - the same form as ALIST. It should return the window used, or - nil if it fails to display the window. See `display-buffer' - for more details. - -Usable action functions include: - `display-buffer-reuse-selected-window' - `display-buffer-same-window' - `display-buffer-maybe-same-window' - `display-buffer-reuse-window' - `display-buffer-pop-up-frame' - `display-buffer-pop-up-window' - `display-buffer-reuse-or-pop-window' - `display-buffer-use-some-window' - -The above functions recognize the following alist entries: - - `inhibit-same-window', if non-nil, prevents the same window - from being used for display. - - `reuse-frame' specifies the frames that can be searched for a - window displaying the buffer. Its values have the same - meaning as the ALL-FRAMES arg to `get-buffer-window-list'.") + ACTION is a cons cell (FUNCTION . ALIST), where FUNCTION is a + function or a list of functions. Each such function should + accept 2 arguments: a buffer to display and an alist of the + same form as ALIST. See `display-buffer' for details.") +(put 'display-buffer-alist 'risky-local-variable t) (defvar display-buffer-default-action - '((display-buffer-reuse-selected-window - display-buffer-maybe-same-window - display-buffer-reuse-or-pop-window + '((display-buffer-maybe-same-window + display-buffer-reuse-window + display-buffer--special + display-buffer--maybe-pop-up-frame-or-window display-buffer-use-some-window - ;; If all else fails, pop up a new frame regardless of - ;; restrictions. + ;; If all else fails, pop up a new frame. display-buffer-pop-up-frame)) "List of default actions for `display-buffer'. -It should be a cons cell of the form (FUNCTION . ALIST), which -has the same meaning as in `display-buffer-alist'.") +It should be a cons cell (FUNCTION . ALIST), where FUNCTION is a +function or a list of functions. Each function should accept 2 +arguments: a buffer to display and an alist of the same form as +ALIST. See `display-buffer' for details.") +(put 'display-buffer-default-action 'risky-local-variable t) (defvar display-buffer-overriding-action nil "Overriding action to perform to display a buffer. -If non-nil, it should be a cons cell (FUNCTION . ALIST), which -has the same meaning as in `display-buffer-alist'.") +If non-nil, it should be a cons cell (FUNCTION . ALIST), where +FUNCTION is a function or a list of functions. Each function +should accept 2 arguments: a buffer to display and an alist of +the same form as ALIST. See `display-buffer' for details.") +(put 'display-buffer-overriding-action 'risky-local-variable t) (defun display-buffer-assq-regexp (buffer-name alist) "Retrieve ALIST entry corresponding to BUFFER-NAME." @@ -4558,6 +4549,21 @@ has the same meaning as in `display-buffer-alist'.") (funcall key buffer-name alist))) (throw 'match (cdr entry))))))) +(defvar display-buffer--same-window-action + '(display-buffer-same-window + (inhibit-same-window . nil)) + "A `display-buffer' action for displaying in the same window.") +(put 'display-buffer--same-window-action 'risky-local-variable t) + +(defvar display-buffer--other-frame-action + '((display-buffer-reuse-window + display-buffer--special + display-buffer-pop-up-frame) + (reusable-frames . 0) + (inhibit-same-window . t)) + "A `display-buffer' action for displaying in another frame.") +(put 'display-buffer--other-frame-action 'risky-local-variable t) + (defun display-buffer (&optional buffer-or-name action frame) "Display BUFFER-OR-NAME in some window. BUFFER-OR-NAME must be a buffer or the name of an existing @@ -4570,12 +4576,29 @@ function is called with 2 arguments: the buffer to display and an alist. It should either display the buffer and return the window, or return nil if it is unable to display the buffer. -`display-buffer' constructs a list of action functions and an -action alist by combining `display-buffer-overriding-action', -`display-buffer-alist', the ACTION argument, and -`display-buffer-default-action' (in that order). It calls each -action function in turn, passing the combined action alist as the -second argument, until one of the functions returns non-nil. +`display-buffer' builds a function list and an alist from +`display-buffer-overriding-action', `display-buffer-alist', +ACTION, and `display-buffer-default-action' (in that order). +Then it calls each function in the combined function list in +turn, passing the buffer as the first argument and the combined +alist as the second argument, until a function returns non-nil. + +Available action functions include: + `display-buffer-same-window' + `display-buffer-maybe-same-window' + `display-buffer-reuse-window' + `display-buffer-pop-up-frame' + `display-buffer-pop-up-window' + `display-buffer-use-some-window' + +Recognized alist entries include: + + `inhibit-same-window' -- A non-nil value prevents the same + window from being used for display. + + `reusable-frames' -- Value specifies frame(s) to search for a + window that already displays the buffer. + See `display-buffer-reuse-window'. The ACTION argument to `display-buffer' can also have a non-nil and non-list value. This means to display the buffer in a window @@ -4583,14 +4606,10 @@ other than the selected one, even if it is already displayed in the selected window. If called interactively with a prefix argument, ACTION is t. -Optional argument FRAME specifies where to look for a window that -already displays the buffer. If nil, check only the selected -frame (actually the last non-minibuffer frame), except if -`display-buffer-reuse-frames' or `pop-up-frames' is non-nil -\(non-nil and not graphic-only on a text-only terminal), in which -case check all visible or iconified frames. Otherwise, FRAME can -be a specific frame, `visible' (all visible frames), 0 (all -frames on the current terminal), or t (all frames)." +Optional argument FRAME, if non-nil, acts like an additional +ALIST entry (reusable-frames . FRAME), specifying the frame(s) to +search for a window that is already displaying the buffer. See +`display-buffer-reuse-window'." (interactive (list (read-buffer "Display buffer: " (other-buffer)) (if current-prefix-arg t))) (let ((buffer (window-normalize-buffer-to-display buffer-or-name)) @@ -4609,7 +4628,7 @@ frames on the current terminal), or t (all frames)." (cons nil (append (if inhibit-same-window '((inhibit-same-window . t))) (if frame - `((reuse-frame . ,frame)))))) + `((reusable-frames . ,frame)))))) ;; Construct action function list and action alist. (actions (list display-buffer-overriding-action user-action action extra-action @@ -4633,45 +4652,16 @@ frames on the current terminal), or t (all frames)." This uses the function `display-buffer' as a subroutine; see its documentation for additional customization information." (interactive "BDisplay buffer in other frame: ") - (let ((pop-up-frames t) - same-window-buffer-names same-window-regexps - ;;(old-window (selected-window)) - new-window) - (setq new-window (display-buffer buffer t)) - ;; This may have been here in order to prevent the new frame from hiding - ;; the old frame. But it does more harm than good. - ;; Maybe we should call `raise-window' on the old-frame instead? --Stef - ;;(lower-frame (window-frame new-window)) - - ;; This may have been here in order to make sure the old-frame gets the - ;; focus. But not only can it cause an annoying flicker, with some - ;; window-managers it just makes the window invisible, with no easy - ;; way to recover it. --Stef - ;;(make-frame-invisible (window-frame old-window)) - ;;(make-frame-visible (window-frame old-window)) - )) + (display-buffer buffer display-buffer--other-frame-action t)) ;;; `display-buffer' action functions: -(defun display-buffer-reuse-selected-window (buffer alist) - "Try to display BUFFER in the selected window if it is already there. -If this succeeds, return the selected window. - -This fails if BUFFER is not displayed in the selected window, or -if ALIST has a non-nil `inhibit-same-window' entry. In that -case, return nil." - (when (and (not (cdr (assq 'inhibit-same-window alist))) - (eq buffer (window-buffer))) - (display-buffer-record-window 'reuse-window (selected-window) buffer) - (window--display-buffer-1 (selected-window)))) - (defun display-buffer-same-window (buffer alist) - "Try to display BUFFER in the selected window. -If this succeeds, return the selected window. - -This fails if the selected window is a minibuffer window or is -dedicated to another buffer, or if ALIST has a non-nil -`inhibit-same-window' entry. In that case, return nil." + "Display BUFFER in the selected window. +This fails if ALIST has a non-nil `inhibit-same-window' entry, or +if the selected window is a minibuffer window or is dedicated to +another buffer; in that case, return nil. Otherwise, return the +selected window." (unless (or (cdr (assq 'inhibit-same-window alist)) (window-minibuffer-p) (window-dedicated-p)) @@ -4679,42 +4669,66 @@ dedicated to another buffer, or if ALIST has a non-nil (window--display-buffer-2 buffer (selected-window)))) (defun display-buffer-maybe-same-window (buffer alist) - "Try to display BUFFER in the selected window. -This acts like `display-buffer-same-window', except that it also -fails if `same-window-p' returns nil for this buffer." + "Conditionally display BUFFER in the selected window. +If `same-window-p' returns non-nil for BUFFER's name, call +`display-buffer-same-window' and return its value. Otherwise, +return nil." (and (same-window-p (buffer-name buffer)) (display-buffer-same-window buffer alist))) (defun display-buffer-reuse-window (buffer alist) "Return a window that is already displaying BUFFER. -If no usable window is found, return nil. - -If ALIST has a non-nil `inhibit-same-window' entry, the same -window cannot be reused. - -If ALIST contains a `reuse-frame' entry, that determines the -frames to check for a window displaying the buffer. If the entry -is omitted or the value is nil, check only this frame. The value -can also be a specific frame, `visible' (all visible frames), -0 (all frames on the current terminal), or t (all frames)." - (let* ((can-use-selected-window - (not (cdr (assq 'inhibit-same-window alist)))) - (frames (or (cdr (assq 'reuse-frame alist)) - (last-nonminibuffer-frame))) - (window (catch 'found - (dolist (window (get-buffer-window-list - buffer 'nomini frames)) - (when (or can-use-selected-window - (not (eq (selected-window) window))) - (throw 'found window)))))) +Return nil if no usable window is found. + +If ALIST has a non-nil `inhibit-same-window' entry, the selected +window is not eligible for reuse. + +If ALIST contains a `reusable-frames' entry, its value determines +which frames to search for a reusable window: + nil -- the selected frame (actually the last non-minibuffer frame) + A frame -- just that frame + `visible' -- all visible frames + 0 -- all frames on the current terminal + t -- all frames. + +If ALIST contains no `reusable-frames' entry, search just the +selected frame if `display-buffer-reuse-frames' and +`pop-up-frames' are both nil; search all frames on the current +terminal if either of those variables is non-nil." + (let* ((alist-entry (assq 'reusable-frames alist)) + (frames (cond (alist-entry (cdr alist-entry)) + ((if (eq pop-up-frames 'graphic-only) + (display-graphic-p) + pop-up-frames) + 0) + (display-buffer-reuse-frames 0) + (t (last-nonminibuffer-frame)))) + (window (if (and (eq buffer (window-buffer)) + (not (cdr (assq 'inhibit-same-window alist)))) + (selected-window) + (car (delq (selected-window) + (get-buffer-window-list buffer 'nomini + frames)))))) (when window (display-buffer-record-window 'reuse-window window buffer) (window--display-buffer-1 window)))) +(defun display-buffer--special (buffer alist) + "Try to display BUFFER using `special-display-function'. +Call `special-display-p' on BUFFER's name, and if that returns +non-nil, call `special-display-function' on BUFFER." + (and special-display-function + ;; `special-display-p' returns either t or a list of frame + ;; parameters to pass to `special-display-function'. + (let ((pars (special-display-p (buffer-name buffer)))) + (when pars + (funcall special-display-function + buffer (if (listp pars) pars)))))) + (defun display-buffer-pop-up-frame (buffer alist) "Display BUFFER in a new frame. -This works by calling `pop-up-frame-function'. If sucessful, -return the window on the new frame; otherwise return nil." +This works by calling `pop-up-frame-function'. If successful, +return the window used; otherwise return nil." (let ((fun pop-up-frame-function) frame window) (when (and fun @@ -4752,42 +4766,20 @@ If sucessful, return the new window; otherwise return nil." (set-window-prev-buffers window nil) window))) -;; This display action function groups together some lower-level ones: -(defun display-buffer-reuse-or-pop-window (buffer alist) - "Display BUFFER in some window other than the selected one. -This attempts to call the following functions (in order): - - `display-buffer-reuse-window', ensuring that it checks all - frames on this terminal if `display-buffer-reuse-frames' or - `pop-up-frames' is non-nil. - - `special-display-function', if it is available. - - `display-buffer-pop-up-frame', if specified by `pop-up-frames'. - - `display-buffer-pop-up-window', if specified by `pop-up-windows'. - -If BUFFER is sucessfully display, return its window; otherwise -return nil." - (let ((use-pop-up-frames (if (eq pop-up-frames 'graphic-only) - (display-graphic-p) - pop-up-frames))) - (or (display-buffer-reuse-window - buffer - ;; If `display-buffer-reuse-frames' or `pop-up-frames' is - ;; non-nil, check all frames on this terminal. - (if (and (null (cdr (assq 'reuse-frame alist))) - (or use-pop-up-frames display-buffer-reuse-frames)) - (cons '(reuse-frame . 0) alist) - alist)) - ;; Try with `special-display-function': - (and special-display-function - ;; `special-display-p' returns either t or a list of frame - ;; parameters to pass to `special-display-function'. - (let ((pars (special-display-p (buffer-name buffer)))) - (when pars - (funcall special-display-function - buffer (if (listp pars) pars))))) - (and use-pop-up-frames - (display-buffer-pop-up-frame buffer alist)) - (and pop-up-windows - (display-buffer-pop-up-window buffer alist))))) +(defun display-buffer--maybe-pop-up-frame-or-window (buffer alist) + "Try displaying BUFFER based on `pop-up-frames' or `pop-up-windows'. + +If `pop-up-frames' is non-nil (and not `graphic-only' on a +text-only terminal), try with `display-buffer-pop-up-frame'. + +If that cannot be done, and `pop-up-windows' is non-nil, try +again with `display-buffer-pop-up-window'." + (or (and (if (eq pop-up-frames 'graphic-only) + (display-graphic-p) + pop-up-frames) + (display-buffer-pop-up-frame buffer alist)) + (and pop-up-windows + (display-buffer-pop-up-window buffer alist)))) (defun display-buffer-use-some-window (buffer alist) "Display BUFFER in an existing window. @@ -4803,10 +4795,7 @@ return the window. If no suitable window is found, return nil." (selected-window))) (frame (or (window--frame-usable-p (selected-frame)) (window--frame-usable-p (last-nonminibuffer-frame)))) - (use-pop-up-frames (if (eq pop-up-frames 'graphic-only) - (display-graphic-p) - pop-up-frames)) - window popped-up-frame) + window) (unwind-protect (setq window ;; Reuse an existing window. @@ -4820,17 +4809,12 @@ return the window. If no suitable window is found, return nil." (unless (and not-this-window (eq window (selected-window))) window)) - (get-largest-window 0) - (and use-pop-up-frames - (prog1 - (frame-selected-window (funcall pop-up-frame-function)) - (setq popped-up-frame t))))) + (get-largest-window 0))) (when (window-live-p window-to-undedicate) ;; Restore dedicated status of selected window. (set-window-dedicated-p window-to-undedicate nil))) (when window - (display-buffer-record-window - (if popped-up-frame 'pop-up-frame 'reuse-window) window buffer) + (display-buffer-record-window 'reuse-window window buffer) (window--even-window-heights window) (window--display-buffer-2 buffer window)))) @@ -4857,13 +4841,11 @@ Optional third arg NORECORD non-nil means do not put this buffer at the front of the list of recently selected ones." (interactive (list (read-buffer "Pop to buffer: " (other-buffer)) (if current-prefix-arg t))) - (setq buffer (window-normalize-buffer-to-display - ;; BUFFER nil means another buffer. - (or buffer (other-buffer)))) + (setq buffer (window-normalize-buffer-to-switch-to buffer)) (set-buffer buffer) (let* ((old-window (selected-window)) (old-frame (selected-frame)) - (window (display-buffer (current-buffer) action)) + (window (display-buffer buffer action)) (frame (window-frame window))) (if (eq frame old-frame) ;; Make sure new window is selected (Bug#8615), (Bug#6954). @@ -4937,18 +4919,7 @@ Return the buffer switched to." (list (read-buffer-to-switch "Switch to buffer: ") nil nil)) (let ((buffer (window-normalize-buffer-to-switch-to buffer-or-name))) (if (null force-same-window) - (cond - ((eq buffer (window-buffer)) - (unless norecord - (select-window (selected-window))) - (set-buffer buffer)) - ((or (window-minibuffer-p) (window-dedicated-p)) - (pop-to-buffer buffer)) - (t - (set-window-buffer nil buffer) - (unless norecord - (select-window (selected-window))) - (set-buffer buffer))) + (pop-to-buffer buffer display-buffer--same-window-action norecord) (cond ;; Don't call set-window-buffer if it's not needed since it ;; might signal an error (e.g. if the window is dedicated). @@ -4984,10 +4955,8 @@ This uses the function `display-buffer' as a subroutine; see its documentation for additional customization information." (interactive (list (read-buffer-to-switch "Switch to buffer in other window: "))) - (let ((buffer (window-normalize-buffer-to-switch-to buffer-or-name)) - (pop-up-windows t) - same-window-buffer-names same-window-regexps) - (pop-to-buffer buffer t norecord))) + (let ((pop-up-windows t)) + (pop-to-buffer buffer-or-name t norecord))) (defun switch-to-buffer-other-frame (buffer-or-name &optional norecord) "Switch to buffer BUFFER-OR-NAME in another frame. @@ -5010,10 +4979,7 @@ This uses the function `display-buffer' as a subroutine; see its documentation for additional customization information." (interactive (list (read-buffer-to-switch "Switch to buffer in other frame: "))) - (let ((buffer (window-normalize-buffer-to-switch-to buffer-or-name)) - (pop-up-frames t) - same-window-buffer-names same-window-regexps) - (pop-to-buffer buffer t norecord))) + (pop-to-buffer buffer-or-name display-buffer--other-frame-action norecord)) (defun set-window-text-height (window height) "Set the height in lines of the text display area of WINDOW to HEIGHT. |