From 1b326d380533194805789c27261bfff23832324f Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Wed, 27 Oct 2010 18:06:55 +0200 Subject: [PATCH] Install and document new buffer display code. * frame.el (pop-up-frame-alist, pop-up-frame-function) (special-display-frame-alist): Make obsolete. * window.el (display-buffer-window-and-buffer) (window--display-buffer-in-window, window--reuse-window) (window--pop-up-window, window--pop-up-frame) (split-window-sensibly, window-sensibly-splittable-p) (window--raise-window-frame, window--usable-frame): Remove. (display-buffer-mark-dedicated, display-buffer-function) (special-display-buffer-names) (special-display-regexps, special-display-p) (special-display-function, same-window-buffer-names) (same-window-regexps, same-window-p, pop-up-frames) (display-buffer-reuse-frames, pop-up-windows) (split-height-threshold, split-width-threshold) (even-window-heights): Make obsolete. (display-buffer-names, display-buffer-regexps): New options. (display-buffer-frame, display-buffer-normalize-specifiers-1) (display-buffer-normalize-specifiers) (display-buffer-adjust-heights, display-buffer-select-window) (display-buffer-in-window, display-buffer-in-lru-buffer-window) (display-buffer-in-lru-window, display-buffer-split-window-1) (display-buffer-split-window, display-buffer-in-new-window) (display-buffer-in-new-frame, normalize-buffer-to-display) (display-buffer-same-window, display-buffer-other-window) (pop-to-buffer-same-window, pop-to-buffer-other-window) (pop-to-buffer-other-frame, normalize-buffer-to-switch-to): New functions. (display-buffer-locations, display-buffer-default-specifiers) (display-buffer-other-window-specifiers) (display-buffer-other-frame-specifiers) (display-buffer-split-specifiers) (display-buffer-side-specifiers): New variables/constants. (display-buffer): Major rewrite. (pop-to-buffer): Rewrite. Default buffer-or-name argument to the current buffer. (switch-to-buffer, switch-to-buffer-other-window) (switch-to-buffer-other-frame): Rewrite. * calendar/calendar.el (calendar-basic-setup): Do not call split-window-horizontally before popping to buffer. Eventually the second argument of pop-to-buffer must be set accordingly. * dired.el (dired-pop-to-buffer): Adapt to new buffer display code. * info.el (Info-revert-find-node, info, info-other-window) (Info-find-node, Info-next, Info-prev, Info-up) (Info-goto-emacs-command-node, Info-speedbar-goto-node): Adapt to new buffer display code. * windows.texi (Displaying Buffers, Switching Buffers): Describe new buffer display code. * frames.texi (Initial Parameters): Fix reference to buffer display section. --- doc/lispref/ChangeLog | 8 + doc/lispref/frames.texi | 4 +- doc/lispref/windows.texi | 977 +++++++++------- lisp/ChangeLog | 53 + lisp/calendar/calendar.el | 4 +- lisp/dired.el | 14 +- lisp/frame.el | 12 + lisp/info.el | 30 +- lisp/window.el | 2243 ++++++++++++++++++++++++++++--------- 9 files changed, 2393 insertions(+), 952 deletions(-) diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index f35986255b3..8c91d392317 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@ -1,3 +1,11 @@ +2010-10-27 Martin Rudalics + + * windows.texi (Displaying Buffers, Switching Buffers): Describe + new buffer display code. + + * frames.texi (Initial Parameters): Fix reference to buffer + display section. + 2010-10-24 Eli Zaretskii * display.texi (Window Systems): Deprecate use of window-system as diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index d7467782cf7..b42a08c5374 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -448,8 +448,8 @@ Setting this variable does not affect existing frames. @end defopt Functions that display a buffer in a separate frame can override the -default parameters by supplying their own parameters. @xref{Definition -of special-display-frame-alist}. +default parameters by supplying their own parameters. +@xref{Displaying Buffers}. If you use options that specify window appearance when you invoke Emacs, they take effect by adding elements to @code{default-frame-alist}. One diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 16662c05c8f..00e46a435c4 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -22,9 +22,9 @@ windows. * Selecting Windows:: The selected window is the one that you edit in. * Cyclic Window Ordering:: Moving around the existing windows. * Buffers and Windows:: Each live window displays the contents of a buffer. +* Displaying Buffers:: How to choose a window for displaying a buffer. * Switching Buffers:: Higher-level functions for switching to a buffer in some window. -* Displaying Buffers:: How to choose a window for displaying a buffer. * Dedicated Windows:: How to avoid displaying another buffer in a specific window. * Window Point:: Each window has its own location of point. @@ -1719,449 +1719,507 @@ in another window. Moreover, they try to restore the window specific start and point positions of buffers which should handle viewing one and the same buffer in multiple windows more easily. +@node Displaying Buffers +@section Choosing a Window for Displaying a Buffer -@node Switching Buffers -@section Switching to a Buffer in Some Window -@cindex switching to a buffer -@cindex popping to a buffer +The basic facility to choose a window and display a buffer in it is +@code{display-buffer}. Many higher-level functions like +@code{pop-to-buffer} (@pxref{Switching Buffers}) and +@code{with-output-to-temp-buffer} (@pxref{Temporary Displays}) work by +calling this function. Here we describe how @code{display-buffer} +works, how to customize its behavior, and how to get rid of the chosen +window once it is no more needed. -In this section we describe convenient functions for switching to a -specified buffer in some window. These functions can also split an -existing window in certain circumstances. In any case, the window -chosen becomes the selected window and the buffer current. +@deffn Command display-buffer &optional buffer-or-name specifiers ignore +This command makes the buffer specified by @var{buffer-or-name} appear +in some window, but it does not necessarily select that window or make +the buffer current. It returns the window chosen to display the buffer +or @code{nil} if no such window can be found. + + The optional argument @var{buffer-or-name} has to specify a buffer or +the name of a buffer and defaults to the current buffer. If +@var{buffer-or-name} is a string that does not name an existing buffer, +@code{display-buffer} creates a buffer with that name. When called +interactively, it prompts for a buffer name in the minibuffer. + + The optional argument @var{specifiers} is usually a list of buffer +display specifiers, see below. For convenience, @var{specifiers} may +also consist of a single location specifier or @code{t}, where the +latter means to display the buffer in any but the selected window. If +@var{specifiers} is @code{nil} or omitted, this means to exclusively use +the values provided by the variables @code{display-buffer-names} and +@code{display-buffer-regexps} described below. If their values are nil +too, default specifiers are used. + +The optional third argument @var{ignore} is ignored. +@end deffn - Do not use the functions in this section in order to make a buffer -current so that a Lisp program can access or modify it; they are too -drastic for that purpose, since they change the display of buffers in -windows, which would be gratuitous and surprise the user. Instead, use -@code{set-buffer} and @code{save-current-buffer} (@pxref{Current -Buffer}), which designate buffers as current for programmed access -without affecting the display of buffers in windows. +Precisely how @code{display-buffer} finds or creates a window depends on +the @var{specifiers} argument and the two variables described next. + +@defopt display-buffer-names +The value of this option is a list associating buffer names with buffer +display specifiers. The @sc{car} of each element of this list is a list +specifying a set of buffer names. A buffer whose name is a member of +that set is handled by @code{display-buffer} according to the list of +specifiers that form the @sc{cdr} of the element. + +@cindex buffer display specifier +@cindex location specifier +A @dfn{buffer display specifier} is a symbol, a cons cell, or a list, +telling @code{display-buffer} where or how to display a given buffer. A +buffer display specifier that is a symbol provides the location where +the buffer shall be displayed. Three location specifiers are +predefined: -@deffn Command switch-to-buffer buffer-or-name &optional norecord -This function makes the buffer specified by @var{buffer-or-name} current -and displays it in the selected window. This means that a human can see -the buffer and subsequent keyboard commands will apply to it. Contrast -this with @code{set-buffer}, which makes @var{buffer-or-name} the -current buffer but does not display it in the selected window; see -@ref{Current Buffer}. +@itemize @bullet +@item +@code{same-window} stands for the selected window, -If called interactively, it prompts for the buffer name using the -minibuffer. The variable @code{confirm-nonexistent-file-or-buffer} -determines whether to request confirmation before creating a new buffer. +@item +@code{same-frame} for a window on the selected frame, -If @var{buffer-or-name} is @code{nil}, @code{switch-to-buffer} chooses a -buffer using @code{other-buffer}. If @var{buffer-or-name} is a string -that does not identify an existing buffer, then a new buffer by that -name is created. The major mode for the new buffer is set according to -the variable @code{major-mode}; see @ref{Auto Major Mode}. +@item +@code{other-frame} for a window on another frame. +@end itemize -When the selected window is the minibuffer window or is strongly -dedicated to its buffer (@pxref{Dedicated Windows}), this function calls -@code{pop-to-buffer} (see below) to display the buffer in some other -window. +Any other symbol with a function definition means to call that function +to display the buffer. The function is called with two arguments - the +buffer to display and a list of specifiers - and is supposed to display +the buffer and return the window used for that purpose. The function is +also responsible for giving the variable +@code{display-buffer-window-and-buffer} a meaningful value, see below +for an explanation. -Normally, the specified buffer is put at the front of the buffer list -(both the selected frame's buffer list and the frame-independent buffer -list, see @ref{The Buffer List}). This affects the operation of -@code{other-buffer}. However, if @var{norecord} is non-@code{nil}, this -is not done. Also, if @var{norecord} is non-@code{nil}, the window -chosen for displaying the buffer is not automatically made the most -recently selected one. + The remaining buffer display specifiers are cons cells or lists whose +@sc{car} is one of the symbols listed next. -@code{switch-to-buffer} is often used interactively, as the binding of -@kbd{C-x b}. It is also used frequently in programs. It returns the -buffer that it switched to. -@end deffn +@itemize @bullet +@item +@code{not-this-window} with a non-@code{nil} @sc{cdr} means that the +selected window shall not be used for displaying the buffer. -The remaining functions described in this section are similar to -@code{switch-to-buffer}, except for the described features. +@item +@code{reuse-buffer-window} specifies whether a window currently showing +the buffer may be returned and which frame that window must be on. The +possible values for the @sc{cdr} and their meanings are: -@deffn Command switch-to-buffer-other-window buffer-or-name &optional norecord -This command makes the buffer specified by @var{buffer-or-name} current -and displays it in a window not currently selected, by using the -function @code{pop-to-buffer} (see below). It returns the buffer -switched to. +@itemize @minus +@item +@code{never} means to never reuse a window showing the buffer. -The currently selected window is absolutely never used to do the job. -If the selected window already displays @var{buffer-or-name}, then it -continues to do so, but another window is nonetheless found to display -it in as well. +@item +@code{nil} means to stay on the selected frame. -The arguments @var{buffer-or-name} and @var{norecord} have the same -meaning as for @code{switch-to-buffer}. -@end deffn +@item +@code{visible} means to consider visible frames only. -@deffn Command switch-to-buffer-other-frame buffer-or-name &optional norecord -This command switches to buffer @var{buffer-or-name} in another frame. -It returns the buffer switched to. +@item +0 (the number zero) means that any such window must be on a visible or +iconified frame. -The arguments @var{buffer-or-name} and @var{norecord} have the same -meaning as for @code{switch-to-buffer}. -@end deffn +@item +@code{t} means the window may be on an arbitrary frame, including +invisible ones. +@end itemize -@deffn Command pop-to-buffer buffer-or-name &optional other-window norecord -This command makes @var{buffer-or-name} the current buffer and switches -to it in some window, preferably not the window previously selected. -The ``popped-to'' window becomes the selected window. Its frame is -given the X server's focus, if possible; see @ref{Input Focus}. The -return value is the buffer that was switched to. - -If either of the variables @code{display-buffer-reuse-frames} or -@code{pop-up-frames} is non-@code{nil}, @code{pop-to-buffer} looks for a -window in any visible frame already displaying the buffer; if there is -one, it selects and returns that window. If no such window exists and -@code{pop-up-frames} is non-@code{nil}, it creates a new frame and -displays the buffer in it. Otherwise, @code{pop-to-buffer} operates -entirely within the selected frame. (If the selected frame has just a -minibuffer, @code{pop-to-buffer} operates within the most recently -selected frame that was not just a minibuffer.) - -If the variable @code{pop-up-windows} is non-@code{nil}, windows may be -split to create a new window that is different from the original window. -For details, see @ref{Displaying Buffers}. - -If @var{other-window} is non-@code{nil}, @code{pop-to-buffer} finds or -creates another window even if @var{buffer-or-name} is already visible -in the selected window. Thus @var{buffer-or-name} could end up -displayed in two windows. On the other hand, if @var{buffer-or-name} is -already displayed in the selected window and @var{other-window} is -@code{nil}, then the selected window is considered sufficient for -displaying @var{buffer-or-name}, so that nothing needs to be done. - -All the variables that affect @code{display-buffer} affect -@code{pop-to-buffer} as well. @xref{Displaying Buffers}. - -The arguments @var{buffer-or-name} and @var{norecord} are handled as -with @code{switch-to-buffer}. -@end deffn + Observe that the @code{not-this-window} specifier (and the +@code{not-this-frame} specifier described below) with a non-@code{nil} +@sc{cdr} forbid reusing the selected window disregarding what is +specified here. -@node Displaying Buffers -@section Choosing a Window for Displaying a Buffer +@item +@code{reuse-other-window} specifies whether a window currently +@emph{not} showing the buffer may be returned and which frame that +window must be on. The possible values for the @sc{cdr} are the same +as for the @code{reuse-buffer-window} specifier. +@end itemize -This section describes the basic facility that chooses a window to -display a buffer in---@code{display-buffer}. Higher-level commands and -functions like @code{pop-to-buffer} (@pxref{Switching Buffers}) and -@code{with-output-to-temp-buffer} (@pxref{Temporary Displays}), use this -as a subroutine. Here we describe how @code{display-buffer} works and -and how to customize it. We also describe a function which allows to -``quit'' the chosen window in a way that tries to restore the window to -its state before the buffer was displayed. +The additional specifiers listed so far are useful if the location +specifier equals @code{same-frame} or @code{other-frame}. The +specifiers we describe next are mainly useful in the @code{same-frame} +case. -@deffn Command display-buffer buffer-or-name &optional not-this-window frame -This command makes the buffer specified by @var{buffer-or-name} appear -in some window, but it does not select that window and does not make the -buffer current. The argument @var{buffer-or-name} must be a buffer or -the name of an existing buffer and defaults to the current buffer. +@itemize @bullet +@item +@code{new-window} specifies how a new window shall be made on the +selected frame. This specifier is a list whose @sc{car} is the symbol +@code{new-window}. The @sc{cdr} consists of window/side pairings, that +is, cons cells whose @sc{car} identifies the window that shall be split. +Currently recognized are the symbols @code{largest}, @code{lru}, +@code{selected}, @code{root} and @code{first} to respectively split the +largest, least recently used, selected, root or first window of the +selected frame. -When called interactively, it prompts for a buffer name in the -minibuffer. The variable `confirm-nonexistent-file-or-buffer' -determines whether to request confirmation before creating a new buffer. -The return value is the window chosen to display that buffer. + The @sc{cdr} of such a pairing specifies on which side of the window +to split the new window shall appear and can be one of the symbols +@code{below}, @code{right}, @code{above}, or @code{left} with the +obvious meanings. If the @sc{cdr} is @code{nil}, the window is split in +a fashion suitable for the current dimensions of the window to split. +If the @sc{cdr} specifies a function, that function is called with two +arguments - the window to split and a list of buffer display specifiers. +The function is supposed to split that window and return the new window. + + The pairings will be tried by @code{display-buffer} in turn until +either a suitable window is found or creating a new window fails. The +default value for the option @code{display-buffer-regexps}, see below, +uses + +@example +@code{(new-window (largest . nil) (lru . nil))} +@end example + +in order to try splitting the largest window first and, if that fails, +the least recently used one. + +@item +The symbols @code{min-height} and @code{min-width}. In this case, the +@sc{cdr} must be a number specifying the minimum height or width of a +new window to display the buffer. An integer number specifies the +minimum number of lines or columns of the new window. A floating point +number gives the minimum fraction of the window's size with respect to +the frame's root window. A new window will be made if and only if it +can be made at least as large as specified by the number. + + Note that @code{min-height} and @code{min-width} (as well as the +specifiers @code{max-height} and @code{max-width} below) restrict the +size of new windows only. Reusing a window or making a new frame is not +affected by these specifiers. + +@item +The symbols @code{max-height} and @code{max-width}. In this case, the +@sc{cdr} must be a number specifying the maximum height or width of any +new window displaying the buffer. An integer number specifies the +maximum number of lines or columns of the new window. A floating point +number gives the maximum fraction of the window's size with respect to +the frame's root window. + + Setting @code{min-height} and @code{max-height} to the same value will +make a window of exactly that height. Conversely, setting +@code{min-width} and @code{max-width} to the same value will produce a +window of that width. Note, however, that specifying the exact size of +a new window might reduce the number of candidate windows that can be +suitably split. + +@item +The symbol @code{split-unsplittable-frame} with a non-@code{nil} +@sc{cdr} allows to split a window on an unsplittable frame. This +specifier should be used in special cases only since frames are usually +unsplittable in order to prevent @code{display-buffer} from splitting +them. + +@item +@code{adjust-height} with the following interpretations for the +@sc{cdr}: + +@itemize @minus +@item +@code{nil} means do not adjust the height of a new window. -If the optional argument @var{not-this-window} is non-@code{nil}, this -means to display the specified buffer in a window other than the -selected one, even if it is already displayed in the selected window. -This can cause the buffer to appear in two windows at once. +@item +The symbol @code{even-window-heights} means to even the height of the +window used for displaying the buffer with the height of the selected +window, provided these windows are full-width and appear above each +other. + +@item +The symbols @code{shrink-window-if-larger-than-buffer} and +@code{fit-window-to-buffer} specify that the new window shall be +adjusted by the homonymous function. -If the optional argument @var{frame} is non-@code{nil}, it specifies -which frames to check when deciding whether the buffer is already -displayed. If the buffer is already displayed in some window on one of -these frames, @code{display-buffer} will simply return that window. -Here are the possible values of @var{frame}: + Observe that a non-@code{nil} value for @code{adjust-height} can +override restrictions given by @code{min-height}, @code{min-width}, +@code{max-height}, and @code{max-width} specifiers. + +@end itemize +@end itemize + +The following specifiers are useful when the location is specified as +@code{other-frame}: @itemize @bullet -@item @code{nil} -means consider windows on the selected frame. -(Actually, the last non-minibuffer frame.) -@item @code{t} -means consider windows on all frames. -@item @code{visible} -means consider windows on all visible frames. -@item 0 -means consider windows on all visible or iconified frames. -@item A frame -means consider windows on that frame only. +@item +@code{not-this-frame} with a non-@code{nil} @sc{cdr} means that the +selected frame shall not be used for displaying the buffer. + +@item +@code{graphic-only} with a non-@code{nil} @sc{cdr} means that a new +frame shall be made on graphic displays only. + +@item +@code{popup-frame-function} together with a valid function as @sc{cdr} +specifies the function for creating a new frame. By default, +@code{make-frame} is called here. The function is called with the +parameters and values provided by the specifier described next. + +@item +@code{popup-frame-alist} followed by an arbitrary number of frame +parameter/value pairs, each given as a cons cell, specifies the +parameters passed to the popup frame function. For convenience, this +specifier is not a cons cell but a list whose first element is the +symbol @code{popup-frame-alist} and whose remaining elements are pairs +of parameters and values. @end itemize -@end deffn -Precisely how @code{display-buffer} finds or creates a window depends on -the variables described below. - -@defopt display-buffer-function -This variable is the most flexible way to customize the behavior of -@code{display-buffer}. If it is non-@code{nil}, it should be a function -that @code{display-buffer} calls to do the work. The function is called -with two arguments, the buffer to display and the @var{not-this-window} -argument of @code{display-buffer}. It should choose or create a window, -display the specified buffer in it, and then return the window. -@end defopt + It's also possible to specify whether the window chosen shall become +dedicated to the buffer (@pxref{Dedicated Windows}). This is +accomplished with the help of a cons cell whose @sc{car} is the symbol +@code{dedicated} and whose @sc{cdr} is one of the following values: -If @code{display-buffer-function} is @code{nil}, the selected window -already displays @var{buffer-or-name}, and @var{not-this-window} is -@code{nil}, @code{display-buffer} simply returns the selected window. -Otherwise, it consults the two options described next in order to decide -whether the buffer specified by @var{buffer-or-name} should appear in -the selected window. - -@defopt same-window-buffer-names -A list of buffer names for buffers that should be displayed in the -selected window. If the buffer's name is in this list, then -@code{display-buffer} displays the buffer in the selected window. -@end defopt +@itemize @bullet +@item +@code{nil} which means to not dedicate the window to the buffer, -@defopt same-window-regexps -A list of regular expressions that specify buffers that should be -displayed in the selected window. If the buffer's name matches any of -the regular expressions in this list, @code{display-buffer} displays the -buffer in the selected window. -@end defopt +@item +@code{weak} which means the window shall be weakly dedicated to +its buffer, or + +@item +@code{t} to strongly dedicate the window to the buffer. +@end itemize -If the selected window is not considered suitable for displaying -@var{buffer-or-name}, @code{display-buffer} will try to find another -window already displaying @var{buffer-or-name}. It will do so, however, -if and only if either the variable @code{pop-up-frames} (see below) is -non-@code{nil} or the following option has been activated. - -@defopt display-buffer-reuse-frames -If this variable is non-@code{nil}, @code{display-buffer} searches -visible and iconified frames for a window displaying -@var{buffer-or-name}. If there is such a window, @code{display-buffer} -makes that window's frame visible, raises it if necessary, and returns -the window. + In general, an application is free to ignore the specifiers of +@code{display-buffer-names} by explicitly passing a non-@code{nil} +second argument to @code{display-buffer}. For any +@code{display-buffer-names} entry one can, however, add a cons cell +whose @sc{car} is the symbol @code{override} and whose @sc{cdr} is +non-@code{nil} to explicitly override the value supplied by the +application. + + Overriding arguments supplied by the calling application is, in +general, not advisable. It permits, for example, to change the +semantics of a command like @code{switch-to-buffer-other-window} by +setting the method specifier to @code{same-window} or +@code{other-frame}. @end defopt -If there is no such window or both @var{display-buffer-reuse-frames} and -@var{pop-up-frames} are @code{nil}, @code{display-buffer} checks whether -@var{buffer-or-name} should be displayed specially according to the -options described next. - -@defopt special-display-buffer-names -A list of buffer names identifying buffers that should be displayed -specially. If the name of @var{buffer-or-name} is in this list, -@code{display-buffer} handles the buffer specially. By default, special -display means to give the buffer a dedicated frame. - -If an element is a list, instead of a string, then the @sc{car} of that -list is the buffer name, and the rest of that list says how to create -the frame. There are two possibilities for the rest of that list (its -@sc{cdr}): It can be an alist, specifying frame parameters, or it can -contain a function and arguments to give to it. (The function's first -argument is always the buffer to be displayed; the arguments from the -list come after that.) +@defopt display-buffer-regexps +The value of this option is a list associating regular expressions with +buffer display specifiers. The @sc{car} of each element of this list is +a list of regular expressions. Buffers whose names match that +expression are displayed according to the list of specifiers +constituting the @sc{cdr} of the element. For a description of the +@sc{cdr} see the description of @code{display-buffer-names} above. -For example: +This variable has the following default value: @example -(("myfile" (minibuffer) (menu-bar-lines . 0))) +(((".*") + same-frame + (reuse-buffer-window) + (largest) (lru) + (min-height . 24) (min-width . 60) + (adjust-height . even-window-heights) + other-frame + (reuse-buffer-window . visible) + (graphic-only . t) + (popup-frame-alist + (height . 24) (width . 80) (unsplittable . t)))) @end example -@noindent -specifies to display a buffer named @samp{myfile} in a dedicated frame -with specified @code{minibuffer} and @code{menu-bar-lines} parameters. - -The list of frame parameters can also use the phony frame parameters -@code{same-frame} and @code{same-window}. If the specified frame -parameters include @code{(same-window . @var{value})} and @var{value} -is non-@code{nil}, that means to display the buffer in the current -selected window. Otherwise, if they include @code{(same-frame . -@var{value})} and @var{value} is non-@code{nil}, that means to display -the buffer in a new window in the currently selected frame. +It means that buffers shall be displayed preferably on the selected +frame. If the buffer is already shown on that frame, +@code{display-buffer} returns the corresponding window. Otherwise, it +tries to split the largest or the least recently used window with the +new window below or on the right of the window that is split. The +minimum height of the new window shall be 24 lines, its minimum width 60 +columns. If a window above or below the selected window is used, the +heights of both windows shall be evened out. + + If these specifiers fail to produce a window, @code{display-buffer} +tries to show the buffer on a new frame unless a window showing the +buffer can be found on some visible frame. The default function to pop +up a new frame (@code{make-frame}) is given three parameters: A height +of 24 lines, a width of 80 columns, and a non-@code{nil} unsplittable +property. On text-only displays, @code{display-buffer} will not try to +show the buffer on another frame. @end defopt -@defopt special-display-regexps -A list of regular expressions specifying buffers that should be -displayed specially. If the buffer's name matches any of the regular -expressions in this list, @code{display-buffer} handles the buffer -specially. By default, special display means to give the buffer a -dedicated frame. + In order to understand how @code{display-buffer} combines the values +of @code{display-buffer-names} and @code{display-buffer-regexps} with +the @var{specifiers} argument consider the following settings. Suppose +the value of @code{display-buffer-names} has been specified as -If an element is a list, instead of a string, then the @sc{car} of the -list is the regular expression, and the rest of the list says how to -create the frame. See @code{special-display-buffer-names} above. -@end defopt +@example +((("*text*") + same-frame (reuse-buffer-window . none) + (new-window (selected . below) (root . below)) + (override . t))) +@end example -@defopt special-display-function -This variable holds the function to call to display a buffer specially. -It receives the buffer as an argument, and should return the window in -which it is displayed. The default value of this variable is -@code{special-display-popup-frame}, see below. -@end defopt +the value of @code{display-buffer-regexps} is the default value, and +@code{display-buffer} is called as -@defun special-display-popup-frame buffer &optional args -This function tries to make @var{buffer} visible in a frame of its own. -If @var{buffer} is already displayed in some window, it makes that -window's frame visible and raises it. Otherwise, it creates a frame -that is dedicated to @var{buffer}. The return value is the window used -to display @var{buffer}. - -If @var{args} is an alist, it specifies frame parameters for the new -frame. If @var{args} is a list whose @sc{car} is a symbol, then -@code{(car @var{args})} is called as a function to actually create and -set up the frame; it is called with @var{buffer} as first argument, and -@code{(cdr @var{args})} as additional arguments. - -This function always uses an existing window displaying @var{buffer}, -whether or not it is in a frame of its own; but if you set up the above -variables in your init file, before @var{buffer} was created, then -presumably the window was previously made by this function. -@end defun - -@defopt special-display-frame-alist -@anchor{Definition of special-display-frame-alist} -This variable holds frame parameters for -@code{special-display-popup-frame} to use when it creates a frame. -@end defopt +@example +(display-buffer "*text*" 'same-window) +@end example -If @var{buffer-or-name} shall not be displayed specially, -@code{display-buffer} will try to pop up a new frame provided the option -described next permits that. - -@defopt pop-up-frames -This variable specifies whether @code{display-buffer} should make new -frames. If it is non-@code{nil}, @code{display-buffer} tries to locate -a window displaying @var{buffer-or-name} on any visible or iconified -frame, see above. If no such window can be found, it makes a new frame, -unless the variable's value is @code{graphic-only} and the selected -frame is not on a graphic display. @xref{Frames}, for more information. -@end defopt +Since the entry from @code{display-buffer-names} matches the buffer name +and has the @code{override} specifier set, @code{display-buffer} will +first try to display the buffer on the selected frame. Reusing any +window showing the buffer is forbidden, so @code{display-buffer} will +try to split either the selected or the frame's root window (if the +frame has only one window these are one and the same window). The +minimum height (width) of the new window is 24 lines (60 columns) and +are taken from @code{display-buffer-regexps} since +@code{display-buffer-names} does not supply any values for these +specifiers. + + If neither of these windows can be split, @code{display-buffer} will +try to display the buffer in the selected window as requested by the +@var{specifiers} argument. If this fails as well, for example, because +the selected window is dedicated to another buffer, +@code{display-buffer} will apply the default specifiers from +@code{display-buffer-regexps} as sketched above. Observe that in this +case @code{display-buffer} will not necessarily try to split the +selected or the frame's root window because the corresponding specifiers +from @code{display-buffer-names} have been already consumed at that +time. + + So the order of precedence is to try the overriding specifiers from +@code{display-buffer-names} first, followed by overriding specifiers +from @code{display-buffer-regexps}. Next come the specifiers from the +@var{specifiers} argument of @code{display-buffer}. Finally, +non-overriding specifiers from @code{display-buffer-names} and +@code{display-buffer-regexps} are tried. + + If neither of these methods is able to produce a suitable window, +@code{display-buffer} applies a number of built-in methods, overriding +specifiers like @code{reuse-buffer-window} or @code{reuse-other-window}, +if necessary. + + In case you observe any unexpected behavior of @code{display-buffer} +keep in mind the following issues: -@defopt pop-up-frame-function -This variable specifies how to make a new frame if @code{pop-up-frames} -is non-@code{nil}. +@itemize @bullet +@item +Specifiers are consumed in the order sketched above. When +@code{display-buffer} applies a location specifier, any specifiers +preceding that location specifier have been consumed already, that is +they do not affect the work of @code{display-buffer} any more. + + Specifiers following a location specifier are applied in the order +given, which means that the value of the first specifier encountered +prevails. If you want to make sure that, for example, buffer windows +are not reused as specified by the default value of +@code{display-buffer-regexps}, use a @code{reuse-buffer-window} +specifier with a @code{none} @sc{cdr} as in the display-buffer-names +example above. -The value of this variable must be a function of no arguments. When -@code{display-buffer} makes a new frame, it does so by calling that -function, which should return a frame. The default value of this -variable is a function that creates a frame using the parameters -specified by @code{pop-up-frame-alist} described next. -@end defopt +@item +Displaying a buffer on a new or other frame will always raise that frame +and give it input focus. This contrasts with earlier definitions of +@code{display-buffer} up to Emacs 22. While not raising the frame seems +like a worthwhile scope in this case, it has not been pursued any longer +due to possible bad interaction with window mangers on various +platforms. -@defopt pop-up-frame-alist -This variable holds an alist specifying frame parameters used by the -default value of @code{pop-up-frame-function} for making new frames. -@xref{Frame Parameters}, for more information about frame parameters. -@end defopt +@item +The customization interface does not allow to assign every conceivable +value to the options @code{display-buffer-names} and +@code{display-buffer-regexps}. You have to set these by hand to achieve +more exotic behavior. +@end itemize -If popping up a new frame is not possible, @code{display-buffer} will -try to split an existing window. + Next we describe how to transcribe the buffer display options of +Emacs 23 with @code{display-buffer-names} and +@code{display-buffer-regexps}. -@defopt pop-up-windows -If this variable is non-@code{nil}, @code{display-buffer} is allowed to -make a new window on the selected frame. (If the selected frame is a -minibuffer-only frame, @code{display-buffer} tries to make a new window -on another frame instead.) If this variable is a non-empty list, that -list has to specify the windows @code{display-buffer} will consider for -splitting. The following entries are supported. +@itemize @bullet +@item +For @code{display-buffer-function} supply the function named there as +location specifier. -@table @code -@item largest -The largest window, that is the window returned by -@code{get-largest-window}, see @ref{Cyclic Window Ordering}. +@item +@code{same-window-buffer-names} and @code{same-window-regexps} are +handled by adding a @code{same-window} specifier. -@item lru -The least recently used window as returned by @code{get-lru-window}, see -@ref{Cyclic Window Ordering}. +@item +For @code{display-buffer-reuse-frames} use the +@code{reuse-buffer-window} specifier with an appropriate @sc{cdr}. -@item selected -The selected window on that frame as returned by -@code{frame-selected-window}, see @ref{Selecting Windows}. +@item +@code{special-display-buffer-names} and @code{special-display-regexps} +are replaced by @code{display-buffer-names} and +@code{display-buffer-names} because, in a sense, all buffers are special +now. -@item root -The frame's root window as returned by @code{frame-root-window}, see -@ref{Frames and Windows}. -@end table +@item +@code{special-display-function} is emulated either by using a function +as location specifier or by setting the @code{pop-up-frame-function} +specifier appropriately. - The default value @code{t} stands for the list `(largest lru)'. This -means that @code{display-buffer} will first try to split the largest -window and, if that fails, the least recently used window. If this -variable is @code{nil}, @code{display-buffer} does not split any window. -@end defopt +@item +@code{special-display-frame-alist} is now handled by the +@code{popup-frame-alist} specifier. -@defopt split-window-preferred-function -This variable must specify a function with one argument, which is a -window. The @code{display-buffer} routines will call this function with -one or more candidate windows when they look for a window to split. The -function is expected to split that window and return the new window. If -the function returns @code{nil}, this means that the argument window -cannot be split. - -The default value of @code{split-window-preferred-function} is the -function @code{split-window-sensibly} described below. If you customize -this option, bear in mind that @code{display-buffer} may call the -specified function once for each element of @code{pop-up-windows}, see -above. +@item +To handle @code{pop-up-frames} use the @code{other-frame} location +specifier and the @code{graphic-only} specifier. -This option affects the behavior of @code{display-buffer} only. Other -functions like @code{split-window} and its relatives are @emph{not} -affected by it. -@end defopt +@item +@code{pop-up-frame-function} has become the homonymous specifier. It +must now handle arguments as specified by the @code{pop-up-frame-alist} +specifier, though. -@defun split-window-sensibly window -This function takes a window as argument and tries to split that window -in a suitable way. The two variables described next are useful for -tuning the behavior of this function. -@end defun - -@defopt split-height-threshold -This variable specifies whether @code{split-window-sensibly} may split -windows vertically. If it is an integer, @code{split-window-sensibly} -tries to split a window vertically only if it has at least this many -lines. If the window has less lines, splitting fails, or the value of -this variable is @code{nil}, @code{split-window-sensibly} will try to -split the window horizontally, subject to restrictions of -@code{split-width-threshold} (see below). - -If splitting horizontally fails too, and the window is the only window -on its frame, @code{split-window-sensibly} will try to split that window -vertically disregarding the value of this variable. If this fails as -well, @code{split-window-sensibly} returns @code{nil}. - -@code{split-window-sensibly} does not split a window vertically when -that window's height is fixed (@pxref{Window Sizes}). Also, it splits a -window vertically only if the space taken up by that window can -accommodate two windows one above the other that are both at least -@code{window-min-height} lines tall. - -Moreover, if the window that shall be split has a mode line, -@code{split-window-sensibly} does not split the window unless the new -window can accomodate a mode line too. However, if the option -@code{window-splits} (@pxref{Splitting Windows}) equals @code{resize}, -@code{split-window-sensibly} may split a window provided the resulting -windows can be embedded in a combination of windows. -@end defopt +@item +@code{pop-up-frame-alist} has become the homonymous specifier. -@defopt split-width-threshold -This variable specifies whether @code{split-window-sensibly} may split -windows horizontally. If it is an integer, @code{split-window-sensibly} -tries to split a window horizontally only if it has at least this many -columns. If it is @code{nil}, @code{split-window-sensibly} will not -split the window horizontally. (It still might split the window -vertically, though, see above.) - -@code{split-window-sensibly} does not split a window horizontally if -that window's width is fixed (@pxref{Window Sizes}). Also, it splits a -window horizontally only if the space that window takes up can -accommodate two windows side by side that are both at least -@code{window-min-width} columns wide. Note, however, that if the option -@code{window-splits} (@pxref{Splitting Windows}) equals @code{resize}, -@code{split-window-sensibly} will split the window provided it can embed -the emanating windows in a window combination. -@end defopt +@item +@code{pop-up-windows} is handled by the @code{new-window} specifier. -If all options described so far fail to produce a suitable window, -@code{display-buffer} tries to reuse an existing window. As a last -resort, it will try to display @var{buffer-or-name} on a separate frame. -In that case, the value of @code{pop-up-frames} is disregarded. - -@defopt even-window-heights -This variable specifies whether @code{display-buffer} should even out -window heights if the buffer gets displayed in an existing window, above -or beneath another window. If @code{even-window-heights} is -non-@code{nil}, the default, window heights will be evened out. If -either of the involved window has fixed height (@pxref{Window Sizes}) or -@code{even-window-heights} is @code{nil}, window heights are left alone. -@end defopt +@item +@code{split-window-preferred-function} can be specified as second +argument of window / side pairings. The semantics of the argument have +not changed. + +@item +@code{split-height-threshold} and +@code{split-width-threshold} are handled by the @code{min-height} and +@code{min-width} specifiers respectively. The sizes you specify there +are, however, no more the original sizes of the window to split but +the desired minimum sizes of the new window. + +@item +@code{even-window-heights} is handled by setting the @sc{cdr} of the +@code{adjust-height} specifier to @code{even-window-heights}. +@end itemize + +The following two functions are simple variations of +@code{display-buffer}. + +@defun display-buffer-same-window &optional buffer-or-name +This function is like @code{display-buffer} but preferably displays the +buffer specified by @var{buffer-or-name} in the selected window. +Another window will be used only if the buffer can't be shown in the +selected window, usually because it is dedicated to some other buffer. +@end defun + +@defun display-buffer-other-window &optional buffer-or-name +This function is like @code{display-buffer} but tries to avoid using the +selected window. The selected window will be used if and only if there +is no other choice. +@end defun + +The following variable conveys some information about the last +@code{display-buffer} action performed and is used mainly when popping +up a @samp{*Help*} buffer. + +@defvar display-buffer-window-and-buffer +After @code{display-buffer} has shown a buffer in some window this +variable should be a cons cell whose @sc{car} denotes the window used to +display the buffer. The @sc{cdr} is either @code{nil} (which means the +same buffer was displayed in that window before), @code{t} (which means +the window was created by @code{display-buffer}), or the buffer +displayed in that window before. + + If the location specifier is one of @code{same-window}, +@code{same-frame}, or @code{other-frame}, the @code{display-buffer} +routines themselves set the value of this variable. See the code of the +function @code{display-buffer-in-window} for how this is done. If the +location specifier is a function, that function becomes responsible for +assigning a meaningful value to this variable. +@end defvar The command described next allows to quit the window chosen by @code{display-buffer} and restore the previous state without undoing @@ -2182,7 +2240,8 @@ According to information stored in @var{window}'s @code{quit-restore} window parameter (@pxref{Window Parameters}) this function performs one of the following actions. -@itemize @bullet +@itemize @bullet + @item Delete @var{window} and its frame. This action is useful when @var{window} was created on a standalone frame and there are other @@ -2211,6 +2270,148 @@ simply puts @var{window}'s buffer at the end of the buffer list. Interactively, @var{kill} is the prefix argument. @end deffn +@node Switching Buffers +@section Switching to a Buffer in Some Window +@cindex switching to a buffer +@cindex popping to a buffer + +In this section we describe convenient functions for switching to a +specified buffer in some window. These functions can also split an +existing window or create a new frame in certain circumstances. In any +case, the window chosen becomes the selected window and the buffer +current. + + Do not use the functions in this section in order to make a buffer +current so that a Lisp program can access or modify it; they are too +drastic for that purpose, since they change the display of buffers in +windows, which would be gratuitous and surprise the user. Instead, use +@code{set-buffer} and @code{save-current-buffer} (@pxref{Current +Buffer}), which designate buffers as current for programmed access +without affecting the display of buffers in windows. + +@deffn Command switch-to-buffer buffer-or-name &optional norecord +This function makes the buffer specified by @var{buffer-or-name} current +and displays it in the selected window. This means that a human can see +the buffer and subsequent keyboard commands will apply to it. Contrast +this with @code{set-buffer}, which makes @var{buffer-or-name} the +current buffer but does not display it in the selected window; see +@ref{Current Buffer}. + +If @var{buffer-or-name} is @code{nil}, @code{switch-to-buffer} chooses a +buffer using @code{other-buffer}. If @var{buffer-or-name} is a string +that does not identify an existing buffer, then a new buffer by that +name is created. The major mode for the new buffer is set according to +the variable @code{major-mode}; see @ref{Auto Major Mode}. + +If called interactively, it prompts for the buffer name using the +minibuffer. The variable @code{confirm-nonexistent-file-or-buffer} +determines whether to request confirmation before creating a new buffer. + +When the selected window is the minibuffer window or is strongly +dedicated to its buffer (@pxref{Dedicated Windows}), this function calls +@code{pop-to-buffer} (see below) to display the buffer in some other +window. + +Normally, the specified buffer is put at the front of the buffer list +(both the selected frame's buffer list and the frame-independent buffer +list, see @ref{The Buffer List}). This affects the operation of +@code{other-buffer}. However, if @var{norecord} is non-@code{nil}, this +is not done. Also, if @var{norecord} is non-@code{nil}, the window +chosen for displaying the buffer is not automatically made the most +recently selected one. + +@code{switch-to-buffer} is often used interactively, as the binding of +@kbd{C-x b}. It returns the buffer that it switched to. +@end deffn + +The next two functions are similar to @code{switch-to-buffer}, except +for the described features. + +@deffn Command switch-to-buffer-other-window buffer-or-name &optional norecord +This command makes the buffer specified by @var{buffer-or-name} current +and displays it in a window not currently selected, by using the +function @code{pop-to-buffer} (see below). It returns the buffer +switched to. + +This function tries hard to avoid using the selected window for doing +the job. If the selected window already displays @var{buffer-or-name}, +then it continues to do so, but another window is nonetheless found to +display it in as well. + +The arguments @var{buffer-or-name} and @var{norecord} have the same +meaning as for @code{switch-to-buffer}. +@end deffn + +@deffn Command switch-to-buffer-other-frame buffer-or-name &optional norecord +This command switches to buffer @var{buffer-or-name} in another frame. +It returns the buffer switched to. + +The arguments @var{buffer-or-name} and @var{norecord} have the same +meaning as for @code{switch-to-buffer}. +@end deffn + +@deffn Command pop-to-buffer buffer-or-name &optional specifiers norecord +This command makes @var{buffer-or-name} the current buffer and switches +to it in some window. The ``popped-to'' window becomes the selected +window. Its frame is given the X server's focus, if possible; see +@ref{Input Focus}. The return value is the buffer that was switched to +or @code{nil} if no suitable window could be found. + + The optional argument @var{buffer-or-name} may be a buffer, a string +(a buffer name), or @code{nil}. If @var{buffer-or-name} is a string not +naming an existent buffer, it creates a buffer with that name. If +@var{buffer-or-name} is @code{nil} or omitted, it displays the current +buffer. + + The optional second argument @var{specifiers} must be a list of +buffer display specifiers or a single location specifier, see the +documentations of @code{display-buffer} and @code{display-buffer-names}. +If @var{specifiers} is @code{t}, it means to pop to the buffer in any +but the selected window. If @var{specifiers} is @code{nil} or omitted, +this means to exclusively use the values provided by +@code{display-buffer-names} and @code{display-buffer-regexps} +(@pxref{Displaying Buffers}). If their values are nil too, default +specifiers are used. + + The optional argument @var{norecord} is handled just as by +@code{switch-to-buffer}. +@end deffn + +The following three commands are similar to @code{pop-to-buffer} but +for the mentioned differences. + +@deffn Command pop-to-buffer-same-window &optional buffer-or-name norecord +This command tries to display the buffer specified by +@var{buffer-or-name} in the selected window. Another window will be +used only if the buffer can't be shown in the selected window, usually +because it is dedicated to another buffer. + + The optional arguments @var{buffer-or-name} and @var{norecord} are as +for @code{pop-to-buffer}. +@end deffn + +@deffn Command pop-to-buffer-other-window &optional buffer-or-name norecord +This command displays the buffer specified by @var{buffer-or-name} in +any but the selected window and selects that window. The selected +window will be used if and only if there is no other choice. Windows on +the selected frame are preferred to windows on other frames. It returns +the buffer specified by @var{buffer-or-name} or @code{nil} if displaying +the buffer failed. + + The optional arguments @var{buffer-or-name} and @var{norecord} are as +for @code{pop-to-buffer}. +@end deffn + +@deffn Command pop-to-buffer-other-frame &optional buffer-or-name norecord +This command displays the buffer specified by @var{buffer-or-name} +preferably on another frame. It selects the window used for displaying +the buffer and returns the buffer specified by @var{buffer-or-name} or +@code{nil} if displaying the buffer failed. + + The optional arguments @var{buffer-or-name} and @var{norecord} are as +for @code{pop-to-buffer}. +@end deffn + @node Dedicated Windows @section Dedicated Windows @cindex dedicated window diff --git a/lisp/ChangeLog b/lisp/ChangeLog index f80a67ee997..e2f0139c55e 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,56 @@ +2010-10-27 Martin Rudalics + + * frame.el (pop-up-frame-alist, pop-up-frame-function) + (special-display-frame-alist): Make obsolete. + + * window.el (display-buffer-window-and-buffer) + (window--display-buffer-in-window, window--reuse-window) + (window--pop-up-window, window--pop-up-frame) + (split-window-sensibly, window-sensibly-splittable-p) + (window--raise-window-frame, window--usable-frame): Remove. + (display-buffer-mark-dedicated, display-buffer-function) + (special-display-buffer-names) + (special-display-regexps, special-display-p) + (special-display-function, same-window-buffer-names) + (same-window-regexps, same-window-p, pop-up-frames) + (display-buffer-reuse-frames, pop-up-windows) + (split-height-threshold, split-width-threshold) + (even-window-heights): Make obsolete. + (display-buffer-names, display-buffer-regexps): New options. + (display-buffer-frame, display-buffer-normalize-specifiers-1) + (display-buffer-normalize-specifiers) + (display-buffer-adjust-heights, display-buffer-select-window) + (display-buffer-in-window, display-buffer-in-lru-buffer-window) + (display-buffer-in-lru-window, display-buffer-split-window-1) + (display-buffer-split-window, display-buffer-in-new-window) + (display-buffer-in-new-frame, normalize-buffer-to-display) + (display-buffer-same-window, display-buffer-other-window) + (pop-to-buffer-same-window, pop-to-buffer-other-window) + (pop-to-buffer-other-frame, normalize-buffer-to-switch-to): New + functions. + (display-buffer-locations, display-buffer-default-specifiers) + (display-buffer-other-window-specifiers) + (display-buffer-other-frame-specifiers) + (display-buffer-split-specifiers) + (display-buffer-side-specifiers): New variables/constants. + (display-buffer): Major rewrite. + (pop-to-buffer): Rewrite. Default buffer-or-name argument to + the current buffer. + (switch-to-buffer, switch-to-buffer-other-window) + (switch-to-buffer-other-frame): Rewrite. + + * calendar/calendar.el (calendar-basic-setup): Do not call + split-window-horizontally before popping to buffer. Eventually + the second argument of pop-to-buffer must be set accordingly. + + * dired.el (dired-pop-to-buffer): Adapt to new buffer display + code. + + * info.el (Info-revert-find-node, info, info-other-window) + (Info-find-node, Info-next, Info-prev, Info-up) + (Info-goto-emacs-command-node, Info-speedbar-goto-node): Adapt + to new buffer display code. + 2010-10-27 Glenn Morris * term/ns-win.el: Restore require of cl when compiling. diff --git a/lisp/calendar/calendar.el b/lisp/calendar/calendar.el index c02e7f5d9bc..1e6b85e5b5d 100644 --- a/lisp/calendar/calendar.el +++ b/lisp/calendar/calendar.el @@ -1330,7 +1330,9 @@ display the generated calendar." ;; the right thing in that case. ;; ;; Is this a wide frame? If so, split it horizontally. - (if (window-sensibly-splittable-p t) (split-window-horizontally)) + + ;; FIXME: Adapt to new splitting code. + ;; (if (window-sensibly-splittable-p t) (split-window-horizontally)) (pop-to-buffer calendar-buffer) ;; Has the window already been split vertically? (when (and (not (window-dedicated-p)) diff --git a/lisp/dired.el b/lisp/dired.el index d01687acbf3..49e0c52aafb 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -2748,17 +2748,9 @@ name, or the marker and a count of marked files." (format "%c [%d files]" dired-marker-char count))))) (defun dired-pop-to-buffer (buf) - "Pop up buffer BUF in a way suitable for Dired." - (let ((split-window-preferred-function - (lambda (window) - (or (and (let ((split-height-threshold 0)) - (window-sensibly-splittable-p (selected-window))) - ;; Try to split the selected window vertically if - ;; that's possible. (Bug#1806) - (split-window-vertically)) - ;; Otherwise, try to split WINDOW sensibly. - (split-window-sensibly window))))) - (pop-to-buffer (get-buffer-create buf))) + "Pop up buffer BUF in a way suitable for Dired. +Curently this means just above the echo area." + (pop-to-buffer (get-buffer-create buf) '(same-frame (split-root . below))) ;; If dired-shrink-to-fit is t, make its window fit its contents. (when dired-shrink-to-fit ;; Try to not delete window when we want to display less than diff --git a/lisp/frame.el b/lisp/frame.el index 06e2268c697..a909f6a04a9 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -114,6 +114,10 @@ affected by this variable." (symbol :tag "Parameter") (sexp :tag "Value"))) :group 'frames) +(make-obsolete-variable + 'pop-up-frame-alist + "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead." + "24.1") (defcustom pop-up-frame-function (lambda () (make-frame pop-up-frame-alist)) @@ -123,6 +127,10 @@ frame. The default value calls `make-frame' with the argument `pop-up-frame-alist'." :type 'function :group 'frames) +(make-obsolete-variable + 'pop-up-frame-function + "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead." + "24.1") (defcustom special-display-frame-alist '((height . 14) (width . 80) (unsplittable . t)) @@ -140,6 +148,10 @@ These supersede the values given in `default-frame-alist'." (symbol :tag "Parameter") (sexp :tag "Value"))) :group 'frames) +(make-obsolete-variable + 'special-display-frame-alist + "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead." + "24.1") (defun special-display-popup-frame (buffer &optional args) "Display BUFFER and return the window chosen. diff --git a/lisp/info.el b/lisp/info.el index 9b0e87b3c25..b9ce8437f08 100644 --- a/lisp/info.el +++ b/lisp/info.el @@ -612,14 +612,11 @@ in `Info-file-supports-index-cookies-list'." "Like `info' but show the Info buffer in another window." (interactive (if current-prefix-arg (list (read-file-name "Info file name: " nil nil t)))) - (let (same-window-buffer-names same-window-regexps) - (info file-or-node))) - -;;;###autoload (add-hook 'same-window-regexps (purecopy "\\*info\\*\\(\\|<[0-9]+>\\)")) + (info file-or-node nil 'same-frame)) ;;;###autoload (put 'info 'info-file (purecopy "emacs")) ;;;###autoload -(defun info (&optional file-or-node buffer) +(defun info (&optional file-or-node buffer window-specifiers) "Enter Info, the documentation browser. Optional argument FILE-OR-NODE specifies the file to examine; the default is the top-level directory of Info. @@ -645,7 +642,8 @@ See a list of available Info commands in `Info-mode'." (read-file-name "Info file name: " nil nil t)) (if (numberp current-prefix-arg) (format "*info*<%s>" current-prefix-arg)))) - (pop-to-buffer (or buffer "*info*")) + (pop-to-buffer + (or buffer "*info*") (or window-specifiers 'same-window)) (if (and buffer (not (eq major-mode 'Info-mode))) (Info-mode)) (if file-or-node @@ -772,7 +770,8 @@ it says do not attempt further (recursive) error recovery." (info-initialize) (setq filename (Info-find-file filename)) ;; Go into Info buffer. - (or (eq major-mode 'Info-mode) (pop-to-buffer "*info*")) + (or (eq major-mode 'Info-mode) + (pop-to-buffer "*info*" 'same-window)) ;; Record the node we are leaving, if we were in one. (and (not no-going-back) Info-current-file @@ -806,7 +805,8 @@ otherwise, that defaults to `Top'." "Go to an Info node FILENAME and NODENAME, re-reading disk contents. When *info* is already displaying FILENAME and NODENAME, the window position is preserved, if possible." - (or (eq major-mode 'Info-mode) (pop-to-buffer "*info*")) + (or (eq major-mode 'Info-mode) + (pop-to-buffer "*info*" 'same-window)) (let ((old-filename Info-current-file) (old-nodename Info-current-node) (old-buffer-name (buffer-name)) @@ -818,7 +818,8 @@ is preserved, if possible." (new-history (and Info-current-file (list Info-current-file Info-current-node (point))))) (kill-buffer (current-buffer)) - (pop-to-buffer (or old-buffer-name "*info*")) + (pop-to-buffer + (or old-buffer-name "*info*") 'same-window) (Info-mode) (Info-find-node filename nodename) (setq Info-history-forward old-history-forward) @@ -2015,7 +2016,7 @@ End of submatch 0, 1, and 3 are the same, so you can safely concat." (interactive) ;; In case another window is currently selected (save-window-excursion - (or (eq major-mode 'Info-mode) (pop-to-buffer "*info*")) + (or (eq major-mode 'Info-mode) (pop-to-buffer "*info*" 'same-window)) (Info-goto-node (Info-extract-pointer "next")))) (defun Info-prev () @@ -2023,7 +2024,7 @@ End of submatch 0, 1, and 3 are the same, so you can safely concat." (interactive) ;; In case another window is currently selected (save-window-excursion - (or (eq major-mode 'Info-mode) (pop-to-buffer "*info*")) + (or (eq major-mode 'Info-mode) (pop-to-buffer "*info*" 'same-window)) (Info-goto-node (Info-extract-pointer "prev[ious]*" "previous")))) (defun Info-up (&optional same-file) @@ -2032,7 +2033,7 @@ If SAME-FILE is non-nil, do not move to a different Info file." (interactive) ;; In case another window is currently selected (save-window-excursion - (or (eq major-mode 'Info-mode) (pop-to-buffer "*info*")) + (or (eq major-mode 'Info-mode) (pop-to-buffer "*info*" 'same-window)) (let ((old-node Info-current-node) (old-file Info-current-file) (node (Info-extract-pointer "up")) p) @@ -4158,7 +4159,8 @@ COMMAND must be a symbol or string." ;; Get Info running, and pop to it in another window. (save-window-excursion (info)) - (or (eq major-mode 'Info-mode) (pop-to-buffer "*info*")) + (or (eq major-mode 'Info-mode) + (pop-to-buffer "*info*" 'same-window)) ;; Bind Info-history to nil, to prevent the last Index node ;; visited by Info-find-emacs-command-nodes from being ;; pushed onto the history. @@ -4766,7 +4768,7 @@ The INDENT level is ignored." (select-window bwin) (raise-frame (window-frame bwin))) (if speedbar-power-click - (let ((pop-up-frames t)) (select-window (display-buffer buff))) + (select-window (display-buffer buff 'other-frame)) (speedbar-select-attached-frame) (switch-to-buffer buff))) (if (not (string-match "^(\\([^)]+\\))\\([^.]+\\)$" node)) diff --git a/lisp/window.el b/lisp/window.el index 3d8d9012d44..908bdfcd5e1 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -3618,6 +3618,1654 @@ specific buffers." :version "24.1" :group 'windows) +(defcustom display-buffer-names nil + "List associating buffer names with buffer display specifiers. +The car of each element of this list specifies a set of buffer +names. `display-buffer' displays a buffer whose name is a member +of that set according to the display specifiers in the element's +cdr \(note that elements are true lists). + +Valid display specifiers are symbols, cons cells, or lists. +Buffer display specifiers that are symbols specify the location +for showing the buffer. Three such specifiers are predefined: + +- `same-window' to preferably use the selected window, + +- `same-frame' to show the buffer on the selected frame, or + +- `other-frame' to show the buffer on another frame. + +Any other symbol with a function definition means to call that +function to display the buffer. The function is called with two +arguments - the buffer to display and a list of specifiers - and +is supposed to display the buffer and return the window used for +that purpose. The function is also responsible for giving the +variable `display-buffer-window-and-buffer' a meaningful value. + +The remaining display specifiers are cons cells \(occasionally +also true lists) whose components are listed below. The +specifiers listed below are useful if the location specifier +equals either `same-frame' or `other-frame': + +- `other-window' with a non-nil cdr can be used to specify that + the selected window must not be used for displaying the buffer + regardless of whether it shows that buffer or any other buffer. + +- `reuse-buffer-window' is used to specify whether a window + currently showing the buffer may be reused and where to look + for such a window. The possible values for the cdr are + + - `none', to never reuse a window showing the buffer, + + - nil, a reused window must be on the selected frame, + + - `visible', any such window must be on a visible frame, + + - 0 \(the number zero), meaning that any such window must be on + a visible or iconified frame, and + + - t, the window may be on an arbitrary frame, including + invisible ones. + +- `reuse-other-window' is used to specify whether a window + currently _not_ showing the buffer may be reused and where to + look for such a window. The possible values for the cdr are + the same as for the `reuse-buffer-window' specifier. + +The following display specifiers are useful if the location +specifier equals 'same-frame: + +- `new-window' specifies whether a new window shall be made on + the selected frame. For convenience, this specifier is + represented by a true list. The cdr of the specifier is built + from cons cells representing window/side pairings. The car of + each cell identifies the window that shall be split. Possible + values are `largest', `lru', `selected', `root' and `first' to + split the largest, least recently used, selected, root or first + window of the selected frame. + + The cdr specifies on which side of the window to split the new + window shall appear and can be one of `below', `right', + `above', or `left' with the obvious meanings. If the cdr is + nil, the window is split in a fashion suitable for its current + dimensions. If the cdr specifies a function, that function is + called with two arguments - the window to split and a list of + display specifiers. The function is supposed to split that + window and return the new window. + + `display-buffer' scans these pairings until it can either + produce a suitable window or fails. The default value for + `display-buffer-regexps' contains (split-largest . nil) and + (split-lru . nil) in order to make `display-buffer' try + splitting the largest window first and, if that fails, the + least recently used one. + +- The symbols `min-height' and `min-width'. In this case the cdr + must be a number specifying the minimum height or width of a + new window to display the buffer. An integer number specifies + the minimum number of lines or columns of the new window. A + floating point number gives the minimum fraction of the window + size with respect to the frame's root window. A new window + will be made if and only if it can be made at least as large as + specified by the number. + + Note that `min-height' and `min-width' \(as well as the + specifiers `max-height' and `max-width' below) restrict the + size of new windows only. Reusing an existing window or making + a new frame is not affected by these specifiers. + +- The symbols `max-height' and `max-width'. In this case the cdr + must be a number specifying the maximum height or width of any + new window displaying the buffer. An integer number specifies + the maximum number of lines or columns of the new window. A + floating point number gives the maximum fraction of the window + size with respect to the frame's root window. + + Setting `min-height' and `max-height' to the same value will + make a window of exactly that height. Conversely, setting + `min-width' and `max-width' to the same value will produce a + window of that width. Note, however, that specifying the exact + size of a new window this way may reduce the number of windows + that can be suitably split. + +- The symbol `split-unsplittable-frame' with a non-nil cdr allows + to split a window on an unsplittable frame. This specifier + should be used in special cases only since frames are usually + made unsplittable in order to prevent `display-buffer' from + splitting them. + +- `adjust-height' with the following interpretations for the cdr: + + - nil means do not adjust the height of a new window. + + - `even-window-heights' means to even the height of the window + used for displaying the buffer with the height of the + selected window provided these windows appear above each + other. + + - The symbols `shrink-window-if-larger-than-buffer' and + `fit-window-to-buffer' specify that the new window shall be + adjusted by the homonymous function. + + Observe that a non-nil value may override restrictions given by + the `min-height', `min-width', `max-height', and `max-width' + specifiers. Think of the latter being applied when the new + window is created and `adjust-height' being applied after that + window has been created. + +The specifiers listed next are useful if the location specifier +equals 'other-frame: + +- `graphic-only' with a non-nil cdr means that a new frame shall + be made on graphic displays only. + +- `popup-frame-function' together with a valid function as cdr + specifies the function for creating a new frame. The default + function is `make-frame'. The function is called with the + parameters and values provided by the specifier described next. + +- `popup-frame-alist' followed by an arbitrary number of frame + parameter/value pairs, each given as a cons cell, specifies the + parameters passed to the popup frame function. For + convenience, this specifier is not a cons cell but a list whose + first element is the symbol `popup-frame-alist' and whose + remaining elements are pairs of parameters and values. + +One specifier is useful with any of the 'same-window, +'same-frame, 'other-frame location specifiers: `dedicated' with a +non-nil cdr can be used to dedicate a new window to the buffer. +The cdr is either + +- nil, to not dedicate the window to the buffer, + +- `weak', the window shall be weakly dedicated to its buffer, or + +- t, to strongly dedicate the window to the buffer. + +Usually, applications are free to override the specifiers of +`display-buffer-names' by passing its own specifiers as second +argument of `display-buffer'. For every `display-buffer-names' +entry you can, however, add a cons cell whose car is the symbol +`override' and whose cdr is non-nil, to explicitly override any +value supplied by the application. + +Overriding specifiers supplied by the calling application is, in +general, not advisable. It permits, for example, to change the +semantics of a function like `switch-to-buffer-other-window' by +using the location specifiers `same-window' or `other-frame'." + :risky t + :type + '(repeat + :offset 9 + (list + :tag "Association" + (repeat + :tag "Buffer names" + (string :format "%v\n" :size 24)) + (repeat + :offset 9 + :tag "Display specifiers" + :inline t + (list + :tag "Specifiers" + :inline t + :format "%v" + (choice + :tag "Locations" + :inline t + :help-echo "Choose a location for displaying the buffer(s)." + :value (same-frame + (new-window (largest . nil) (lru . nil)) + (min-height . 24) (min-width . 60)) + :format "%[Location%] %v" :size 15 + + ;; Same window. + (list + :tag "Same window" + :format "%t%v" + :inline t + (const :format "\n" same-window) + (set + :format "%v" :inline t + (cons + :format "%v" + (const :format "" dedicated) + (choice + :tag "Dedicate window to buffer" :value nil + :help-echo "Mark window as dedicated to its buffer." + :format "%[%t%] %v\n" :size 15 + (const :tag "Off" :format "%t" nil) + (const :tag "Weak" :format "%t" weak) + (const :tag "Strong" :format "%t" t))))) + + ;; Same frame. + (list + :tag "Same frame" + :value (same-frame + (new-window (largest . nil) (lru . nil)) + (min-height . 24) (min-width . 60) + (adjust-height . even-window-heights) + (reuse-buffer-window . nil)) + :format "%t%v" + :inline t + (const :format "\n" same-frame) + (set + :format "%v" :inline t + (cons + :tag "Avoid selected window" + :format "%v%t\n" + (const :format "" not-this-window) + (const :format "" t)) + (cons + :format "%v" + (const + :format "" reuse-buffer-window) + (choice + :tag "Reuse buffer window" + :help-echo "Frames to search for a window showing the buffer." + :value nil :format "%[Reuse buffer window%] %v\n" :size 15 + (const :tag "None" :format "%t" none) + (const :tag "Selected frame only" :format "%t" nil) + (const :tag "Visible frames" :format "%t" visible) + (const :tag "Visible and iconified frames" :format "%t" 0) + (const :tag "All frames" :format "%t" t))) + (cons + :format "%v" + (const + :format "" reuse-other-window) + (choice + :tag "Reuse other window" + :help-echo "Frames to search for a window not showing the buffer." + :value nil :format "%[Reuse other window%] %v\n" :size 15 + (const :tag "None" :format "%t" none) + (const :tag "Selected frame only" :format "%t" nil) + (const :tag "Visible frames" :format "%t" visible) + (const :tag "Visible and iconified frames" :format "%t" 0) + (const :tag "All frames" :format "%t" t))) + (list + :format "%v" + :value (new-window (largest . nil) (lru . nil)) + (const :format "" new-window) + (repeat + :inline t + :tag "Window / Side pairings" + (cons + :format "%v" + (choice + :tag "Window" :help-echo "The window to split." + :value largest :format "%[Window%] %v" :size 15 + (const :tag "Largest" :format "%t" largest) + (const :tag "Least recently used" :format "%t" lru) + (const :tag "Selected" :format "%t" selected) + (const :tag "Root" :format "%t" root) + (const :tag "First" :format "%t" first)) + (choice + :tag "Side" + :help-echo "The position of the new window with respect to the window to split." + :value nil :format " %[Side%] %v" :size 15 + (const :tag "Dynamic" nil) + (const :tag "Below" below) + (const :tag "Right" right) + (const :tag "Above" above) + (const :tag "Left" left) + (function + :tag "Function" :format "%v\n" :size 25))))) + (cons + :format "%v\n" + (const :format "" min-height) + (number + :tag "Minimum height" :value 12 :size 5)) + (cons + :format "%v\n" + (const :format "" min-width) + (number + :tag "Minimum width" :value 60 :size 5)) + (cons + :format "%v\n" + (const :format "" max-height) + (number + :tag "Maximum height" :value 48 :size 5)) + (cons + :format "%v\n" + (const :format "" max-width) + (number + :tag "Maximum width" :value 120 :size 5)) + (cons + :tag "Make new window even if frame is unsplittable" :size 5 + :format "%v%t\n" + (const :format "" split-unsplittable-frame) + (const :format "" t)) + (cons + :format "%v" + (const :format "" adjust-height) + (choice + :tag "Adjust window height" :value even-window-heights + :help-echo "Whether window height shall be adjusted." + :format "%[Adjust height%] %v\n" :size 15 + ;; nil matters when we want to override. + (const :tag "Do not adjust heights" :format "%t" nil) + (const :tag "Even window heights" :format "%t" even-window-heights) + (const :tag "Shrink window if larger than buffer" + :format "%t" shrink-window-if-larger-than-buffer) + (const :tag "Fit window to buffer" :format "%t" fit-window-to-buffer))) + (cons + :format "%v" + :inline t + (const :format "" dedicated) + (choice + :tag "Dedicate window to buffer" :value nil + :help-echo "Mark window as dedicated to its buffer." + :format "%[%t%] %v\n" :size 15 + (const :tag "Off" :format "%t" nil) + (const :tag "Weak" :format "%t" weak) + (const :tag "Strong" :format "%t" t))))) + + ;; Other frame. + (list + :tag "Other frame" + :value (other-frame + (graphic-only . t) + (popup-frame-alist + (height . 24) (width . 80) (unsplittable . t)) + (reuse-buffer-window . visible)) + :format "%t%v" + :inline t + (const :format "\n" other-frame) + (set + :format "%v" + :inline t + (cons + :tag "Avoid selected window" + :format "%v%t\n" + (const :format "" other-window) + (const :format "" t)) + (cons + :format "%v" + (const + :format "" reuse-buffer-window) + (choice + :tag "Reuse buffer window" + :help-echo "Frames to search for a window showing the buffer." + :value nil :format "%[Reuse buffer window%] %v\n" :size 15 + (const :tag "None" :format "%t" none) + (const :tag "Selected frame only" :format "%t" nil) + (const :tag "Visible frames" :format "%t" visible) + (const :tag "Visible and iconified frames" :format "%t" 0) + (const :tag "All frames" :format "%t" t))) + (cons + :format "%v" + (const + :format "" reuse-other-window) + (choice + :tag "Reuse other window" + :help-echo "Frames to search for a window not showing the buffer." + :value nil :format "%[Reuse other window%] %v\n" :size 15 + (const :tag "None" :format "%t" none) + (const :tag "Selected frame only" :format "%t" nil) + (const :tag "Visible frames" :format "%t" visible) + (const :tag "Visible and iconified frames" :format "%t" 0) + (const :tag "All frames" :format "%t" t))) + (cons + :tag "Avoid selected frame" + :format "%v%t\n" + (const :format "" not-this-frame) + (const :format "" t)) + (cons + :tag "Switch to another frame on graphic displays only" + :format "%v%t\n" + (const :format "" graphic-only) + (const :format "" t)) + (cons + :format "%v" + (const :format "" popup-frame-function) + (function + :tag "Popup frame function" + :value make-frame + :format "%t: %v\n" + :size 25)) + (list + :format "%v" + :value (popup-frame-alist (height . 24) (width . 80) (unsplittable . t)) + (const :format "" popup-frame-alist) + (repeat + :tag "Parameter / Value pairings" + :inline t + (cons + :format "%v\n" + (symbol + :tag "Parameter" + :format "Parameter: %v" + :size 16) + (sexp + :tag "Value" + :format " Value: %v" + :size 8)))) + (cons + :format "%v" + (const :format "" dedicated) + (choice + :tag "Dedicate window to buffer" :value nil + :help-echo "Mark window as dedicated to its buffer." + :format "%[%t%] %v\n" :size 15 + (const :tag "Off" :format "%t" nil) + (const :tag "Weak" :format "%t" weak) + (const :tag "Strong" :format "%t" t))))) + + ;; Function. + (list + :tag "Function" + :format "%t%v\n" + :inline t + (function + :tag "" + :size 25))))) + + ;; Specifiers that are not location specific. + (set + :format "%v" + :inline t + (cons + :tag "Override other specifiers" + :format "%v%t\n" + (const :format "" override) + (const :format "" t))))) + :group 'windows + :group 'frames) + +(defcustom display-buffer-regexps + '(((".*") + same-frame + (reuse-buffer-window . nil) + (new-window (largest . nil) (lru . nil)) + (min-height . 24) (min-width . 60) + (adjust-height . even-window-heights) + other-frame + (reuse-buffer-window . visible) + (graphic-only . t) + (popup-frame-alist + (height . 24) (width . 80) (unsplittable . t)))) + "List associating regexps with buffer display specifiers. +The car of each element of this list is a list of regular +expressions. Buffers whose name matches that expression are +displayed according to the list of buffer display specifiers +constituting the cdr of the element. Consult the documentation +of the variable `display-buffer-names' for a description of valid +display specifiers. + +The default value of this variable provides one element matching +all buffers. It states that any buffer shall be displayed +preferably on the selected frame. If, however, there already +exists a window showing the buffer on the selected frame, +`display-buffer' returns that window. Otherwise, it tries to +split either the largest or the least recently used window with +the new window below or on the right of the window that is split. +The minimum height of the new window shall be 24 lines, its +minimum width 60 columns. If a window above or below the +selected window is used, the heights of both windows shall be +evened out. + +If these specifiers fail to produce a suitable window and a +graphic display is used, then the buffer shall be displayed on a +new frame unless a window showing the buffer can be found on some +visible. The function to pop up a new frame is given three +parameters: A frame height of 24 lines, a frame width of 80 +lines, and a non-nil unsplittable property." + :risky t + :type + '(repeat + :offset 9 + (list + :tag "Association" + (repeat + :tag "Regular expressions that match buffer names" + (string :format "%v\n" :size 48)) + (repeat + :offset 9 + :tag "Display specifiers" + :inline t + (list + :tag "Specifiers" + :inline t + :format "%v" + (choice + :tag "Locations" + :inline t + :help-echo "Choose a location for displaying the buffer(s)." + :value (same-frame + (new-window (largest . nil) (lru . nil)) + (min-height . 24) (min-width . 60)) + :format "%[Location%] %v" :size 15 + + ;; Same window. + (list + :tag "Same window" + :format "%t%v" + :inline t + (const :format "\n" same-window) + (set + :format "%v" :inline t + (cons + :format "%v" + (const :format "" dedicated) + (choice + :tag "Dedicate window to buffer" :value nil + :help-echo "Mark window as dedicated to its buffer." + :format "%[%t%] %v\n" :size 15 + (const :tag "Off" :format "%t" nil) + (const :tag "Weak" :format "%t" weak) + (const :tag "Strong" :format "%t" t))))) + + ;; Same frame. + (list + :tag "Same frame" + :value (same-frame + (reuse-buffer-window . nil) + (new-window (largest . nil) (lru . nil)) + (min-height . 24) (min-width . 60) + (adjust-height . even-window-heights)) + :format "%t%v" + :inline t + (const :format "\n" same-frame) + (set + :format "%v" :inline t + (cons + :tag "Avoid selected window" + :format "%v%t\n" + (const :format "" not-this-window) + (const :format "" t)) + (cons + :format "%v" + (const + :format "" reuse-buffer-window) + (choice + :tag "Reuse buffer window" + :help-echo "Frames to search for a window showing the buffer." + :value nil :format "%[Reuse buffer window%] %v\n" :size 15 + (const :tag "None" :format "%t" none) + (const :tag "Selected frame only" :format "%t" nil) + (const :tag "Visible frames" :format "%t" visible) + (const :tag "Visible and iconified frames" :format "%t" 0) + (const :tag "All frames" :format "%t" t))) + (cons + :format "%v" + (const + :format "" reuse-other-window) + (choice + :tag "Reuse other window" + :help-echo "Frames to search for a window not showing the buffer." + :value nil :format "%[Reuse other window%] %v\n" :size 15 + (const :tag "None" :format "%t" none) + (const :tag "Selected frame only" :format "%t" nil) + (const :tag "Visible frames" :format "%t" visible) + (const :tag "Visible and iconified frames" :format "%t" 0) + (const :tag "All frames" :format "%t" t))) + (list + :format "%v" + :value (new-window (largest . nil) (lru . nil)) + (const :format "" new-window) + (repeat + :inline t + :tag "Window / Side pairings" + (cons + :format "%v" + (choice + :tag "Window" :help-echo "The window to split." + :value largest :format "%[Window%] %v" :size 15 + (const :tag "Largest" :format "%t" largest) + (const :tag "Least recently used" :format "%t" lru) + (const :tag "Selected" :format "%t" selected) + (const :tag "Root" :format "%t" root) + (const :tag "First" :format "%t" first)) + (choice + :tag "Side" + :help-echo "The position of the new window with respect to the window to split." + :value nil :format " %[Side%] %v" :size 15 + (const :tag "Dynamic" nil) + (const :tag "Below" below) + (const :tag "Right" right) + (const :tag "Above" above) + (const :tag "Left" left) + (function + :tag "Function" :format "%v\n" :size 25))))) + (cons + :format "%v\n" + (const :format "" min-height) + (number + :tag "Minimum height" :value 12 :size 5)) + (cons + :format "%v\n" + (const :format "" min-width) + (number + :tag "Minimum width" :value 60 :size 5)) + (cons + :format "%v\n" + (const :format "" max-height) + (number + :tag "Maximum height" :value 48 :size 5)) + (cons + :format "%v\n" + (const :format "" max-width) + (number + :tag "Maximum width" :value 120 :size 5)) + (cons + :tag "Make new window even if frame is unsplittable" :size 5 + :format "%v%t\n" + (const :format "" split-unsplittable-frame) + (const :format "" t)) + (cons + :format "%v" + (const :format "" adjust-height) + (choice + :tag "Adjust window height" :value even-window-heights + :help-echo "Whether window height shall be adjusted." + :format "%[Adjust height%] %v\n" :size 15 + ;; nil matters when we want to override. + (const :tag "Do not adjust heights" :format "%t" nil) + (const :tag "Even window heights" :format "%t" even-window-heights) + (const :tag "Shrink window if larger than buffer" + :format "%t" shrink-window-if-larger-than-buffer) + (const :tag "Fit window to buffer" :format "%t" fit-window-to-buffer))) + (cons + :format "%v" + :inline t + (const :format "" dedicated) + (choice + :tag "Dedicate window to buffer" :value nil + :help-echo "Mark window as dedicated to its buffer." + :format "%[%t%] %v\n" :size 15 + (const :tag "Off" :format "%t" nil) + (const :tag "Weak" :format "%t" weak) + (const :tag "Strong" :format "%t" t))))) + + ;; Other frame. + (list + :tag "Other frame" + :value (other-frame + (graphic-only . t) + (popup-frame-alist + (height . 24) (width . 80) (unsplittable . t)) + (reuse-buffer-window . visible)) + :format "%t%v" + :inline t + (const :format "\n" other-frame) + (set + :format "%v" + :inline t + (cons + :tag "Avoid selected window" + :format "%v%t\n" + (const :format "" other-window) + (const :format "" t)) + (cons + :format "%v" + (const + :format "" reuse-buffer-window) + (choice + :tag "Reuse buffer window" + :help-echo "Frames to search for a window showing the buffer." + :value nil :format "%[Reuse buffer window%] %v\n" :size 15 + (const :tag "None" :format "%t" none) + (const :tag "Selected frame only" :format "%t" nil) + (const :tag "Visible frames" :format "%t" visible) + (const :tag "Visible and iconified frames" :format "%t" 0) + (const :tag "All frames" :format "%t" t))) + (cons + :format "%v" + (const + :format "" reuse-other-window) + (choice + :tag "Reuse other window" + :help-echo "Frames to search for a window not showing the buffer." + :value nil :format "%[Reuse other window%] %v\n" :size 15 + (const :tag "None" :format "%t" none) + (const :tag "Selected frame only" :format "%t" nil) + (const :tag "Visible frames" :format "%t" visible) + (const :tag "Visible and iconified frames" :format "%t" 0) + (const :tag "All frames" :format "%t" t))) + (cons + :tag "Avoid selected frame" + :format "%v%t\n" + (const :format "" not-this-frame) + (const :format "" t)) + (cons + :tag "Switch to another frame on graphic displays only" + :format "%v%t\n" + (const :format "" graphic-only) + (const :format "" t)) + (cons + :format "%v" + (const :format "" popup-frame-function) + (function + :tag "Popup frame function" + :value make-frame + :format "%t: %v\n" + :size 25)) + (list + :format "%v" + :value (popup-frame-alist (height . 24) (width . 80) (unsplittable . t)) + (const :format "" popup-frame-alist) + (repeat + :tag "Parameter / Value pairings" + :inline t + (cons + :format "%v\n" + (symbol + :tag "Parameter" + :format "Parameter: %v" + :size 16) + (sexp + :tag "Value" + :format " Value: %v" + :size 8)))) + (cons + :format "%v" + (const :format "" dedicated) + (choice + :tag "Dedicate window to buffer" :value nil + :help-echo "Mark window as dedicated to its buffer." + :format "%[%t%] %v\n" :size 15 + (const :tag "Off" :format "%t" nil) + (const :tag "Weak" :format "%t" weak) + (const :tag "Strong" :format "%t" t))))) + + ;; Function. + (list + :tag "Function" + :format "%t%v\n" + :inline t + (function + :tag "" + :size 25))))) + + ;; Specifiers that are not location specific. + (set + :format "%v" + :inline t + (cons + :tag "Override other specifiers" + :format "%v%t\n" + (const :format "" override) + (const :format "" t))))) + :group 'windows + :group 'frames) + +;; Minibuffer-only frames should be documented better. They really +;; deserve a separate section in the manual. Also +;; `last-nonminibuffer-frame' is nowhere documented in the manual. +(defun display-buffer-frame (&optional frame) + "Return FRAME if it is live and not a minibuffer-only frame. +Return the value of `last-nonminibuffer-frame' otherwise." + (setq frame (normalize-live-frame frame)) + (if (and (frame-live-p frame) + ;; A not very nice way to get that information. + (not (window-minibuffer-p (frame-root-window frame)))) + frame + (last-nonminibuffer-frame))) + +(defconst display-buffer-locations '(same-window same-frame other-frame) + "Buffer display location specifiers.") + +(defconst display-buffer-default-specifiers + '(same-frame + (reuse-buffer-window . nil) + (new-window (largest . nil) (lru . nil)) + (min-height . 24) (min-width . 60) + other-frame + (reuse-buffer-window . visible) + (popup-frame-alist + (height . 24) (width . 80) (unsplittable . t))) + "The default buffer display specifiers. +The value specified here is used when no other specifiers have +been specified by the user or the application. Consult the +documentation of `display-buffer-names' for a description of +buffer display specifiers.") + +(defconst display-buffer-other-window-specifiers + '(same-frame (reuse-buffer-window . nil) + other-frame (reuse-buffer-window . visible) + (not-this-window . t)) + "Specifiers for displaying a buffer in any but the selected window. +These are the specifiers applied when `display-buffer' is called +with the second argument equal t.") + +(defconst display-buffer-other-frame-specifiers + '(other-frame (reuse-buffer-window . visible) + (not-this-window . t) (not-this-frame . t)) + "Specifiers for displaying a buffer in any but the selected frame. +These should avoid the selected window and the selected frame.") + +(defun display-buffer-normalize-specifiers-1 (specifiers) + "Subroutine of `display-buffer-normalize-specifiers'. +SPECIFIERS is the homonymous argument for `display-buffer'." + (cond + ((memq specifiers '(t other-window)) + ;; Historically t means "other window". 'other-window is + ;; occasionally used with the same meaning. + display-buffer-other-window-specifiers) + ((or (memq specifiers display-buffer-locations) + (functionp 'specifiers)) + ;; A single specifier à la 'same-window - make it a list. + (list specifiers)) + ((or (not specifiers) (not (listp specifiers))) + ;; Not a valid specifier. + nil) + (t specifiers))) + +(defun display-buffer-normalize-specifiers (buffer-name specifiers) + "Return normalized specifiers for displaying a buffer called BUFFER-NAME. +BUFFER-NAME must be a string specifying a valid buffer name. +SPECIFIERS is the homonymous argument of `display-buffer'. + +The method for displaying the buffer specified by BUFFER-NAME is +established by appending the following five lists of specifiers: + +- The specifiers in `display-buffer-names' whose name component + contains BUFFER-NAME and whose 'override component is set. + +- The specifiers in `display-buffer-regexps' whose name component + matches BUFFER-NAME and whose 'override component is set. + +- SPECIFIERS. + +- The list of specifiers in `display-buffer-names' whose name + component contains BUFFER-NAME and whose 'override component is + not set. + +- The list of specifiers in `display-buffer-regexps' whose name + component matches BUFFER-NAME and whose 'override component is + not set. + +The return value is always a list. The first element of that +list is not necessarily a location specifier." + (let (names-over regexps-over names-no regexps-no) + (dolist (entry display-buffer-names) + (when (and (listp entry) (member buffer-name (car entry))) + (let ((specifier (cdr entry))) + (if (assq 'override specifier) + (setq names-over + (if names-over + (append names-over specifier) + specifier)) + (setq names-no + (if names-no + (append names-no specifier) + specifier)))))) + (dolist (entry display-buffer-regexps) + (when (and (listp entry) + (catch 'match + (dolist (regexp (car entry)) + (when (and (stringp regexp) + (string-match-p regexp buffer-name)) + (throw 'match t))))) + (let ((specifier (cdr entry))) + (if (assq 'override specifier) + (setq regexps-over + (if regexps-over + (append regexps-over specifier) + specifier)) + (setq regexps-no + (if regexps-no + (append regexps-no specifier) + specifier)))))) + (append + names-over regexps-over + (display-buffer-normalize-specifiers-1 specifiers) + names-no regexps-no + ;; Append the default specifiers. + display-buffer-default-specifiers))) + +;; The following is a global variable which is used both internally by +;; the `display-buffer' routines and externally by e.g. help.el. +(defvar display-buffer-window-and-buffer nil + "Window used by `display-buffer' and related information. +After `display-buffer' displays a buffer in some window this +variable is a cons cell whose car denotes the window used to +display the buffer. The cdr is either nil \(which means the same +buffer was displayed before in that window), t \(which means the +window was created by `display-buffer'), or the buffer displayed +previously in that window. + +If the buffer display location specifier is one of 'same-window, +'same-frame, or 'other-frame, the `display-buffer' routines +assign the value of this variable. If the location specifier is +a function, that function becomes responsible for assigning a +meaningful value to `display-buffer-window-and-buffer'. See the +function `display-buffer-in-window' for how this is done.") + +(defun display-buffer-adjust-heights (window specifiers) + "Adjust height of WINDOW according to SPECIFIERS. +SPECIFIERS must be a list of buffer display specifiers, see the +documentation of `display-buffer-names' for a description." + (let ((adjust-height (cdr (assq 'adjust-height specifiers)))) + (cond + ((eq adjust-height 'even-window-heights) + (when (and (not (eq window (selected-window))) + ;; Don't resize minibuffer windows. + (not (window-minibuffer-p)) + ;; Resize iff the selected window is higher than WINDOW. + (> (window-total-size) (window-total-size window)) + ;; Resize vertical combinations only. + (and (window-parent) (window-iso-combined-p (window-parent)) + ;; WINDOW must be adjacent to the selected one. + (or (eq window (window-prev)) (eq window (window-next))))) + ;; Don't throw an error if we can't even window heights for + ;; whatever reason. In any case, enlarging the selected window + ;; might fail anyway if there are other windows above or below + ;; WINDOW and the selected one. But for a simple two windows + ;; configuration the present behavior is good enough so why care? + (condition-case nil + (resize-window + window (/ (- (window-total-size window) (window-total-size)) 2)) + (error nil)))) + ((eq adjust-height 'shrink-window-if-larger-than-buffer) + (shrink-window-if-larger-than-buffer window)) + ((eq adjust-height 'fit-window-to-buffer) + (fit-window-to-buffer window))))) + +(defun display-buffer-select-window (window &optional norecord) + "Select WINDOW and make sure it's frame is risen." + (let ((old-frame (selected-frame)) + (new-frame (window-frame window))) + (select-window window norecord) + (unless (eq old-frame new-frame) + (select-frame-set-input-focus new-frame)))) + +(defun display-buffer-in-window (buffer window specifiers type) + "Display BUFFER in WINDOW and raise its frame. +WINDOW must be a live window and defaults to the selected one. +Return WINDOW. + +SPECIFIERS must be a list of buffer display specifiers, see the +documentation of `display-buffer-names' for a description. TYPE +must be 'new-window if a new window is used and 'new-frame if a +new frame was created. Other values currently have no special +meaning." + (setq buffer (normalize-live-buffer buffer)) + (setq window (normalize-live-window window)) + (let* ((old-frame (selected-frame)) + (new-frame (window-frame window)) + (new (memq type '(new-window new-frame))) + (dedicated (cdr (assq 'dedicated specifiers)))) + ;; Set up information for help-windows. + (setq display-buffer-window-and-buffer + (cons window (if new t (window-buffer window)))) + ;; Set `quit-restore' information. + (cond + ((memq type '(new-window new-frame)) + (set-window-parameter + ;; Maybe we should use (frame-selected-window frame) here? Do we + ;; have to save the selected window here? Should we discriminate + ;; new-window and new-frame somehow? + window 'quit-restore (list t (selected-window)))) + ((and (not (eq buffer (window-buffer window))) + ;; Do not overwrite an existing value. + (not (window-parameter window 'quit-restore))) + (set-window-parameter + window 'quit-restore + (list (window-buffer window) (window-start window) + (window-point window) buffer (window-total-size window) + (selected-window))))) + ;; Show BUFFER in WINDOW. + (set-window-dedicated-p window nil) + (set-window-buffer window buffer) + (when dedicated + (set-window-dedicated-p window dedicated)) + ;; Adjust heights if necessary. + (display-buffer-adjust-heights window specifiers) + ;; Raise the frame if it's new (no use to check all sorts of things + ;; as we did earlier). I'm not sure what gets broken by this but at + ;; least the case where the buffer is already shown on another frame + ;; should be handled correctly this time (Emacs 23 apparently always + ;; raises the frame and selects the window). + + ;; The "do not raise new frame" case is too difficult to handle (see + ;; also the problems with `display-buffer-other-frame'). + (unless (eq old-frame new-frame) + ;; Maybe we should call this with NORECORD non-nil. + (display-buffer-select-window window)) + ;; Return window. + window)) + +(defun display-buffer-in-lru-buffer-window (buffer frames &optional specifiers) + "Display BUFFER in least recently used window showing BUFFER. +FRAMES specifies the set of frames to consider. Return the +window displaying BUFFER if done, nil otherwise. + +Optional argument SPECIFIERS must be a list of buffer display +specifiers, see the documentation of `display-buffer-names' for a +description." + ;; Try to return the least recently used window showing BUFFER + ;; avoiding the selected window. `get-buffer-window-list' starts with + ;; the first window on the selected frame showing BUFFER (provided + ;; there is such a window). + (let ((windows (get-buffer-window-list buffer 'nomini frames)) + best-window best-time time) + (dolist (window windows) + (unless (or (and (eq window (selected-window)) + (assq 'not-this-window specifiers)) + (and (eq (window-frame window) (selected-frame)) + (assq 'not-this-frame specifiers)) + (window-minibuffer-p window)) + (setq time (window-use-time window)) + (when (or (not best-window) (< time best-time)) + (setq best-window window) + (setq best-time time)))) + + (when best-window + (display-buffer-in-window + buffer best-window specifiers 'buffer-window)))) + +(defun display-buffer-in-lru-window (buffer frames &optional specifiers) + "Display BUFFER in least recently used window. +FRAMES specifies the set of frames to consider. Return the +window displaying BUFFER if done, nil otherwise. + +Optional argument SPECIFIERS must be a list of buffer display +specifiers, see the documentation of `display-buffer-names' for a +description." + (let ((window + (catch 'found + (let ((windows + (window-list-1 + (frame-first-window (display-buffer-frame)) 'nomini frames)) + ;; lru-windows is a list of (window . use-time) pairs. + lru-windows) + (dolist (window windows) + (unless (or (and (eq window (selected-window)) + (assq 'not-this-window specifiers)) + (and (eq (window-frame window) (selected-frame)) + (assq 'not-this-frame specifiers)) + (window-minibuffer-p window) + (window-dedicated-p window)) + (setq lru-windows (cons (cons window (window-use-time window)) + lru-windows)))) + ;; Sort pairs according to their use-time. + (setq lru-windows + (sort lru-windows '(lambda (pair1 pair2) + (<= (cdr pair1) (cdr pair2))))) + ;; Try to get a full-width window. + (dolist (pair lru-windows) + (when (window-full-width-p (car pair)) + (throw 'found (car pair)))) + + ;; If there's no full-width window return the lru window. + (caar lru-windows))))) + (when window + (display-buffer-in-window + buffer window specifiers 'same-frame)))) + +(defun display-buffer-split-window-1 (window side min-size max-size) + "Subroutine of `display-buffer-split-window'." + (let* ((horflag (memq side '(left right))) + (parent (window-parent window)) + (resize (and (eq window-splits 'resize) + (window-iso-combined-p window horflag))) + (old-size + ;; We either resize WINDOW or its parent. + (window-total-size (if resize parent window) horflag)) + (new-size + ;; Don't make a window larger than MAX-SIZE, and not smaller + ;; than MIN-SIZE and the minimum size of a window. + (min max-size + (max min-size + (if resize + (min (- old-size (window-min-size parent horflag)) + (/ old-size + (1+ (window-iso-combinations parent horflag)))) + (/ old-size 2)))))) + ;; Check the sizes. + (when (if resize + (window-sizable-p parent (- new-size) horflag) + (window-sizable-p window (- new-size) horflag)) + ;; We don't call `split-window-vertically' any more here. If for + ;; some reason it seems appropriate we can always do so. + (split-window window (- new-size) side)))) + +(defun display-buffer-split-window (window &optional side specifiers) + "Split WINDOW in a way suitable for `display-buffer'. +Optional argument SIDE must be a side specifier \(one of the +symbols below, right, above, left, or nil). SPECIFIERS must be a +list of buffer display specifiers, see the documentation of +`display-buffer-names' for a description. + +Return the new window, nil if it could not be created." + ;; Normalize min-height / min-width, we might need both. + (let ((min-height (cdr (assq 'min-height specifiers))) + (min-width (cdr (assq 'min-width specifiers))) + (max-height (cdr (assq 'max-height specifiers))) + (max-width (cdr (assq 'max-width specifiers))) + (root-height (window-total-height + (frame-root-window (window-frame window)))) + (root-width (window-total-width + (frame-root-window (window-frame window)))) + size) + (setq min-height + (cond + ((and (integerp min-height) + ;; If min-height is specified, it can be as small + ;; `window-safe-min-height'. + (>= min-height window-safe-min-height)) + min-height) + ((and (floatp min-height) + (<= min-height 1) + (let ((height (round (* min-height root-height)))) + (when (>= height window-safe-min-height) + height)))) + (t window-min-height))) + (setq max-height + (cond + ((and (integerp max-height) + ;; If max-height is specified, it can be as large + ;; as root-height. + (>= max-height min-height) + (<= max-height root-height)) + max-height) + ((and (floatp max-height) + (<= max-height 1) + (let ((height (round (* max-height root-height)))) + (when (>= height min-height) + height)))) + (t root-height))) + (setq min-width + (cond + ((and (integerp min-width) + ;; If min-width is specified, it can be as small + ;; `window-safe-min-width'. + (>= min-width window-safe-min-width)) + min-width) + ((and (floatp min-width) + (<= min-width 1) + (let ((width (round (* min-width root-width)))) + (when (>= width window-safe-min-width) + width)))) + (t window-min-width))) + (setq max-width + (cond + ((and (integerp max-width) + ;; If max-width is specified, it can be as large as + ;; root-width. + (>= max-width min-width) + (<= max-width root-width)) + max-width) + ((and (floatp max-width) + (<= max-width 1) + (let ((width (round (* max-width root-width)))) + (when (>= width min-width) + width)))) + (t root-width))) + + (or (and (memq side '(nil above below)) + (display-buffer-split-window-1 + window (or side 'below) min-height max-height)) + ;; If SIDE is nil and vertical splitting failed, we try again + ;; splitting horizontally this time. For the SIDE nil case, we + ;; could also try to split horizontally if splitting vertically + ;; with proportional sizes fails and try the vertical split with + ;; minimum size afterwards - but this might be disconcerting. + (and (memq side '(nil left right)) + (display-buffer-split-window-1 + window (or side 'below) min-width max-width))))) + +(defconst display-buffer-split-specifiers '(largest lru selected root first) + "Buffer display window split specifiers.") + +(defconst display-buffer-side-specifiers '(below right above left nil) + "Buffer display window side specifiers.") + +(defun display-buffer-in-new-window (buffer specifiers) + "Display BUFFER in a new window. +Return the window displaying BUFFER if creating the new window +was successful, nil otherwise. + +SPECIFIERS must be a list of buffer display specifiers, see the +documentation of `display-buffer-names' for a description." + (let* ((frame (display-buffer-frame)) + window window-specifier side-specifier) + ;; Don't split an unsplittable frame unless SPECIFIERS allow it. + (unless (and (cdr (assq 'unsplittable (frame-parameters frame))) + (not (cdr (assq 'split-unsplittable-frame specifiers)))) + (catch 'done + (dolist (specifier specifiers) + (when (and (consp specifier) (eq (car specifier) 'new-window)) + (dolist (window-side-specifier (cdr specifier)) + (setq window-specifier (car window-side-specifier)) + (setq side-specifier (cdr window-side-specifier)) + (setq window + (cond + ((eq window-specifier 'largest) + (get-largest-window frame t)) + ((eq window-specifier 'lru) + (get-lru-window frame t)) + ((eq window-specifier 'selected) + (frame-selected-window frame)) + ((eq window-specifier 'root) + (frame-root-window frame)) + ((eq window-specifier 'first) + (frame-first-window frame)))) + (and window (eq (window-frame window) frame) + (not (window-minibuffer-p window)) + (setq window + (cond + ((memq + side-specifier display-buffer-side-specifiers) + (display-buffer-split-window + window side-specifier specifiers)) + ((fboundp side-specifier) + (condition-case nil + (funcall + side-specifier window (cdr specifiers)) + (error nil))))) + (throw 'done window)))))) + (when window + (display-buffer-in-window + buffer window specifiers 'new-window))))) + +(defun display-buffer-in-new-frame (buffer specifiers) + "Make a new frame for displaying BUFFER. +Return the window displaying BUFFER if creating the new frame was +successful, nil otherwise. + +SPECIFIERS must be a list of buffer display specifiers, see the +documentation of `display-buffer-names' for a description." + (unless (and (cdr (assq 'graphic-only specifiers)) + (not (display-graphic-p))) + (let* ((function (or (cdr (assq 'popup-frame-function specifiers)) + 'make-frame)) + (parameters (cdr (assq 'popup-frame-alist specifiers))) + (frame (funcall function parameters))) + (when frame + (display-buffer-in-window + buffer (frame-selected-window frame) specifiers 'new-frame))))) + +(defun normalize-buffer-to-display (buffer-or-name) + "Normalize BUFFER-OR-NAME argument for buffer display functions. +If BUFFER-OR-NAME is nil, return the curent buffer. Else, if a +buffer specified by BUFFER-OR-NAME exists, return that buffer. +If no such buffer exists, create a buffer with the name +BUFFER-OR-NAME and return that buffer." + (if buffer-or-name + (or (get-buffer buffer-or-name) + (let ((buffer (get-buffer-create buffer-or-name))) + (set-buffer-major-mode buffer) + buffer)) + (current-buffer))) + +(defun display-buffer (&optional buffer-or-name specifiers ignore) + "Make the buffer specified by BUFFER-OR-NAME appear in some window. +Optional argument BUFFER-OR-NAME may be a buffer, a string \(a +buffer name), or nil. If BUFFER-OR-NAME is a string not naming +an existent buffer, create a buffer with that name. If +BUFFER-OR-NAME is nil or omitted, display the current buffer. +Interactively, prompt for the buffer name using the minibuffer. + +Return the window chosen to display the buffer or nil if no such +window is found. Do not change the selected window unless a new +frame is created. + +Optional argument SPECIFIERS must be a list of buffer display +specifiers, see the documentation of `display-buffer-names' for a +description. + +For convenience, SPECIFIERS may also consist of a single buffer +display location specifier or t, where the latter means to +display the buffer in any but the selected window. If SPECIFIERS +is nil or omitted, this means to exclusively use the values +provided by `display-buffer-names' and `display-buffer-regexps'. +If these values are nil too, all specifiers are provided by the +constant `display-buffer-default-specifiers'. + +The optional third argument IGNORE is ignored. + +The method to display a buffer is derived by combining the values +of `display-buffer-names', `display-buffer-regexps', and +SPECIFIERS. Highest priority is given to overriding elements of +`display-buffer-names' followed by overriding elements of +`display-buffer-regexps'. Next come the elements specified by +SPECIFIERS, followed by the non-overriding elements of +`display-buffer-names' and the non-overriding elements of +`display-buffer-regexps'. + +The result must be a list of valid buffer display specifiers. +`display-buffer' scans this list from front to back until it +finds a location specifier and attempts to use that specifier in +order to produce a suitable window. For this purpose, all +non-symbolic specifiers following the location specifier in the +list are considered additional specifiers. If an attempt fails +to produce a window, `display-buffer' continues with the next +location specifier on the list. Additional specifiers preceding +the currently chosen location specifier in the list are ignored." + (interactive "BDisplay buffer:\nP") + (let* ((buffer (normalize-buffer-to-display buffer-or-name)) + (buffer-name (buffer-name buffer)) + (specifiers + ;; Normalize specifiers. + (display-buffer-normalize-specifiers buffer-name specifiers)) + ;; Don't use a minibuffer frame. + (frame (display-buffer-frame)) + ;; `window' is the window we use for showing `buffer'. + specifier location window type + reuse-buffer-window reuse-other-window) + ;; Reset `display-buffer-window-and-buffer'. + (setq display-buffer-window-and-buffer nil) + ;; Retrieve the next location specifier while there a specifiers left + ;; and we don't have a valid window. + (while (and specifiers (or (not window) (not (window-live-p window)))) + (setq location (car specifiers)) + (setq specifiers (cdr specifiers)) + (when (symbolp location) + (setq window + (or (and (eq location 'same-window) + (or (not (window-dedicated-p)) + (not (eq (window-buffer) buffer))) + (let ((selected-window + ;; If the selected window is a minibuffer + ;; window, use the selected window of the + ;; last nonminibuffer frame instead. + (if (window-minibuffer-p) + (frame-selected-window (last-nonminibuffer-frame)) + (selected-window)))) + (display-buffer-in-window + buffer selected-window specifiers 'reuse-window))) + (and (memq location '(same-frame other-frame)) + (not (eq (setq reuse-buffer-window + (cdr (assq 'reuse-buffer-window specifiers))) + 'never)) + ;; Try to reuse a window showing BUFFER. If + ;; reuse-buffer-window was set, it will specify + ;; the frames to consider, otherwise look at the + ;; selected frame's windows only. + (display-buffer-in-lru-buffer-window + buffer reuse-buffer-window specifiers)) + (and (eq location 'same-frame) + (not (frame-parameter frame 'unsplittable)) + ;; Try making a new window. + (display-buffer-in-new-window buffer specifiers)) + (and (eq location 'other-frame) + ;; Try making a new frame. + (display-buffer-in-new-frame buffer specifiers)) + (and (eq location 'same-frame) + (not (eq (setq reuse-other-window + (cdr (assq 'reuse-other-window specifiers))) + 'never)) + ;; Try to reuse a window not showing BUFFER. If + ;; reuse-buffer-window was set, it will specify + ;; the frames to consider, otherwise look at the + ;; selected frame's windows only. + (display-buffer-in-lru-window + buffer reuse-other-window specifiers)) + (and (not (memq location display-buffer-locations)) + (fboundp location) + ;; Separate function. + (funcall location buffer specifiers)))))) + + ;; If we don't have a window yet, try a fallback method. Note: All + ;; specifiers have been used up by now. + (or (and (window-live-p window) window) + ;; Try reusing any window showing BUFFER on a visible or + ;; iconfied frame. + (display-buffer-in-lru-buffer-window buffer 0) + ;; Try reusing a window on the selected frame. + (display-buffer-in-lru-window buffer nil) + ;; Try reusing a window on a visible frame. + (display-buffer-in-lru-window buffer 'visible) + ;; Try reusing a window on a visible or iconified frame. + (display-buffer-in-lru-window buffer 0) + ;; Try reusing any window showing BUFFER on any frame. + (display-buffer-in-lru-buffer-window buffer t) + ;; Try reusing a window on any frame. + (display-buffer-in-lru-window buffer t) + ;; Try making a new window. + (display-buffer-in-new-window buffer nil) + ;; Try making a new frame + (display-buffer-in-new-frame buffer nil) + ;; Use the selected window and let errors show trough. + (display-buffer-in-window + buffer (selected-window) nil 'reuse-window)))) + +(defun display-buffer-same-window (&optional buffer-or-name) + "Display buffer specified by BUFFER-OR-NAME in the selected window. +Another window will be used only if the buffer can't be shown in +the selected window, usualy because it is dedicated to another +buffer. + +Optional argument BUFFER-OR-NAME may be a buffer, a string \(a +buffer name), or nil. If BUFFER-OR-NAME is a string not naming +an existent buffer, create a buffer with that name. If +BUFFER-OR-NAME is nil or omitted, display the current buffer. + +Return the window chosen to display BUFFER-OR-NAME or +nil if no such window is found. Do not change the selected +window unless a new frame is created." + (display-buffer buffer-or-name 'same-window)) + +(defun display-buffer-other-window (&optional buffer-or-name) + "Display buffer specified by BUFFER-OR-NAME in another window. +The selected window will be used if and only if there is no other +choice. Windows on the selected frame are preferred to windows +on other frames. + +Optional argument BUFFER-OR-NAME may be a buffer, a string \(a +buffer name), or nil. If BUFFER-OR-NAME is a string not naming +an existent buffer, create a buffer with that name. If +BUFFER-OR-NAME is nil or omitted, display the current buffer. + +Return the window chosen to display BUFFER-OR-NAME or +nil if no such window is found. Do not change the selected +window unless a new frame is created." + (display-buffer + buffer-or-name display-buffer-other-window-specifiers)) + +(defun pop-to-buffer (&optional buffer-or-name specifiers norecord) + "Display buffer specified by BUFFER-OR-NAME and select the window used. +Optional argument BUFFER-OR-NAME may be a buffer, a string \(a +buffer name), or nil. If BUFFER-OR-NAME is a string not naming +an existent buffer, create a buffer with that name. If +BUFFER-OR-NAME is nil or omitted, display the current buffer. +Interactively, prompt for the buffer name using the minibuffer. + +Optional second argument SPECIFIERS must be a list of buffer +display specifiers, a single location specifier, `t' which means +the latter means to display the buffer in any but the selected +window, or nil which means to exclusively apply the specifiers +customized by the user. + +Optional argument NORECORD non-nil means do not put the buffer +specified by BUFFER-OR-NAME at the front of the buffer list and +do not make the window displaying it the most recently selected +one. + +Return the buffer specified by BUFFER-OR-NAME or nil if +displaying the buffer failed. + +This uses the function `display-buffer' as a subroutine; see the +documentations of `display-buffer', `display-buffer-names' and +`display-buffer-regexps' for additional information." + (interactive "BPop to buffer:\nP") + (let ((buffer (normalize-buffer-to-display buffer-or-name)) + window) + (set-buffer buffer) + (when (setq window (display-buffer buffer specifiers)) + (display-buffer-select-window window norecord) + buffer))) + +(defun pop-to-buffer-same-window (&optional buffer-or-name norecord) + "Pop to buffer specified by BUFFER-OR-NAME in the selected window. +Another window will be used only if the buffer can't be shown in +the selected window, usually because it is dedicated to another +buffer. Select the window used for displaying the buffer and +return the buffer specified by BUFFER-OR-NAME or nil if +displaying the buffer failed. + +Optional arguments BUFFER-OR-NAME and NORECORD are as for +`pop-to-buffer'." + (interactive "BPop to buffer in selected window:\nP") + (pop-to-buffer buffer-or-name 'same-window norecord)) + +(defun pop-to-buffer-other-window (&optional buffer-or-name norecord) + "Pop to buffer specified by BUFFER-OR-NAME in another window. +The selected window will be used if and only if there is no other +choice. Windows on the selected frame are preferred to windows +on other frames. Select the window used for displaying the +buffer and return the buffer specified by BUFFER-OR-NAME or nil +if displaying the buffer failed. + +Optional arguments BUFFER-OR-NAME and NORECORD are as for +`pop-to-buffer'." + (interactive "BPop to buffer in another window:\nP") + (pop-to-buffer + buffer-or-name display-buffer-other-window-specifiers norecord)) + +(defun pop-to-buffer-other-frame (&optional buffer-or-name norecord) + "Pop to buffer specified by BUFFER-OR-NAME on another frame. +The selected frame will be used only if there's no other choice. +Select the window used for displaying the buffer and return the +buffer specified by BUFFER-OR-NAME or nil if displaying the +buffer failed. + +Optional arguments BUFFER-OR-NAME and NORECORD are as for +`pop-to-buffer'." + (interactive "BPop to buffer on another frame:\nP") + (pop-to-buffer + buffer-or-name display-buffer-other-frame-specifiers norecord)) + +(defun read-buffer-to-switch (prompt) + "Read the name of a buffer to switch to, prompting with PROMPT. +Return the neame of the buffer as a string. + +This function is intended for the `switch-to-buffer' family of +commands since these need to omit the name of the current buffer +from the list of completions and default values." + (let ((rbts-completion-table (internal-complete-buffer-except))) + (minibuffer-with-setup-hook + (lambda () + (setq minibuffer-completion-table rbts-completion-table) + ;; Since rbts-completion-table is built dynamically, we + ;; can't just add it to the default value of + ;; icomplete-with-completion-tables, so we add it + ;; here manually. + (if (and (boundp 'icomplete-with-completion-tables) + (listp icomplete-with-completion-tables)) + (set (make-local-variable 'icomplete-with-completion-tables) + (cons rbts-completion-table + icomplete-with-completion-tables)))) + (read-buffer prompt (other-buffer (current-buffer)) + (confirm-nonexistent-file-or-buffer))))) + +(defun normalize-buffer-to-switch-to (buffer-or-name) + "Normalize BUFFER-OR-NAME argument of buffer switching functions. +If BUFFER-OR-NAME is nil, return the buffer returned by +`other-buffer'. Else, if a buffer specified by BUFFER-OR-NAME +exists, return that buffer. If no such buffer exists, create a +buffer with the name BUFFER-OR-NAME and return that buffer." + (if buffer-or-name + (or (get-buffer buffer-or-name) + (let ((buffer (get-buffer-create buffer-or-name))) + (set-buffer-major-mode buffer) + buffer)) + (other-buffer))) + +(defun switch-to-buffer (buffer-or-name &optional norecord) + "Switch to buffer BUFFER-OR-NAME in the selected window. +If called interactively, prompt for the buffer name using the +minibuffer. The variable `confirm-nonexistent-file-or-buffer' +determines whether to request confirmation before creating a new +buffer. + +BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or +nil. If BUFFER-OR-NAME is a string that does not identify an +existing buffer, create a buffer with that name. If +BUFFER-OR-NAME is nil, switch to the buffer returned by +`other-buffer'. + +Optional argument NORECORD non-nil means do not put the buffer +specified by BUFFER-OR-NAME at the front of the buffer list and +do not make the window displaying it the most recently selected +one. Return the buffer switched to. + +This function is intended for interactive use. Lisp functions +should call `pop-to-buffer-same-window' instead." + (interactive + (list (read-buffer-to-switch "Switch to buffer: "))) + (let ((buffer (normalize-buffer-to-switch-to buffer-or-name))) + (if (and (or (window-minibuffer-p) (eq (window-dedicated-p) t)) + (not (eq buffer (window-buffer)))) + ;; Cannot switch to another buffer in a minibuffer or strongly + ;; dedicated window that does not show the buffer already. Call + ;; `pop-to-buffer' instead. + (pop-to-buffer buffer 'same-window norecord) + (unless (eq buffer (window-buffer)) + ;; I'm not sure why we should NOT call `set-window-buffer' here, + ;; but let's keep things as they are (otherwise we could always + ;; call `pop-to-buffer-same-window' here). + (set-window-buffer nil buffer)) + (unless norecord + (select-window (selected-window))) + (set-buffer buffer)))) + +(defun switch-to-buffer-other-window (buffer-or-name &optional norecord) + "Switch to buffer BUFFER-OR-NAME in another window. +The selected window will be used if and only if there is no other +choice. Windows on the selected frame are preferred to windows +on other frames. + +If called interactively, prompt for the buffer name using the +minibuffer. The variable `confirm-nonexistent-file-or-buffer' +determines whether to request confirmation before creating a new +buffer. + +When called from Lisp, BUFFER-OR-NAME may be a buffer, a string +\(a buffer name), or nil. If BUFFER-OR-NAME is a string that +does not identify an existing buffer, create a buffer with that +name. If BUFFER-OR-NAME is nil, switch to the buffer returned by +`other-buffer'. + +Optional argument NORECORD non-nil means do not put the buffer +specified by BUFFER-OR-NAME at the front of the buffer list and +do not make the window displaying it the most recently selected +one. Return the buffer switched to. + +This uses the function `display-buffer' as a subroutine; see the +documentations of `display-buffer', `display-buffer-names' and +`display-buffer-regexps' for additional information. + +This function is intended for interactive use. Lisp functions +should call `pop-to-buffer-other-window' instead." + (interactive + (list (read-buffer-to-switch "Switch to buffer in other window: "))) + (let ((buffer (normalize-buffer-to-switch-to buffer-or-name))) + (pop-to-buffer + buffer display-buffer-other-window-specifiers norecord))) + +(defun switch-to-buffer-other-frame (buffer-or-name &optional norecord) + "Switch to buffer BUFFER-OR-NAME on another frame. +If called interactively, prompt for the buffer name using the +minibuffer. The variable `confirm-nonexistent-file-or-buffer' +determines whether to request confirmation before creating a new +buffer. + +When called from Lisp, BUFFER-OR-NAME may be a buffer, a string +\(a buffer name), or nil. If BUFFER-OR-NAME is a string that +does not identify an existing buffer, create a buffer with that +name. If BUFFER-OR-NAME is nil, switch to the buffer returned by +`other-buffer'. + +Optional argument NORECORD non-nil means do not put the buffer +specified by BUFFER-OR-NAME at the front of the buffer list and +do not make the window displaying it the most recently selected +one. Return the buffer switched to. + +This uses the function `display-buffer' as a subroutine; see the +documentations of `display-buffer', `display-buffer-names' and +`display-buffer-regexps' for additional information. + +This function is intended for interactive use. Lisp functions +should call `pop-to-buffer-other-frame' instead." + (interactive + (list (read-buffer-to-switch "Switch to buffer in other frame: "))) + (let ((buffer (normalize-buffer-to-switch-to buffer-or-name))) + (pop-to-buffer buffer display-buffer-other-frame-specifiers norecord))) + +;;; Obsolete definitions of `display-buffer' below. (defcustom display-buffer-function nil "If non-nil, function to call to display a buffer. `display-buffer' calls this function with two arguments, the @@ -3632,6 +5280,10 @@ Commands such as `switch-to-buffer-other-window' and (const nil) (function :tag "function")) :group 'display-buffer) +(make-obsolete-variable + 'display-buffer-function + "use `display-buffer-names' or `display-buffer-regexps' instead." + "24.1") (defcustom special-display-buffer-names nil "List of names of buffers that should be displayed specially. @@ -3696,6 +5348,10 @@ See also `special-display-regexps'." (repeat :tag "Arguments" (sexp))))) :group 'display-buffer :group 'frames) +(make-obsolete-variable + 'special-display-buffer-names + "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead." + "24.1") ;;;###autoload (put 'special-display-buffer-names 'risky-local-variable t) @@ -3766,9 +5422,13 @@ See also `special-display-buffer-names'." (repeat :tag "Arguments" (sexp))))) :group 'display-buffer :group 'frames) +(make-obsolete-variable + 'special-display-regexps + "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead." + "24.1") (defun special-display-p (buffer-name) - "Return non-nil if a buffer named BUFFER-NAME is displayed specially. + "Return non-nil if a buffer named BUFFER-NAME gets a special frame. More precisely, return t if `special-display-buffer-names' or `special-display-regexps' contain a string entry equaling or matching BUFFER-NAME. If `special-display-buffer-names' or @@ -3791,6 +5451,7 @@ entry." ((and (consp regexp) (stringp (car regexp)) (string-match-p (car regexp) buffer-name)) (throw 'found (cdr regexp)))))))))) +(make-obsolete 'special-display-p "pass argument to buffer display function instead." "24.1") (defcustom special-display-function 'special-display-popup-frame "Function to call for displaying special buffers. @@ -3806,6 +5467,10 @@ A buffer is special when its name is either listed in `special-display-regexps'." :type 'function :group 'frames) +(make-obsolete-variable + 'special-display-function + "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead." + "24.1") (defcustom same-window-buffer-names nil "List of names of buffers that should appear in the \"same\" window. @@ -3821,6 +5486,10 @@ ignored. See also `same-window-regexps'." :type '(repeat (string :format "%v")) :group 'display-buffer) +(make-obsolete-variable + 'same-window-buffer-names + "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead." + "24.1") (defcustom same-window-regexps nil "List of regexps saying which buffers should appear in the \"same\" window. @@ -3836,6 +5505,10 @@ the buffer name. This is for compatibility with See also `same-window-buffer-names'." :type '(repeat (regexp :format "%v")) :group 'display-buffer) +(make-obsolete-variable + 'same-window-regexps + "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead." + "24.1") (defun same-window-p (buffer-name) "Return non-nil if a buffer named BUFFER-NAME would be shown in the \"same\" window. @@ -3858,6 +5531,7 @@ selected rather than \(as usual\) some other window. See (and (consp regexp) (stringp (car regexp)) (string-match-p (car regexp) buffer-name))) (throw 'found t))))))) +(make-obsolete 'same-window-p "pass argument to buffer display function instead." "24.1") (defcustom pop-up-frames nil "Whether `display-buffer' should make a separate frame. @@ -3871,6 +5545,10 @@ Any other non-nil value means always make a separate frame." (const :tag "Always" t)) :group 'display-buffer :group 'frames) +(make-obsolete-variable + 'pop-up-frames + "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead." + "24.1") (defcustom display-buffer-reuse-frames nil "Non-nil means `display-buffer' should reuse frames. @@ -3880,6 +5558,10 @@ that frame." :version "21.1" :group 'display-buffer :group 'frames) +(make-obsolete-variable + 'display-buffer-reuse-frames + "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead." + "24.1") (defcustom pop-up-windows t "Non-nil means `display-buffer' is allowed to make a new window. @@ -3905,6 +5587,10 @@ window and, if that fails, the least recently used window." (const :tag "Selected" selected) (const :tag "Frame Root Window" root)))) :group 'display-buffer) +(make-obsolete-variable + 'pop-up-windows + "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead." + "24.1") (defcustom split-window-preferred-function 'split-window-sensibly "Function called by `display-buffer' to split a window. @@ -3931,6 +5617,10 @@ not want to split the selected window." :type 'function :version "23.1" :group 'display-buffer) +(make-obsolete-variable + 'split-window-preferred-function + "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead." + "24.1") (defcustom split-height-threshold 80 "Minimum height for splitting a window to display a buffer. @@ -3942,6 +5632,10 @@ split it vertically disregarding the value of this variable." :type '(choice (const nil) (integer :tag "lines")) :version "23.1" :group 'display-buffer) +(make-obsolete-variable + 'split-height-threshold + "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead." + "24.1") (defcustom split-width-threshold 160 "Minimum width for splitting a window to display a buffer. @@ -3951,109 +5645,10 @@ is nil, `display-buffer' cannot split windows horizontally." :type '(choice (const nil) (integer :tag "columns")) :version "23.1" :group 'display-buffer) - -(defun window-sensibly-splittable-p (window &optional horizontal) - "Return non-nil if `split-window-sensibly' may split WINDOW. -Optional argument HORIZONTAL nil or omitted means check whether -`split-window-sensibly' may split WINDOW vertically. HORIZONTAL -non-nil means check whether WINDOW may be split horizontally. - -WINDOW may be split vertically when the following conditions -hold: -- `window-size-fixed' is either nil or equals `width' for the - buffer of WINDOW. -- `split-height-threshold' is an integer and WINDOW is at least as - high as `split-height-threshold'. -- When WINDOW is split evenly, the emanating windows are at least - `window-min-height' lines tall and can accommodate at least one - line plus - if WINDOW has one - a mode line. - -WINDOW may be split horizontally when the following conditions -hold: -- `window-size-fixed' is either nil or equals `height' for the - buffer of WINDOW. -- `split-width-threshold' is an integer and WINDOW is at least as - wide as `split-width-threshold'. -- When WINDOW is split evenly, the emanating windows are at least - `window-min-width' or two (whichever is larger) columns wide." - (let* ((min-size - ;; The minimum size of any popped-up window. - (if horizontal - (and (numberp split-width-threshold) - (max (/ split-width-threshold 2) - window-min-width)) - (and (numberp split-height-threshold) - (max (/ split-height-threshold 2) - window-min-height)))) - (parent (window-parent window)) - ;; Bind both of these to min-size, only one will matter. - (window-min-width min-size) - (window-min-height min-size)) - (when min-size - ;; `display-buffer' is not allowed to override `window-splits'. - (if (and parent (eq window-splits 'resize) - (window-iso-combined-p window horizontal)) - (>= (- (window-total-size parent horizontal) - (window-min-size parent horizontal)) - min-size) - (and (not (window-size-fixed-p window horizontal)) - (>= (window-total-size window horizontal) - (+ (max (window-min-size window horizontal) - min-size) - min-size))))))) - -(defun split-window-sensibly (window) - "Split WINDOW in a way suitable for `display-buffer'. -If `split-height-threshold' specifies an integer, WINDOW is at -least `split-height-threshold' lines tall and can be split -vertically, split WINDOW into two windows one above the other and -return the lower window. Otherwise, if `split-width-threshold' -specifies an integer, WINDOW is at least `split-width-threshold' -columns wide and can be split horizontally, split WINDOW into two -windows side by side and return the window on the right. If this -can't be done either and WINDOW is the only window on its frame, -try to split WINDOW vertically disregarding any value specified -by `split-height-threshold'. If that succeeds, return the lower -window. Return nil otherwise. - -By default `display-buffer' routines call this function to split -the largest or least recently used window. To change the default -beahvior customize the option `split-window-preferred-function'." - (or (and (window-sensibly-splittable-p window) - ;; Split window vertically. - (if (window-live-p window) - (with-selected-window window - (split-window-vertically)) - (split-window - window (- (max window-min-height 1 - (/ split-height-threshold 2)))))) - (and (window-sensibly-splittable-p window t) - ;; Split window horizontally. - (if (window-live-p window) - (with-selected-window window - (split-window-horizontally)) - (split-window - window (- (max window-min-width 2 - (/ split-width-threshold 2))) - t))) - (and (frame-root-window-p window) - (not (window-minibuffer-p window)) - ;; If WINDOW is the only window on its frame and is not the - ;; minibuffer window, try to split it vertically disregarding - ;; the value of `split-height-threshold'. - (let ((split-height-threshold 0)) - (when (window-sensibly-splittable-p window) - (with-selected-window window - (split-window-vertically))))))) - -;; Minibuffer-only frames should be documented better. They really -;; deserve a separate section in the manual. Also -;; `last-nonminibuffer-frame' is nowhere documented in the manual. -(defun window--usable-frame (frame) - "Return FRAME if it is live and not a minibuffer-only frame." - (and (frame-live-p frame) - (not (window-minibuffer-p (frame-root-window frame))) - frame)) +(make-obsolete-variable + 'split-width-threshold + "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead." + "24.1") (defcustom even-window-heights t "If non-nil `display-buffer' will try to even window heights. @@ -4062,443 +5657,19 @@ alone. Heights are evened only when `display-buffer' reuses a window that appears above or below the selected window." :type 'boolean :group 'display-buffer) +(make-obsolete-variable + 'even-window-heights + "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead." + "24.1") -(defvar display-buffer-window-and-buffer nil - "Window used by `display-buffer' and related information. -After `display-buffer' displays a buffer in some window this -variable is a cons cell whose car denotes the window used to -display the buffer. The cdr is either nil \(which means the same -buffer was displayed before in that window), t \(which means that -window was created by `display-buffer'), or the buffer displayed -previously in that window. - -This variable holds the value produced by the last invocation of -`display-buffer' and is nil if there was no such invocation.") - -(defsubst display-buffer-window-and-buffer (window &optional value) - "Set `display-buffer-window-and-buffer' to cons of WINDOW and VALUE. -VALUE defaults to nil." - (setq display-buffer-window-and-buffer (cons window value))) - -(defun window--display-buffer-in-window (buffer window &optional dedicated) - "Display BUFFER in WINDOW and maybe raise its frame. -If DEDICATED is non-nil, use it to set the `window-dedicated-p' -flag of WINDOW. Return WINDOW." - (when (and (buffer-live-p buffer) (window-live-p window)) - (set-window-buffer window buffer) - (when dedicated - (set-window-dedicated-p window dedicated)) - (window--raise-window-frame window))) - -(defun window--reuse-window (window buffer not-this-window) - "Reuse WINDOW for displaying BUFFER. -If NOT-THIS-WINDOW is non-nil and WINDOW is the selected window -do nothing and return nil. Return nil also if WINDOW is -dedicated to its buffer. Otherwise, display buffer in WINDOW, -even window heights if requested, and return WINDOW." - (unless (or (and not-this-window (eq window (selected-window))) - (and (window-dedicated-p window) - (not (eq (window-buffer window) buffer)))) - ;; Save `quit-restore' information: It's absolutely necessary to do - ;; this _before_ handling `even-window-heights'. Do not overwrite - ;; an existing value. - (unless (window-parameter window 'quit-restore) - (set-window-parameter - window 'quit-restore - (list (window-buffer window) (window-start window) - (window-point window) buffer (window-total-size window) - (selected-window)))) - ;; Handle `even-window-heights' option. - (when (and even-window-heights - ;; Not needed (but often WINDOW is the selected window): - (not (eq window (selected-window))) - ;; Don't resize minibuffer windows. - (not (window-minibuffer-p)) - ;; Resize iff the selected window is higher than WINDOW. - (> (window-total-size) (window-total-size window)) - ;; Resize vertical combinations only. - (and (window-parent) (window-iso-combined-p (window-parent)) - ;; WINDOW must be adjacent to the selected one. - (or (eq window (window-prev)) (eq window (window-next))))) - ;; Don't throw an error if we can't even window heights for - ;; whatever reason. In any case, enlarging the selected window - ;; might fail anyway if there are other windows above or below - ;; WINDOW and the selected one. But for a simple two windows - ;; configuration the present behavior is good enough so why care? - (condition-case nil - (resize-window - window (/ (- (window-total-size window) (window-total-size)) 2)) - (error nil))) - (display-buffer-window-and-buffer window (window-buffer window)) - ;; Display BUFFER in WINDOW. - (window--display-buffer-in-window buffer window))) - -;; This variable should be probably documented in the manual. (defvar display-buffer-mark-dedicated nil "If non-nil, `display-buffer' marks the windows it creates as dedicated. The actual non-nil value of this variable will be copied to the `window-dedicated-p' flag.") - -(defun window--pop-up-window (buffer frame) - "Pop up a new window for BUFFER on FRAME. -If FRAME cannot be split, try to pop up a window on the last -nonminibuffer frame instead. Return the new window if splitting -succeeded, nil otherwise. - -See the documentation of the variable `pop-up-windows' how to -choose the window to be split for popping up the new one." - (when (or (and (window--usable-frame frame) - (not (frame-parameter frame 'unsplittable))) - (and (setq frame (last-nonminibuffer-frame)) - (window--usable-frame frame) - (not (frame-parameter frame 'unsplittable)))) - (let* ((selected-window (selected-window)) - (windows (window-list-1 (frame-first-window frame) 'nomini frame)) - (probes (if (eq pop-up-windows t) '(largest lru) pop-up-windows)) - window new-window) - (catch 'done - ;; Try to find a window suiting `pop-up-windows'. - (dolist (probe probes) - (setq window - (cond - ((eq probe 'selected) - (frame-selected-window frame)) - ((eq probe 'largest) - (get-largest-window frame t)) - ((eq probe 'lru) - (get-lru-window frame t)) - ((eq probe 'root) - (frame-root-window frame)))) - ;; Do not consider `window' again. - (setq windows (remq window windows)) - (when (and (eq (window-frame window) frame) - (not (window-minibuffer-p window)) - (not (frame-parameter frame 'unsplittable)) - (setq new-window - ;; Since `split-window-preferred-function' might - ;; throw an error use `condition-case'. - (condition-case nil - (funcall split-window-preferred-function window) - (error nil)))) - (set-window-parameter - new-window 'quit-restore (list t selected-window)) - (display-buffer-window-and-buffer new-window t) - (window--display-buffer-in-window - buffer new-window display-buffer-mark-dedicated) - (throw 'done new-window))))))) - -(defun window--pop-up-frame (buffer) - "Pop up a new frame for displaying BUFFER. -Return the window displaying BUFFER if creating the new frame was -successful, nil otherwise." - (let* ((selected-window (selected-window)) - (frame (funcall pop-up-frame-function)) - (window (when frame (frame-selected-window frame)))) - (when window - (display-buffer-window-and-buffer window t) - (window--display-buffer-in-window - buffer window display-buffer-mark-dedicated) - ;; Make sure that quitting is allowed to delete the frame. - (set-window-parameter - window 'quit-restore (list t selected-window)) - window))) - -(defun window--raise-window-frame (&optional window) - "Raise the frame containing WINDOW. -WINDOW must be a live window and defaults to the selected one. -Return WINDOW. - -This function does not raise the selected or an invisible frame." - (setq window (normalize-live-window window)) - (let* ((frame (window-frame window)) - (visible (frame-visible-p frame))) - (unless (or (not visible) - ;; Assume the selected frame is already visible enough. - (eq frame (selected-frame)) - ;; Assume the frame from which we invoked the minibuffer - ;; is visible. - (and (minibuffer-window-active-p (selected-window)) - (eq frame (window-frame (minibuffer-selected-window))))) - (raise-frame frame)) - window)) - -(defun display-buffer (buffer-or-name &optional not-this-window frame) - "Make buffer BUFFER-OR-NAME appear in some window but don't select it. -BUFFER-OR-NAME must be a buffer or the name of an existing -buffer. Return the window chosen to display BUFFER-OR-NAME or -nil if no such window is found. - -Optional argument NOT-THIS-WINDOW non-nil means display the -buffer in a window other than the selected one, even if it is -already displayed in the selected window. - -Optional argument FRAME specifies which frames to investigate -when the specified buffer is already displayed. If the buffer is -already displayed in some window on one of these frames simply -return that window. Possible values of FRAME are: - -`visible' - consider windows on all visible frames. - -0 - consider windows on all visible or iconified frames. - -t - consider windows on all frames. - -A specific frame - consider windows on that frame only. - -nil - consider windows on the selected frame \(actually the -last non-minibuffer frame\) only. If, however, either -`display-buffer-reuse-frames' or `pop-up-frames' is non-nil -\(non-nil and not graphic-only on a text-only terminal), -consider all visible or iconified frames." - (interactive "BDisplay buffer:\nP") - (let* ((buffer (normalize-live-buffer buffer-or-name)) - (buffer-name (buffer-name buffer)) - (can-use-selected-window - ;; We can reuse the selected window unless NOT-THIS-WINDOW is - ;; non-nil, or the selected window is either dedicated to its - ;; buffer, or it is a `minibuffer-window'. - (not (or not-this-window - (window-dedicated-p) - (window-minibuffer-p)))) - ;; On text-only terminals do not pop up a new frame when - ;; `pop-up-frames' equals graphic-only. - (pop-up-frame (if (eq pop-up-frames 'graphic-only) - (display-graphic-p) - pop-up-frames)) - ;; `frame-to-use' is the frame where to show `buffer' - either - ;; the selected frame or the last nonminibuffer frame. - (frame-to-use - (or (window--usable-frame (selected-frame)) - (window--usable-frame (last-nonminibuffer-frame)))) - ;; `window-to-use' is the window we use for showing `buffer'. - window-to-use) - (cond - (display-buffer-function - ;; Let `display-buffer-function' do the job. - (funcall display-buffer-function buffer not-this-window)) - ((and (not not-this-window) (eq (window-buffer) buffer)) - ;; The selected window already displays BUFFER and NOT-THIS-WINDOW - ;; is nil, so reuse the selected window. - (selected-window)) - ((and can-use-selected-window (same-window-p buffer-name)) - ;; If the buffer's name tells us to use the selected window do so. - (display-buffer-window-and-buffer (selected-window)) - (window--display-buffer-in-window buffer (selected-window))) - ((let ((frames (or frame - (and (or pop-up-frame - display-buffer-reuse-frames - (not (last-nonminibuffer-frame))) - 0) - (last-nonminibuffer-frame)))) - (setq window-to-use - (catch 'found - ;; Search frames for a window displaying BUFFER. Return - ;; the selected window only if we are allowed to do so. - (dolist (window (get-buffer-window-list buffer 'nomini frames)) - (when (or can-use-selected-window - (not (eq (selected-window) window))) - (throw 'found window)))))) - ;; The buffer is already displayed in some window; use that. - (display-buffer-window-and-buffer window-to-use) - (window--raise-window-frame window-to-use)) - ((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))) - (when pars - (funcall - special-display-function buffer (and (listp pars) pars)))))) - ((and (or pop-up-frame (not frame-to-use)) - (window--pop-up-frame buffer))) - ((and pop-up-windows - ;; Try popping up a new window. - (window--pop-up-window buffer frame-to-use))) - ((window--reuse-window - ;; Try reusing least recently used window. - (get-lru-window frame-to-use) buffer not-this-window)) - ((window--reuse-window - ;; Try reusing some visible window showing BUFFER. - (get-buffer-window buffer 'visible) buffer not-this-window)) - ((window--reuse-window - ;; Try reusing largest visible window. - (get-largest-window 'visible) buffer not-this-window)) - ((window--reuse-window - ;; Try reusing some window showing BUFFER on any visible or - ;; iconified frame. - (get-buffer-window buffer 0) buffer not-this-window)) - ((window--reuse-window - ;; Try reusing largest window on any visible or iconified frame. - (get-largest-window 0) buffer not-this-window)) - ;; As a last resort try popping up a new frame. - ((window--pop-up-frame buffer))))) - -(defun pop-to-buffer (buffer-or-name &optional other-window norecord) - "Select buffer BUFFER-OR-NAME in some window, preferably a different one. -BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or -nil. If BUFFER-OR-NAME is a string not naming an existent -buffer, create a buffer with that name. If BUFFER-OR-NAME is -nil, choose some other buffer. Return the buffer specified by -BUFFER-OR-NAME. - -If optional second arg OTHER-WINDOW is non-nil, insist on finding -another window even if the specified buffer is already visible in -the selected window, and ignore the options `same-window-regexps' -and `same-window-buffer-names'. - -Optional argument NORECORD non-nil means do not put the buffer -specified by BUFFER-OR-NAME at the front of the buffer list and -do not make the window displaying it the most recently selected -one. - -This uses the function `display-buffer' as a subroutine; see the -documentation of `display-buffer' for additional customization -information." - (let ((buffer - ;; FIXME: This behavior is carried over from the previous C - ;; version of pop-to-buffer, but really we should use just - ;; `get-buffer' here. - (if (null buffer-or-name) - (other-buffer (current-buffer)) - (or (get-buffer buffer-or-name) - (let ((buf (get-buffer-create buffer-or-name))) - (set-buffer-major-mode buf) - buf)))) - (old-frame (selected-frame)) - new-window new-frame) - (set-buffer buffer) - (setq new-window (display-buffer buffer other-window)) - ;; Select the window chosen. - (select-window new-window norecord) - (setq new-frame (window-frame new-window)) - (unless (eq new-frame old-frame) - ;; `display-buffer' has chosen another frame, make sure it gets - ;; input focus and is risen. - (select-frame-set-input-focus new-frame)) - buffer)) - -(defun read-buffer-to-switch (prompt) - "Read the name of a buffer to switch to and return as a string. -It is intended for `switch-to-buffer' family of commands since they -need to omit the name of current buffer from the list of completions -and default values." - (let ((rbts-completion-table (internal-complete-buffer-except))) - (minibuffer-with-setup-hook - (lambda () - (setq minibuffer-completion-table rbts-completion-table) - ;; Since rbts-completion-table is built dynamically, we - ;; can't just add it to the default value of - ;; icomplete-with-completion-tables, so we add it - ;; here manually. - (if (and (boundp 'icomplete-with-completion-tables) - (listp icomplete-with-completion-tables)) - (set (make-local-variable 'icomplete-with-completion-tables) - (cons rbts-completion-table - icomplete-with-completion-tables)))) - (read-buffer prompt (other-buffer (current-buffer)) - (confirm-nonexistent-file-or-buffer))))) - -(defun switch-to-buffer (buffer-or-name &optional norecord) - "Switch to buffer BUFFER-OR-NAME in the selected window. -If BUFFER-OR-NAME does not identify an existing buffer, then this -function creates a buffer with that name. - -If called interactively, prompt for the buffer name using the -minibuffer. The variable `confirm-nonexistent-file-or-buffer' -determines whether to request confirmation before creating a new -buffer. - -When called from Lisp, BUFFER-OR-NAME may be a buffer, a string -\(a buffer name), or nil. If BUFFER-OR-NAME is nil, then this -function chooses a buffer using `other-buffer'. - -Optional argument NORECORD non-nil means do not put the buffer -specified by BUFFER-OR-NAME at the front of the buffer list and -do not make the window displaying it the most recently selected -one. - -WARNING: Do NOT use this function to work on another buffer -temporarily within a Lisp program! Use `with-current-buffer' -instead. That avoids messing with the window-buffer -correspondences." - (interactive - (list (read-buffer-to-switch "Switch to buffer: "))) - (let ((buffer (when buffer-or-name (get-buffer buffer-or-name)))) - (cond - ((eq buffer (window-buffer)) - (unless norecord - (select-window (selected-window))) - (set-buffer buffer)) - ((or (window-minibuffer-p) (eq (window-dedicated-p) t)) - ;; Cannot switch to another buffer in a minibuffer or strongly - ;; dedicated window. Call `pop-to-buffer' instead. - (pop-to-buffer buffer nil norecord)) - (t - (unless buffer - (if buffer-or-name - ;; Create a buffer named BUFFER-OR-NAME. - (progn - (setq buffer (get-buffer-create buffer-or-name)) - (set-buffer-major-mode buffer)) - ;; Use other buffer. - (setq buffer (other-buffer (current-buffer))))) - (set-window-buffer nil buffer) - (unless norecord - (select-window (selected-window))) - (set-buffer buffer))))) - -(defun switch-to-buffer-other-window (buffer-or-name &optional norecord) - "Switch to buffer BUFFER-OR-NAME in another window. -BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or -nil. Return the buffer switched to. - -If called interactively, prompt for the buffer name using the -minibuffer. The variable `confirm-nonexistent-file-or-buffer' -determines whether to request confirmation before creating a new -buffer. - -If BUFFER-OR-NAME is a string and does not identify an existing -buffer, create a new buffer with that name. If BUFFER-OR-NAME is -nil, switch to the buffer returned by `other-buffer'. - -Optional argument NORECORD non-nil means do not put the buffer -specified by BUFFER-OR-NAME at the front of the buffer list and -do not make the window displaying it the most recently selected -one. - -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 ((pop-up-windows (or pop-up-windows t)) - same-window-buffer-names same-window-regexps) - (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. -BUFFER-OR-NAME may be a buffer, a string \(a buffer name), or -nil. Return the buffer switched to. - -If called interactively, prompt for the buffer name using the -minibuffer. The variable `confirm-nonexistent-file-or-buffer' -determines whether to request confirmation before creating a new -buffer. - -If BUFFER-OR-NAME is a string and does not identify an existing -buffer, create a new buffer with that name. If BUFFER-OR-NAME is -nil, switch to the buffer returned by `other-buffer'. - -Optional argument NORECORD non-nil means do not put the buffer -specified by BUFFER-OR-NAME at the front of the buffer list and -do not make the window displaying it the most recently selected -one. - -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 ((pop-up-frames t) - same-window-buffer-names same-window-regexps) - (pop-to-buffer buffer-or-name t norecord))) +(make-obsolete-variable + 'display-buffer-mark-dedicated + "use `display-buffer-names', `display-buffer-regexps' or 2nd arg of `display-buffer' instead." + "24.1") (defun set-window-text-height (window height) "Set the height in lines of the text display area of WINDOW to HEIGHT. -- 2.39.5