Provide persistent window parameters.

* window.c (Vwindow_persistent_parameters): New variable.
(Fset_window_configuration, save_window_save): Handle persistent
window parameters.

* window.el (window-state-ignored-parameters): Remove variable.
(window--state-get-1): Rename argument MARKERS to IGNORE.
Handle persistent window parameters.  Make copy of clone-of
parameter only if requested.  (Bug#10348)
(window--state-put-2): Install a window parameter only if it has
a non-nil value or an existing parameter shall be overwritten.

* windows.texi (Window Configurations, Window Parameters):
Describe persistent window parameters.
This commit is contained in:
Martin Rudalics 2012-01-16 10:34:41 +01:00
parent 97912defd3
commit 6a6ee00d12
6 changed files with 241 additions and 47 deletions

View file

@ -1,3 +1,8 @@
2012-01-16 Martin Rudalics <rudalics@gmx.at>
* windows.texi (Window Configurations, Window Parameters):
Describe persistent window parameters.
2011-12-27 Stefan Monnier <monnier@iro.umontreal.ca>
* variables.texi (Creating Buffer-Local): Warn against misuses of

View file

@ -3104,7 +3104,9 @@ window configuration; see @ref{Frame Configurations}.
@defun current-window-configuration &optional frame
This function returns a new object representing @var{frame}'s current
window configuration. The default for @var{frame} is the selected
frame.
frame. This function saves copies of window parameters listed by the
variable @code{window-persistent-parameters}, see @ref{Window
Parameters} for details.
@end defun
@defun set-window-configuration configuration
@ -3206,24 +3208,30 @@ configurations.
The objects returned by @code{current-window-configuration} die
together with the Emacs process. In order to store a window
configuration on disk and read it back in another Emacs session the
following two functions can be used.
configuration on disk and read it back in another Emacs session, the
functions described next can be used. These functions are also useful
to clone the state of a frame into an arbitrary live window
(@code{set-window-configuration} effectively clones the windows of a
frame into the root window of that very frame only).
@defun window-state-get &optional window markers
@defun window-state-get &optional window ignore
This function returns the state of @var{window} as a Lisp object. The
argument @var{window} can be any window and defaults to the root window
of the selected frame.
The optional argument @var{markers} non-@code{nil} means to use markers
for sampling positions like @code{window-point} or @code{window-start}.
This argument should be non-@code{nil} only if the value is used for
putting the state back in the same session since markers slow down
processing.
If the optional argument @var{ignore} is non-@code{nil}, this means to
not use markers for sampling positions like @code{window-point} or
@code{window-start}. This argument should be non-@code{nil} when the
state shall be written on disk and read back in another session.
The variable @code{window-persistent-parameters} specifies whether and
which window parameters are saved by this function, see @ref{Window
Parameters} for details.
@end defun
The value returned by @code{window-state-get} can be converted by using
The value returned by @code{window-state-get} can be converted, using
one of the functions defined by Desktop Save Mode (@pxref{Desktop Save
Mode}) to an object that can be written to a file. Such objects can be
Mode}), to an object that can be written to a file. Such objects can be
read back and converted to a Lisp object representing the state of the
window. That Lisp object can be used as argument for the following
function in order to restore the state window in another window.
@ -3268,6 +3276,51 @@ This function sets @var{window}'s value of @var{parameter} to
is the selected window.
@end defun
By default, functions saving and restoring window configurations or the
states of windows (@xref{Window Configurations}) do not care about
window parameters. This means, that when you change the value of a
parameter within the body of a @code{save-window-excursion}, the
previous value is not restored upon exit of that macro. It also means
that when you clone via @code{window-state-put} a window state saved
earlier by @code{window-state-get}, the cloned windows come up with no
parameters at all. The following variable allows to override the
standard behavior.
@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
subsequently restored by @code{set-window-configuration} and
@code{window-state-put}, see @ref{Window Configurations}.
The @sc{car} of each entry of this alist is the symbol specifying the
parameter. The @sc{cdr} must be one of the following:
@table @asis
@item @code{state}
This value means the parameter is saved by @code{window-state-get}
provided its @var{ignore} argument is @code{nil}. The function
@code{current-window-configuration} does not save this parameter.
@item @code{nil}
This value specifies that the parameter is saved by
@code{current-window-configuration} and, provided its @var{ignore}
argument is @code{nil}, by @code{window-state-get}.
@item @code{t}
This means that the parameter is saved unconditionally by both
@code{current-window-configuration} and @code{window-state-get}. This
value should not be used for parameters whose values do not have a read
syntax. Otherwise, invoking @code{window-state-put} in another session
may fail with an @code{invalid-read-syntax} error.
@end table
Parameters that have been saved are restored to their previous values by
@code{set-window-configuration} respectively are installed by
@code{window-state-put}. Parameters that have not been saved are left
alone by @code{set-window-configuration} respectively are not installed
by @code{window-state-put}.
@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
@ -3287,7 +3340,7 @@ windows when exiting that function.
@end defvar
The following parameters are currently used by the window management
code.
code:
@table @asis
@item @code{delete-window}
@ -3309,14 +3362,20 @@ This parameter affects the execution of @code{other-window}
@item @code{no-other-window}
This parameter marks the window as not selectable by @code{other-window}
(@pxref{Cyclic Window Ordering}).
@item @code{clone-of}
This parameter specifies the window this one has been cloned from and is
installed by @code{window-state-get}, see @ref{Window Configurations}.
@item @code{quit-restore}
This parameter tells how to proceed with a window when the buffer it
shows is no more needed. It is installed by the buffer display
functions (@pxref{Choosing Window}) and consulted by the function
@code{quit-window} (@pxref{Quitting Windows}).
@end table
In addition, the parameters @code{window-atom} and @code{window-side}
are reserved and should not be used by applications. The
@code{quit-restore} parameter tells how to proceed with a window when
the buffer it shows is no more needed. This parameter is installed by
the buffer display functions (@pxref{Choosing Window}) and consulted by
the function @code{quit-window} (@pxref{Quitting Windows}).
are reserved and should not be used by applications.
@node Window Hooks

