1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-26 10:49:33 +00:00

Document and fix some bugs with side windows

Add a documentation for side windows and fix some bugs
found when testing their behavior.  Also add a new window
parameter `no-delete-other-window', a new `display-buffer'
alist member called `window-parameters', and functions to
toggle and reverse side windows on a frame.  Add new function
`window-swap-states' to exchange states of two live windows.

* lisp/window.el (display-buffer-in-atom-window): Use
`split-window-no-error'.
(window-sides-vertical): Maybe change layouts when setting this
variable.
(window-sides-reversed): New option.
(window-sides-slots): Rewrite doc-string and help echoes.
(window-sides-shown): New buffer-local variable set when showing
a buffer in a side window.
(window--sides-inhibit-check): New variable.
(window--sides-reverse-on-frame-p, window-toggle-side-windows)
(window--sides-reverse-all, window--sides-reverse-frame)
(window--sides-reverse-side, window--sides-reverse)
(window--sides-verticalize-frame, window--sides-verticalize)
(window--sides-check-failed): New functions.
(window--side-window-p): Remove function.
(window--major-non-side-window): Rename to `window-main-window',
adjust callers, rewrite doc-string.
(window--major-side-window): Rename to
`window--make-major-side-window-next-to', adjust caller, fix
doc-string.
(display-buffer-in-major-side-window): Rename to
`window--make-major-side-window', adjust
caller, rewrite doc-string.  Make `window-side' and
`window-slot' parameters persistent (Bug#23858).  Don't set
`delete-window' parameter.  Add `preserve-size' entry to ALIST.
(delete-side-window): Remove function.
(display-buffer-in-side-window): Fix doc-string.  Don't set
`delete-window' parameter.  Add `preserve-size' entry to ALIST.
(window--side-check): Rename to window--sides-check.  Rewrite
completely.  Adjust caller.
(window-resize-no-error): Don't describe PIXELWISE argument.
(adjust-window-trailing-edge): Fix bug that disallowed
re-enlarging windows that were too small.
(window-deletable-p): Don't tell that a minibuffer window on a
non-minibuffer-only frame can be deleted.  Fix doc-string.
(delete-window): Handle deleting a side window here (the
`delete-window' parameter is no more set for side windows).
(delete-other-windows): Handle ‘no-delete-other-window'
parameter. Don't treat side windows separately (see discussion
of Bug#24368) but keep optimization that makes the main window
the root window of its frame.
(switch-to-prev-buffer, switch-to-next-buffer): Handle side
windows and buffers shown in side windows separately.
(split-window-no-error): New function.
(window--state-get-1): Use right buffer when storing window
point and start positions and WRITABLE is nil (Bug#24368).
(window--state-put-1): Fix handling of `window-combination-limit'.
Use `split-window-no-error'.
(window--state-put-2): Try to restore windows with preserved
size to their original size.  Fix bug where a fixed window's width
was not preserved.
(window-state-put): When reducing an internal window to a live
one, don't choose a side window.
(window-swap-states): New function.
(window-splittable-p): Don't call `window--side-window-p'.
(window--display-buffer): Handle `window-parameters' ALIST entry.
Minor rewrite.
(display-buffer): Mention `window-parameters' entry in
doc-string.
(display-buffer-at-bottom): Call `split-window-no-error'.

* doc/lispref/elisp.texi (Top): New section "Side Windows".
* doc/lispref/windows.texi (Deleting Windows): Fix descriptions
of `delete-window' and `delete-other-windows' wrt window
parameters and side windows.
(Display Action Functions): Mention `window-parameters' ALIST
entry.
(Side Windows): New section (Bug#18170).
(Window Configurations): Describe new function `window-swap-states'.
(Window Parameters): Say that functions may behave specially when
their homonymous window parameter has been set.  Mention new
parameter `no-delete-other-window'.  Add cross reference for
`window-side' and `window-slot' parameters.
This commit is contained in:
Martin Rudalics 2016-10-05 10:28:36 +02:00
parent 13ba5af742
commit b8fd71d570
4 changed files with 1004 additions and 310 deletions

View File

@ -1038,6 +1038,7 @@ Windows
a specific window.
* Quitting Windows:: How to restore the state prior to displaying a
buffer.
* Side Windows:: Special windows on a frame's sides.
* Window Point:: Each window has its own location of point.
* Window Start and End:: Buffer positions indicating which text is
on-screen in a window.
@ -1051,6 +1052,14 @@ Windows
redisplay going past a certain point,
or window configuration changes.
Side Windows
* Displaying Buffers in Side Windows:: An action function for displaying
buffers in side windows.
* Side Window Options and Functions:: Further tuning of side windows.
* Frame Layouts with Side Windows:: Setting up frame layouts with side
windows.
Frames
* Creating Frames:: Creating additional frames.

View File

@ -33,6 +33,7 @@ is displayed in windows.
a specific window.
* Quitting Windows:: How to restore the state prior to displaying a
buffer.
* Side Windows:: Special windows on a frame's sides.
* Window Point:: Each window has its own location of point.
* Window Start and End:: Buffer positions indicating which text is
on-screen in a window.
@ -1275,9 +1276,12 @@ Configurations}).
@deffn Command delete-window &optional window
This function removes @var{window} from display and returns
@code{nil}. If @var{window} is omitted or @code{nil}, it defaults to
the selected window. If deleting the window would leave no more
windows in the window tree (e.g., if it is the only live window in the
frame), an error is signaled.
the selected window.
If deleting the window would leave no more windows in the window tree
(e.g., if it is the only live window in the frame) or all remaining
windows on @var{window}'s frame are side windows (@pxref{Side Windows}),
an error is signaled.
By default, the space taken up by @var{window} is given to one of its
adjacent sibling windows, if any. However, if the variable
@ -1285,33 +1289,34 @@ adjacent sibling windows, if any. However, if the variable
proportionally distributed among any remaining windows in the same
window combination. @xref{Recombining Windows}.
The behavior of this function may be altered by the window parameters
of @var{window}, so long as the variable
@code{ignore-window-parameters} is @code{nil}. If the value of
the @code{delete-window} window parameter is @code{t}, this function
ignores all other window parameters. Otherwise, if the value of the
@code{delete-window} window parameter is a function, that function is
called with the argument @var{window}, in lieu of the usual action of
@code{delete-window}. Otherwise, this function obeys the
@code{window-atom} or @code{window-side} window parameter, if any.
@xref{Window Parameters}.
The behavior of this function may be altered by the window parameters of
@var{window}, so long as the variable @code{ignore-window-parameters} is
@code{nil}. If the value of the @code{delete-window} window parameter
is @code{t}, this function ignores all other window parameters.
Otherwise, if the value of the @code{delete-window} window parameter is
a function, that function is called with the argument @var{window}, in
lieu of the usual action of @code{delete-window}. @xref{Window
Parameters}.
@end deffn
@deffn Command delete-other-windows &optional window
This function makes @var{window} fill its frame, by deleting other
windows as necessary. If @var{window} is omitted or @code{nil}, it
defaults to the selected window. The return value is @code{nil}.
This function makes @var{window} fill its frame, deleting other windows
as necessary. If @var{window} is omitted or @code{nil}, it defaults to
the selected window. An error is signaled if @var{window} is a side
window (@pxref{Side Windows}). The return value is @code{nil}.
The behavior of this function may be altered by the window parameters
of @var{window}, so long as the variable
@code{ignore-window-parameters} is @code{nil}. If the value of
the @code{delete-other-windows} window parameter is @code{t}, this
function ignores all other window parameters. Otherwise, if the value
of the @code{delete-other-windows} window parameter is a function,
that function is called with the argument @var{window}, in lieu of the
usual action of @code{delete-other-windows}. Otherwise, this function
obeys the @code{window-atom} or @code{window-side} window parameter,
if any. @xref{Window Parameters}.
The behavior of this function may be altered by the window parameters of
@var{window}, so long as the variable @code{ignore-window-parameters} is
@code{nil}. If the value of the @code{delete-other-windows} window
parameter is @code{t}, this function ignores all other window
parameters. Otherwise, if the value of the @code{delete-other-windows}
window parameter is a function, that function is called with the
argument @var{window}, in lieu of the usual action of
@code{delete-other-windows}. @xref{Window Parameters}.
Also, if @code{ignore-window-parameters} is @code{nil}, this function
does not delete any window whose @code{no-delete-other-window} parameter
is non-@code{nil}.
@end deffn
@deffn Command delete-windows-on &optional buffer-or-name frame
@ -2574,7 +2579,12 @@ assumed that when the caller specifies a non-@code{nil}
from @code{display-buffer} in this case.
@end defun
To illustrate the use of action functions, consider the following
If the @var{alist} argument of any of these functions contains a
@code{window-parameters} entry, @code{display-buffer} assigns the
elements of the associated value as window parameters of the chosen
window.
To illustrate the use of action functions, consider the following
example.
@example
@ -3068,6 +3078,295 @@ other frame on the same terminal.
@end defopt
@node Side Windows
@section Side Windows
@cindex side windows
@cindex main window
@cindex main window of a frame
Side windows are special windows positioned at any of the four sides of
a frame's root window (@pxref{Windows and Frames}). In practice, this
means that the area of the frame's root window is subdivided into a main
window and a number of side windows surrounding that main window. The
main window is either a ``normal'' live window or specifies the area
containing all the normal windows.
In their most simple form of use, side windows allow to display
specific buffers always in the same area of a frame. Hence they can be
regarded as a generalization of the concept provided by
@code{display-buffer-at-bottom} (@pxref{Display Action Functions}) to
the remaining sides of a frame. With suitable customizations, however,
side windows can be also used to provide frame layouts similar to those
found in so-called integrated development environments (IDEs).
@menu
* Displaying Buffers in Side Windows:: An action function for displaying
buffers in side windows.
* Side Window Options and Functions:: Further tuning of side windows.
* Frame Layouts with Side Windows:: Setting up frame layouts with side
windows.
@end menu
@node Displaying Buffers in Side Windows
@subsection Displaying Buffers in Side Windows
The following action function for @code{display-buffer} (@pxref{Display
Action Functions}) creates or reuses a side window for displaying the
specified buffer.
@defun display-buffer-in-side-window buffer alist
This function displays @var{buffer} in a side window of the selected
frame. @var{alist} is an association list of symbols and values as for
@code{display-buffer}. The following symbols in @var{alist} are special
for this function:
@table @code
@item side
Denotes the side of the frame where the window shall be located. Valid
values are @code{left}, @code{top}, @code{right} and @code{bottom}. If
unspecified, the window is located at the bottom of the frame.
@item slot
Denotes a slot at the specified side where to locate the window. A
value of zero means to preferably position the window in the middle of
the specified side. A negative value means to use a slot preceding
(that is, above or on the left of) the middle slot. A positive value
means to use a slot following (that is, below or on the right of) the
middle slot. Hence, all windows on a specific side are ordered by their
@code{slot} value. If unspecified, the window is located in the middle
of the specified side.
@end table
If you specify the same slot on the same side for two or more different
buffers, the buffer displayed last is shown in the corresponding window.
Hence, slots can be used for sharing the same side window between
buffers.
This function installs the @code{window-side} and @code{window-slot}
parameters (@pxref{Window Parameters}) and makes them persistent. It
does not install any other window parameters unless they have been
explicitly provided via a @code{window-parameters} entry in @var{alist}.
@end defun
By default, side windows cannot be split via @code{split-window}
(@pxref{Splitting Windows}). Also, a side window is not reused or split
by any buffer display action (@pxref{Display Action Functions}) unless
it is explicitly specified as target of that action. Note also that
@code{delete-other-windows} cannot make a side window the only window on
its frame (@pxref{Deleting Windows}).
Once set up, side windows also change the behavior of the commands
@code{switch-to-prev-buffer} and @code{switch-to-next-buffer}
(@pxref{Window History}). In particular, these commands will refrain
from showing, in a side window, buffers that have not been displayed in
that window before. And, they will refrain from having a normal,
non-side window show a buffer that has been already displayed in a side
window. A notable exception to the latter rule occurs when an
application, after displaying a buffer, resets that buffer's local
variables.
@node Side Window Options and Functions
@subsection Side Window Options and Functions
The following options provide additional control over the placement of
side windows.
@defopt window-sides-vertical
If non-@code{nil}, this means that the side windows on the left and
right of a frame occupy the frame's full height. Otherwise, the side
windows on the top and bottom of the frame occupy the frame's full
width.
@end defopt
@defopt window-sides-slots
This option specifies the maximum number of side windows on each side of
a frame. The value is a list of four elements specifying the number of
side window slots on (in this order) the left, top, right and bottom of
each frame. If an element is a number, this means to display at most
that many windows on the corresponding side. If an element is
@code{nil}, this means there's no bound on the number of slots on that
side.
If any of the specified values is zero, no window can be created on the
corresponding side. @code{display-buffer-in-side-window} will not
signal an error in that case but return @code{nil}. If a specified
value just forbids the creation of an additional side window, the most
suitable window on that side is reused and may have its
@code{window-slot} parameter changed accordingly.
@end defopt
@defopt window-sides-reversed
This option specifies whether top/bottom side windows should appear in
reverse order. When this is @code{nil}, side windows on the top and
bottom of a frame are always drawn from left to right with increasing
slot values. When this is @code{t}, the drawing order is reversed and
side windows on the top and bottom of a frame are drawn from right to
left with increasing slot values.
When this is @code{bidi}, the drawing order is reversed if and only if
the value of @code{bidi-paragraph-direction} is @code{right-to-left} in
the buffer displayed in the window most recently selected within the
main window area of this frame. Sometimes that window may be hard to
find, so heuristics are used to avoid that the drawing order changes
inadvertently when another window gets selected.
The layout of side windows on the left or right of a frame is not
affected by the value of this variable.
@end defopt
When a frame has side windows, the following function returns the main
window of that frame.
@defun window-main-window &optional frame
This function returns the main window of the specified @var{frame}. The
optional argument @var{frame} must be a live frame and defaults to the
selected one.
If @var{frame} has no side windows, it returns @var{frame}'s root
window. Otherwise, it returns either an internal non-side window such
that all other non-side windows on @var{frame} descend from it, or the
single live non-side window of @var{frame}. Note that the main window
of a frame cannot be deleted via @code{delete-window}.
@end defun
The following command is handy to toggle the appearance of all side
windows on a specified frame.
@deffn Command window-toggle-side-windows &optional frame
This command toggles side windows on the specified @var{frame}. The
optional argument @var{frame} must be a live frame and defaults to the
selected one.
If @var{frame} has at least one side window, this command saves the
state of @var{frame}'s root window in the @var{frame}'s
@code{window-state} frame parameter and deletes all side windows on
@var{frame} afterwards.
If @var{frame} has no side window but a @code{window-state} parameter,
it uses that parameter's value to restore the side windows on
@var{frame} leaving @var{frame}'s main window alone.
An error is signaled if @var{frame} has no side window and no saved
state is found.
@end deffn
@node Frame Layouts with Side Windows
@subsection Frame Layouts with Side Windows
Side windows can be used to create more complex frame layouts like those
provided by integrated development environments (IDEs). In such
layouts, the area of the main window is where the normal editing
activities take place. Side windows are not conceived for editing in
the usual sense. Rather, they are supposed to display information
complementary to the current editing activity, like lists of files, tags
or buffers, help information, search or grep results or shell output.
The layout of such a frame might appear as follows:
@smallexample
@group
___________________________________
| *Buffer List* |
|___________________________________|
| | | |
| * | | * |
| d | | T |
| i | | a |
| r | Main Window Area | g |
| e | | s |
| d | | * |
| * | | |
|_____|_______________________|_____|
| *help*/*grep*/ | *shell*/ |
| *Completions* | *compilation* |
|_________________|_________________|
| Echo Area |
|___________________________________|
@end group
@end smallexample
The following example illustrates how window parameters (@pxref{Window
Parameters}) can be used with @code{display-buffer-in-side-window}
(@pxref{Displaying Buffers in Side Windows}) to set up code for
producing the frame sketched above.
@example
@group
(defvar parameters
'(window-parameters . ((no-other-window . t) (no-delete-other-window . t))))
(setq fit-window-to-buffer-horizontally t)
(setq window-resize-pixelwise t)
(setq
display-buffer-alist
`(("\\*Buffer List\\*" display-buffer-in-side-window
(side . top) (slot . 0) (window-height . fit-window-to-buffer)
(preserve-size . (nil . t)) ,parameters)
("\\*Tags List\\*" display-buffer-in-side-window
(side . right) (slot . 0) (window-width . fit-window-to-buffer)
(preserve-size . (t . nil)) ,parameters)
("\\*\\(?:help\\|grep\\|Completions\\)\\*" display-buffer-in-side-window
(side . bottom) (slot . -1) (preserve-size . (nil . t)) ,parameters)
("\\*\\(?:shell\\|compilation\\)\\*" display-buffer-in-side-window
(side . bottom) (slot . 1) (preserve-size . (nil . t)) ,parameters)))
@end group
@end example
This specifies @code{display-buffer-alist} entries (@pxref{Choosing
Window}) for buffers with fixed names. In particular, it asks for
showing @file{*Buffer List*} with adjustable height at the top of the
frame and @file{*Tags List*} with adjustable width on the frame's right.
It also asks for having the @file{*help*}, @file{*grep*} and
@file{*Completions*} buffers share a window on the bottom left side of
the frame and the @file{*shell*} and @file{*compilation*} buffers appear
in a window on the bottom right side of the frame.
Note that the option @code{fit-window-to-buffer-horizontally} must
have a non-@code{nil} value in order to allow horizontal adjustment of
windows. We also added entries that ask for preserving the height of
side windows at the top and bottom of the frame and the width of side
windows at the left or right of the frame. To assure that side windows
retain their respective sizes when maximizing the associated frame, we
have also set the variable @code{window-resize-pixelwise}.
@xref{Resizing Windows}.
The last form also makes sure that none of the side windows it
creates are accessible via @kbd{C-x o} by installing a
@code{no-other-window} parameter for each of these windows. In addition
it also makes sure that side windows are not deleted via @kbd{C-x 1} by
installing a @code{no-delete-other-window} parameter on each of these
windows.
Since @code{dired} buffers have no fixed names, we use a special
function @code{dired-default-directory-on-left} in order to display a
lean directory buffer on the left side of the frame.
@example
@group
(defun dired-default-directory-on-left ()
"Display `default-directory' in side window on left, hiding details."
(interactive)
(let ((buffer (dired-noselect default-directory)))
(with-current-buffer buffer (dired-hide-details-mode t))
(display-buffer-in-side-window
buffer `((side . left) (slot . 0)
(window-width . fit-window-to-buffer)
(preserve-size . (t . nil)) ,parameters))))
@end group
@end example
Evaluating the preceding forms and typing, in any order, @kbd{M-x
list-buffers}, @kbd{C-h f}, @kbd{M-x shell}, @kbd{M-x list-tags} and
@kbd{M-x dired-default-directory-on-left} should now reproduce the frame
layout sketched above.
@node Window Point
@section Windows and Point
@cindex window position
@ -4242,6 +4541,25 @@ is @code{safe}, this means windows can get as small as one line
and/or two columns.
@end defun
The functions @code{window-state-get} and @code{window-state-put} also
allow to exchange the contents of two live windows. The following
function does precisely that:
@deffn Command window-swap-states &optional window-1 window-2 size
This command swaps the states of the two live windows @var{window-1} and
@var{window-2}. @var{window-1} must specify a live window and defaults
to the selected one. @var{window-2} must specify a live window and
defaults to the window following @var{window-1} in the cyclic ordering
of windows, excluding minibuffer windows and including live windows on
all visible frames.
Optional argument @var{size} non-@code{nil} means to try swapping the
sizes of @var{window-1} and @var{window-2} as well. A value of
@code{height} means to swap heights only, a value of @code{width}
means to swap widths only, while @code{t} means to swap both widths
and heights, if possible. Frames are not resized by this function.
@end deffn
@node Window Parameters
@section Window Parameters
@ -4279,6 +4597,7 @@ earlier by @code{window-state-get}, all cloned windows have their
parameters reset to @code{nil}. The following variable allows you to
override the standard behavior:
@cindex persistent window parameters
@defvar window-persistent-parameters
This variable is an alist specifying which parameters get saved by
@code{current-window-configuration} and @code{window-state-get}, and
@ -4308,10 +4627,10 @@ may fail with an @code{invalid-read-syntax} error.
@end defvar
Some functions (notably @code{delete-window},
@code{delete-other-windows} and @code{split-window}), may behave specially
when their @var{window} argument has a parameter set. You can override
such special behavior by binding the following variable to a
non-@code{nil} value:
@code{delete-other-windows} and @code{split-window}), may behave
specially when the window specified by their @var{window} argument has
the homonymous parameter set. You can override such special behavior by
binding the following variable to a non-@code{nil} value:
@defvar ignore-window-parameters
If this variable is non-@code{nil}, some standard functions do not
@ -4337,6 +4656,10 @@ This parameter affects the execution of @code{delete-window}
This parameter affects the execution of @code{delete-other-windows}
(@pxref{Deleting Windows}).
@item @code{no-delete-other-window}
This parameter marks the window as not deletable by
@code{delete-other-windows} (@pxref{Deleting Windows}).
@item @code{split-window}
This parameter affects the execution of @code{split-window}
(@pxref{Splitting Windows}).
@ -4387,6 +4710,10 @@ The fourth element is the buffer whose display caused the creation of
this parameter. @code{quit-restore-window} deletes the specified window
only if it still shows that buffer.
@item @code{window-side} @code{window-slot}
These parameters are used for implementing side windows (@pxref{Side
Windows}).
@item @code{min-margins}
The value of this parameter is a cons cell whose @sc{car} and @sc{cdr},
if non-@code{nil}, specify the minimum values (in columns) for the left
@ -4409,8 +4736,7 @@ applications. It might be replaced by an improved solution in future
versions of Emacs.
@end table
There are additional parameters @code{window-atom} and @code{window-side};
these are reserved and should not be used by applications.
The @code{window-atom} parameter is used for implemeting atomic windows.
@node Window Hooks

View File

@ -611,6 +611,27 @@ collection).
** The new functions 'make-nearby-temp-file' and 'temporary-file-directory'
can be used for creation of temporary files of remote or mounted directories.
** Changes in Frame- and Window- Handling
+++
*** Support for side windows is now official. The display action
function `display-buffer-in-side-window' will display its buffer in a
side window. Functions for toggling all side windows on a frame,
changing and reversing the layout of side windows and returning the main
(major non-side) window of a frame are provided. For details consult
the section "Side Windows" in the Elisp manual.
+++
*** New `display-buffer' alist entry `window-parameters' allows to
assign window parameters to the window used for displaying the buffer.
+++
*** New window parameter `no-delete-other-window' prevents that
its window gets deleted by `delete-other-windows'.
+++
*** New command `window-swap-states' swaps the states of two live
windows.
* Changes in Emacs 26.1 on Non-Free Operating Systems

File diff suppressed because it is too large Load Diff