From: Martin Rudalics Date: Fri, 16 Nov 2012 10:29:48 +0000 (+0100) Subject: Fix some display-buffer related issues. X-Git-Tag: emacs-24.2.90~67 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=0ff7851c6b4fa2e5c085ee8a42bbe7ccb16b115e;p=emacs.git Fix some display-buffer related issues. * window.el (enlarge-window, shrink-window): Don't mention return value in doc-string (Bug#12896). (window--display-buffer): Don't resize frames - it won't work with all window managers and defeat pop-up-frame-alist. (display-buffer-alist): In doc-string explain that CONDITION can be a function and which arguments are passed to it (Bug#12854). (display-buffer-assq-regexp): New argument ACTION. Handle lambda expressions (Bug#12854). (display-buffer): Pass ACTION argument to display-buffer-assq-regexp. * windows.texi (Choosing Window): Rewrite description of display-buffer-alist (Bug#12167). (Display Action Functions): Mention inhibit-switch-frame. Fix description of display-buffer-below-selected. Reorder actions. Add example (Bug#12848). --- diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index 89b456f5c22..062692ee9f3 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@ -1,3 +1,11 @@ +2012-11-16 Martin Rudalics + + * windows.texi (Choosing Window): Rewrite description of + display-buffer-alist (Bug#12167). + (Display Action Functions): Mention inhibit-switch-frame. Fix + description of display-buffer-below-selected. Reorder actions. + Add example (Bug#12848). + 2012-11-15 Stefan Monnier * keymaps.texi (Translation Keymaps): Add a subsection "Interaction diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index bb02b1d54fd..77f1ff9a179 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -1766,6 +1766,7 @@ Like @code{switch-to-buffer}, this function updates the buffer list unless @var{norecord} is non-@code{nil}. @end deffn + @node Choosing Window @section Choosing a Window for Display @@ -1851,10 +1852,14 @@ default value is empty, i.e. @code{(nil . nil)}. @end defvar @defopt display-buffer-alist -The value of this option is an alist mapping regular expressions to -display actions. If the name of the buffer passed to -@code{display-buffer} matches a regular expression in this alist, then -@code{display-buffer} uses the corresponding display action. +The value of this option is an alist mapping conditions to display +actions. Each condition may be either a regular expression matching a +buffer name or a function that takes two arguments - a buffer name and +the @var{action} argument passed to @code{display-buffer}. If the name +of the buffer passed to @code{display-buffer} either matches a regular +expression in this alist or the function specified by a condition +returns non-@code{nil}, then @code{display-buffer} uses the +corresponding display action to display the buffer. @end defopt @defopt display-buffer-base-action @@ -1868,6 +1873,7 @@ This display action specifies the fallback behavior for @code{display-buffer} if no other display actions are given. @end defvr + @node Display Action Functions @section Action Functions for @code{display-buffer} @@ -1911,8 +1917,9 @@ normally searches just the selected frame; however, if the variable @code{pop-up-frames} is non-@code{nil}, it searches all frames on the current terminal. @xref{Choosing Window Options}. -If this function chooses a window on another frame, it makes that -frame visible and raises it if necessary. +If this function chooses a window on another frame, it makes that frame +visible and, unless @var{alist} contains an @code{inhibit-switch-frame} +entry (@pxref{Choosing Window Options}), raises that frame if necessary. @end defun @defun display-buffer-pop-up-frame buffer alist @@ -1976,16 +1983,12 @@ reason (e.g. if there is just one frame and it has an @code{unsplittable} frame parameter; @pxref{Buffer Parameters}). @end defun -@defun display-buffer-use-some-window buffer alist -This function tries to display @var{buffer} by choosing an existing -window and displaying the buffer in that window. It can fail if all -windows are dedicated to another buffer (@pxref{Dedicated Windows}). -@end defun - @defun display-buffer-below-selected buffer alist This function tries to display @var{buffer} in a window below the -selected window. This means to either split the selected window or -reuse the window below the selected one. +selected window. This means to either split the selected window or use +the window below the selected one. If it does create a new window, it +will also adjust its size provided @var{alist} contains a suitable +@code{window-height} or @code{window-width} entry, see above. @end defun @defun display-buffer-in-previous-window buffer alist @@ -2001,6 +2004,83 @@ specified by that entry will override any other window found by the methods above, even if that window never showed @var{buffer} before. @end defun +@defun display-buffer-use-some-window buffer alist +This function tries to display @var{buffer} by choosing an existing +window and displaying the buffer in that window. It can fail if all +windows are dedicated to another buffer (@pxref{Dedicated Windows}). +@end defun + +To illustrate the use of action functions, consider the following +example. + +@example +@group +(display-buffer + (get-buffer-create "*foo*") + '((display-buffer-reuse-window + display-buffer-pop-up-window + display-buffer-pop-up-frame) + (reusable-frames . 0) + (window-height . 10) (window-width . 40))) +@end group +@end example + +@noindent +Evaluating the form above will cause @code{display-buffer} to proceed as +follows: If `*foo*' already appears on a visible or iconified frame, it +will reuse its window. Otherwise, it will try to pop up a new window +or, if that is impossible, a new frame. If all these steps fail, it +will try to use some existing window. + + Furthermore, @code{display-buffer} will try to adjust a reused window +(provided `*foo*' was put by @code{display-buffer} there before) or a +popped-up window as follows: If the window is part of a vertical +combination, it will set its height to ten lines. Note that if, instead +of the number ``10'', we specified the function +@code{fit-window-to-buffer}, @code{display-buffer} would come up with a +one-line window to fit the empty buffer. If the window is part of a +horizontal combination, it sets its width to 40 columns. Whether a new +window is vertically or horizontally combined depends on the shape of +the window split and the values of +@code{split-window-preferred-function}, @code{split-height-threshold} +and @code{split-width-threshold} (@pxref{Choosing Window Options}). + + Now suppose we combine this call with a preexisting setup for +`display-buffer-alist' as follows. + +@example +@group +(let ((display-buffer-alist + (cons + '("\\*foo\\*" + (display-buffer-reuse-window display-buffer-below-selected) + (reusable-frames) + (window-height . 5)) + display-buffer-alist))) + (display-buffer + (get-buffer-create "*foo*") + '((display-buffer-reuse-window + display-buffer-pop-up-window + display-buffer-pop-up-frame) + (reusable-frames . 0) + (window-height . 10) (window-width . 40)))) +@end group +@end example + +@noindent +Evaluating this form will cause @code{display-buffer} to first try +reusing a window showing @code{*foo*} on the selected frame. +If no such window exists, it will try to split the selected window or, +if that is impossible, use the window below the selected window. + + If there's no window below the selected one, or the window below the +selected one is dedicated to its buffer, @code{display-buffer} will +proceed as described in the previous example. Note, however, that when +it tries to adjust the height of any reused or popped-up window, it will +in any case try to set its number of lines to ``5'' since that value +overrides the corresponding specification in the @var{action} argument +of @code{display-buffer}. + @node Choosing Window Options @section Additional Options for Displaying Buffers diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 74d66809d55..a267c726986 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,16 @@ +2012-11-16 Martin Rudalics + + * window.el (enlarge-window, shrink-window): Don't mention return + value in doc-string (Bug#12896). + (window--display-buffer): Don't resize frames - it won't work + with all window managers and defeat pop-up-frame-alist. + (display-buffer-alist): In doc-string explain that CONDITION can + be a function and which arguments are passed to it (Bug#12854). + (display-buffer-assq-regexp): New argument ACTION. Handle lambda + expressions (Bug#12854). + (display-buffer): Pass ACTION argument to + display-buffer-assq-regexp. + 2012-11-16 Glenn Morris * window.el (fit-frame-to-buffer-bottom-margin) diff --git a/lisp/window.el b/lisp/window.el index c9ea8351e8c..9ac3a4ecda0 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -2571,8 +2571,7 @@ move it as far as possible in the desired direction." Interactively, if no argument is given, make the selected window one line taller. If optional argument HORIZONTAL is non-nil, make selected window wider by DELTA columns. If DELTA is -negative, shrink selected window by -DELTA lines or columns. -Return nil." +negative, shrink selected window by -DELTA lines or columns." (interactive "p") (let ((minibuffer-window (minibuffer-window))) (cond @@ -2605,8 +2604,7 @@ Interactively, if no argument is given, make the selected window one line smaller. If optional argument HORIZONTAL is non-nil, make selected window narrower by DELTA columns. If DELTA is negative, enlarge selected window by -DELTA lines or columns. -Also see the `window-min-height' variable. -Return nil." +Also see the `window-min-height' variable." (interactive "p") (let ((minibuffer-window (minibuffer-window))) (cond @@ -5176,11 +5174,12 @@ is higher than WINDOW." (error nil)))) (defun window--display-buffer (buffer window type &optional alist dedicated) - "Display BUFFER in WINDOW and make its frame visible. + "Display BUFFER in WINDOW. TYPE must be one of the symbols `reuse', `window' or `frame' and -is passed unaltered to `display-buffer-record-window'. Set -`window-dedicated-p' to DEDICATED if non-nil. Return WINDOW if -BUFFER and WINDOW are live." +is passed unaltered to `display-buffer-record-window'. ALIST is +the alist argument of `display-buffer'. Set `window-dedicated-p' +to DEDICATED if non-nil. Return WINDOW if BUFFER and WINDOW are +live." (when (and (buffer-live-p buffer) (window-live-p window)) (display-buffer-record-window type window buffer) (unless (eq buffer (window-buffer window)) @@ -5193,10 +5192,10 @@ BUFFER and WINDOW are live." (let ((parameter (window-parameter window 'quit-restore)) (height (cdr (assq 'window-height alist))) (width (cdr (assq 'window-width alist)))) - (when (or (memq type '(window frame)) + (when (or (eq type 'window) (and (eq (car parameter) 'same) - (memq (nth 1 parameter) '(window frame)))) - ;; Adjust height of new window or frame. + (eq (nth 1 parameter) 'window))) + ;; Adjust height of window if asked for. (cond ((not height)) ((numberp height) @@ -5207,19 +5206,12 @@ BUFFER and WINDOW are live." (* (window-total-size (frame-root-window window)) height)))) (delta (- new-height (window-total-size window)))) - (cond - ((and (window--resizable-p window delta nil 'safe) - (window-combined-p window)) - (window-resize window delta nil 'safe)) - ((or (eq type 'frame) - (and (eq (car parameter) 'same) - (eq (nth 1 parameter) 'frame))) - (set-frame-height - (window-frame window) - (+ (frame-height (window-frame window)) delta)))))) + (when (and (window--resizable-p window delta nil 'safe) + (window-combined-p window)) + (window-resize window delta nil 'safe)))) ((functionp height) (ignore-errors (funcall height window)))) - ;; Adjust width of a window or frame. + ;; Adjust width of window if asked for. (cond ((not width)) ((numberp width) @@ -5230,18 +5222,12 @@ BUFFER and WINDOW are live." (* (window-total-size (frame-root-window window) t) width)))) (delta (- new-width (window-total-size window t)))) - (cond - ((and (window--resizable-p window delta t 'safe) - (window-combined-p window t)) - (window-resize window delta t 'safe)) - ((or (eq type 'frame) - (and (eq (car parameter) 'same) - (eq (nth 1 parameter) 'frame))) - (set-frame-width - (window-frame window) - (+ (frame-width (window-frame window)) delta)))))) + (when (and (window--resizable-p window delta t 'safe) + (window-combined-p window t)) + (window-resize window delta t 'safe)))) ((functionp width) (ignore-errors (funcall width window)))))) + window)) (defun window--maybe-raise-frame (frame) @@ -5301,13 +5287,19 @@ See `display-buffer' for details.") "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. + CONDITION is either a regexp matching buffer names, or a + function that takes two arguments - a buffer name and the + ACTION argument of `display-buffer' - and returns a boolean. ACTION is a cons cell (FUNCTION . ALIST), where FUNCTION is a function or a list of functions. Each such function should accept two arguments: a buffer to display and an alist of the - same form as ALIST. See `display-buffer' for details." + same form as ALIST. See `display-buffer' for details. + +`display-buffer' scans this alist until it either finds a +matching regular expression or the function specified by a +condition returns non-nil. In any of these cases, it adds the +associated action to the list of actions it will try." :type `(alist :key-type (choice :tag "Condition" regexp @@ -5341,15 +5333,16 @@ specified, e.g. by the user options `display-buffer-alist' or `display-buffer-base-action'. See `display-buffer'.") (put 'display-buffer-fallback-action 'risky-local-variable t) -(defun display-buffer-assq-regexp (buffer-name alist) - "Retrieve ALIST entry corresponding to BUFFER-NAME." +(defun display-buffer-assq-regexp (buffer-name alist action) + "Retrieve ALIST entry corresponding to BUFFER-NAME. +ACTION is the action argument passed to `display-buffer'." (catch 'match (dolist (entry alist) (let ((key (car entry))) (when (or (and (stringp key) (string-match-p key buffer-name)) - (and (symbolp key) (functionp key) - (funcall key buffer-name alist))) + (and (functionp key) + (funcall key buffer-name action))) (throw 'match (cdr entry))))))) (defvar display-buffer--same-window-action @@ -5459,8 +5452,8 @@ argument, ACTION is t." (funcall display-buffer-function buffer inhibit-same-window) ;; Otherwise, use the defined actions. (let* ((user-action - (display-buffer-assq-regexp (buffer-name buffer) - display-buffer-alist)) + (display-buffer-assq-regexp + (buffer-name buffer) display-buffer-alist action)) (special-action (display-buffer--special-action buffer)) ;; Extra actions from the arguments to this function: (extra-action