View file

@ -1,3 +1,12 @@
2012-01-16 Martin Rudalics <rudalics@gmx.at>
* window.el (window-state-ignored-parameters): Remove variable.
(window--state-get-1): Rename argument MARKERS to IGNORE.
Handle persistent window parameters. Make copy of clone-of
parameter only if requested. (Bug#10348)
(window--state-put-2): Install a window parameter only if it has
a non-nil value or an existing parameter shall be overwritten.
2012-01-15 Michael Albinus <michael.albinus@gmx.de>
* net/tramp-sh.el (tramp-remote-path): Set tramp-autoload cookie.

View file

@ -3568,10 +3568,7 @@ specific buffers."
))
;;; Window states, how to get them and how to put them in a window.
(defvar window-state-ignored-parameters '(quit-restore)
"List of window parameters ignored by `window-state-get'.")
(defun window--state-get-1 (window &optional markers)
(defun window--state-get-1 (window &optional ignore)
"Helper function for `window-state-get'."
(let* ((type
(cond
@ -3589,12 +3586,27 @@ specific buffers."
(normal-width . ,(window-normal-size window t))
(combination-limit . ,(window-combination-limit window))
,@(let (list)
(dolist (parameter (window-parameters window))
(unless (memq (car parameter)
window-state-ignored-parameters)
(setq list (cons parameter list))))
(unless (window-parameter window 'clone-of)
;; Make a clone-of parameter.
;; Make copies of persistent window parameters whose cdr
;; is either t or, when IGNORE is non-nil, is either nil
;; or `state'.
(dolist (pers window-persistent-parameters)
(when (and (consp pers)
(or (eq (cdr pers) t)
(and (memq (cdr pers) '(state nil))
(not ignore))))
(let ((par (assq (car pers) (window-parameters window))))
(setq list (cons (cons (car pers) (when par (cdr par)))
list)))))
;; Save `clone-of' parameter unless IGNORE or
;; `window-persistent-parameters' prevail.
(when (and (not (assq 'clone-of (window-parameters window)))
(let ((clone-of
(assq 'clone-of
window-persistent-parameters)))
(when clone-of
(if ignore
(eq (cdr clone-of) t)
(memq (cdr clone-of) '(state nil))))))
(setq list (cons (cons 'clone-of window) list)))
(when list
`((parameters . ,list))))
@ -3616,30 +3628,31 @@ specific buffers."
(scroll-bars . ,(window-scroll-bars window))
(vscroll . ,(window-vscroll window))
(dedicated . ,(window-dedicated-p window))
(point . ,(if markers (copy-marker point) point))
(start . ,(if markers (copy-marker start) start))
(point . ,(if ignore point (copy-marker point)))
(start . ,(if ignore start (copy-marker start)))
,@(when mark
`((mark . ,(if markers
(copy-marker mark) mark)))))))))))
`((mark . ,(if ignore
mark (copy-marker mark))))))))))))
(tail
(when (memq type '(vc hc))
(let (list)
(setq window (window-child window))
(while window
(setq list (cons (window--state-get-1 window markers) list))
(setq list (cons (window--state-get-1 window ignore) list))
(setq window (window-right window)))
(nreverse list)))))
(append head tail)))
(defun window-state-get (&optional window markers)
(defun window-state-get (&optional window ignore)
"Return state of WINDOW as a Lisp object.
WINDOW can be any window and defaults to the root window of the
selected frame.
Optional argument MARKERS non-nil means use markers for sampling
positions like `window-point' or `window-start'. MARKERS should
be non-nil only if the value is used for putting the state back
in the same session (note that markers slow down processing).
Optional argument IGNORE non-nil means do not use markers for
sampling positions like `window-point' or `window-start' and do
not record parameters unless `window-persistent-parameters'
requests it. IGNORE should be non-nil when the return value
shall be written to a file and read back in another session.
The return value can be used as argument for `window-state-put'
to put the state recorded here into an arbitrary window. The
@ -3665,7 +3678,7 @@ value can be also stored on disk and read back in a new session."
;; These are probably not needed.
,@(when (window-size-fixed-p window) `((fixed-height . t)))
,@(when (window-size-fixed-p window t) `((fixed-width . t))))
(window--state-get-1 window markers)))
(window--state-get-1 window ignore)))
(defvar window-state-put-list nil
"Helper variable for `window-state-put'.")
@ -3744,10 +3757,15 @@ value can be also stored on disk and read back in a new session."
(state (cdr (assq 'buffer item))))
(when combination-limit
(set-window-combination-limit window combination-limit))
;; Process parameters.
;; Assign saved window parameters. If a parameter's value is nil,
;; don't assign it unless the new window has it set already (which
;; shouldn't happen unless some `window-configuration-change-hook'
;; function installed it).
(when parameters
(dolist (parameter parameters)
(set-window-parameter window (car parameter) (cdr parameter))))
(when (or (cdr parameter)
(window-parameter window (car parameter)))
(set-window-parameter window (car parameter) (cdr parameter)))))
;; Process buffer related state.
(when state
;; We don't want to raise an error here so we create a buffer if

View file

@ -1,3 +1,9 @@
2012-01-16 Martin Rudalics <rudalics@gmx.at>
* window.c (Vwindow_persistent_parameters): New variable.
(Fset_window_configuration, save_window_save): Handle persistent
window parameters.
2012-01-14 Eli Zaretskii <eliz@gnu.org>
* w32fns.c (signal_user_input): Don't do a QUIT, to avoid

View file

@ -57,7 +57,7 @@ static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window;
static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertically;
static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
static Lisp_Object Qsafe, Qabove, Qbelow;
static Lisp_Object Qauto_buffer_name;
static Lisp_Object Qauto_buffer_name, Qclone_of, Qstate;
static int displayed_window_lines (struct window *);
static struct window *decode_window (Lisp_Object);
@ -5410,6 +5410,7 @@ the return value is nil. Otherwise the value is t. */)
{
Lisp_Object window;
Lisp_Object dead_windows = Qnil;
register Lisp_Object tem, par, pers;
register struct window *w;
register struct saved_window *p;
struct window *root_window;
@ -5543,7 +5544,28 @@ the return value is nil. Otherwise the value is t. */)
w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
w->dedicated = p->dedicated;
w->combination_limit = p->combination_limit;
w->window_parameters = p->window_parameters;
/* Restore any window parameters that have been saved.
Parameters that have not been saved are left alone. */
for (tem = p->window_parameters; CONSP (tem); tem = XCDR (tem))
{
pers = XCAR (tem);
if (CONSP (pers))
{
if (NILP (XCDR (pers)))
{
par = Fassq (XCAR (pers), w->window_parameters);
if (CONSP (par) && !NILP (XCDR (par)))
/* Reset a parameter to nil if and only if it
has a non-nil association. Don't make new
associations. */
Fsetcdr (par, Qnil);
}
else
/* Always restore a non-nil value. */
Fset_window_parameter (window, XCAR (pers), XCDR (pers));
}
}
XSETFASTINT (w->last_modified, 0);
XSETFASTINT (w->last_overlay_modified, 0);
@ -5810,7 +5832,7 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
{
register struct saved_window *p;
register struct window *w;
register Lisp_Object tem;
register Lisp_Object tem, pers, par;
for (;!NILP (window); window = w->next)
{
@ -5838,12 +5860,60 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
p->dedicated = w->dedicated;
p->combination_limit = w->combination_limit;
p->window_parameters = w->window_parameters;
p->window_parameters = Qnil;
if (!NILP (Vwindow_persistent_parameters))
{
/* Run cycle detection on Vwindow_persistent_parameters. */
Lisp_Object tortoise, hare;
hare = tortoise = Vwindow_persistent_parameters;
while (CONSP (hare))
{
hare = XCDR (hare);
if (!CONSP (hare))
break;
hare = XCDR (hare);
tortoise = XCDR (tortoise);
if (EQ (hare, tortoise))
/* Reset Vwindow_persistent_parameters to Qnil. */
{
Vwindow_persistent_parameters = Qnil;
break;
}
}
for (tem = Vwindow_persistent_parameters; CONSP (tem);
tem = XCDR (tem))
{
pers = XCAR (tem);
/* Save values for persistent window parameters whose cdr
is either nil or t. */
if (CONSP (pers) && (NILP (XCDR (pers)) || EQ (XCDR (pers), Qt)))
{
par = Fassq (XCAR (pers), w->window_parameters);
if (NILP (par))
/* If the window has no value for the parameter,
make one. */
p->window_parameters = Fcons (Fcons (XCAR (pers), Qnil),
p->window_parameters);
else
/* If the window has a value for the parameter,
save it. */
p->window_parameters = Fcons (Fcons (XCAR (par),
XCDR (par)),
p->window_parameters);
}
}
}
if (!NILP (w->buffer))
{
/* Save w's value of point in the window configuration.
If w is the selected window, then get the value of point
from the buffer; pointm is garbage in the selected window. */
/* Save w's value of point in the window configuration. If w
is the selected window, then get the value of point from
the buffer; pointm is garbage in the selected window. */
if (EQ (window, selected_window))
{
p->pointm = Fmake_marker ();
@ -6433,6 +6503,8 @@ syms_of_window (void)
DEFSYM (Qabove, "above");
DEFSYM (Qbelow, "below");
DEFSYM (Qauto_buffer_name, "auto-buffer-name");
DEFSYM (Qclone_of, "clone-of");
DEFSYM (Qstate, "state");
staticpro (&Vwindow_list);
@ -6542,6 +6614,31 @@ retrieved via the function `window-combination-limit' and altered by the
function `set-window-combination-limit'. */);
Vwindow_combination_limit = Qnil;
DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters,
doc: /* Alist of persistent window parameters.
Parameters in this list are saved by `current-window-configuration' and
`window-state-get' and subsequently restored to their previous values by
`set-window-configuration' and `window-state-put'.
The car of each entry of this alist is the symbol specifying the
parameter. The cdr is one of the following:
The symbol `state' means the parameter is saved by `window-state-get'
provided its IGNORE argument is nil. `current-window-configuration'
does not save this parameter.
nil means the parameter is saved by `current-window-configuration' and,
provided its IGNORE argument is nil, by `window-state-get'.
t means the parameter is saved unconditionally by both
`current-window-configuration' and `window-state-get'. Parameters
without read syntax (like windows or frames) should not use that.
Parameters not saved by `current-window-configuration' or
`window-state-get' are left alone by `set-window-configuration'
respectively are not installed by `window-state-put'. */);
Vwindow_persistent_parameters = list1 (Fcons (Qclone_of, Qstate));
defsubr (&Sselected_window);
defsubr (&Sminibuffer_window);
defsubr (&Swindow_minibuffer_p);