`save-excursion' does not save&restore the mark any more

* src/editfns.c (save_excursion_save): Don't save the mark.
(save_excursion_restore): Don't restore the mark.
(Fsave_excursion): Fix docstring accordingly.

* doc/lispintro/emacs-lisp-intro.texi:
* doc/lispref/positions.texi (Excursions, Narrowing): `save-excursion' does
not save&restore the mark any more.
This commit is contained in:
Stefan Monnier 2015-03-25 09:47:12 -04:00
parent 76040ddd8a
commit 599ca626d7
7 changed files with 55 additions and 81 deletions

View file

@ -1,3 +1,7 @@
2015-03-25 Stefan Monnier <monnier@iro.umontreal.ca>
* emacs-lisp-intro.texi: `save-excursion' doesn't save&restore the mark.
2014-12-31 Paul Eggert <eggert@cs.ucla.edu>
Less 'make' chatter for Emacs doc

View file

@ -352,7 +352,7 @@ How To Write Function Definitions
* if:: What if?
* else:: If--then--else expressions.
* Truth & Falsehood:: What Lisp considers false and true.
* save-excursion:: Keeping track of point, mark, and buffer.
* save-excursion:: Keeping track of point and buffer.
* Review::
* defun Exercises::
@ -2966,7 +2966,7 @@ symbol refers to it.)
* if:: What if?
* else:: If--then--else expressions.
* Truth & Falsehood:: What Lisp considers false and true.
* save-excursion:: Keeping track of point, mark, and buffer.
* save-excursion:: Keeping track of point and buffer.
* Review::
* defun Exercises::
@end menu
@ -4159,11 +4159,11 @@ The @code{save-excursion} function is the third and final special form
that we will discuss in this chapter.
In Emacs Lisp programs used for editing, the @code{save-excursion}
function is very common. It saves the location of point and mark,
executes the body of the function, and then restores point and mark to
their previous positions if their locations were changed. Its primary
function is very common. It saves the location of point,
executes the body of the function, and then restores point to
its previous position if its location was changed. Its primary
purpose is to keep the user from being surprised and disturbed by
unexpected movement of point or mark.
unexpected movement of point.
@menu
* Point and mark:: A review of various locations.
@ -4201,7 +4201,7 @@ region}. Numerous commands work on the region, including
@code{print-region}.
The @code{save-excursion} special form saves the locations of point and
mark and restores those positions after the code within the body of the
restores this position after the code within the body of the
special form is evaluated by the Lisp interpreter. Thus, if point were
in the beginning of a piece of text and some code moved point to the end
of the buffer, the @code{save-excursion} would put point back to where
@ -4212,16 +4212,16 @@ In Emacs, a function frequently moves point as part of its internal
workings even though a user would not expect this. For example,
@code{count-lines-region} moves point. To prevent the user from being
bothered by jumps that are both unexpected and (from the user's point of
view) unnecessary, @code{save-excursion} is often used to keep point and
mark in the location expected by the user. The use of
view) unnecessary, @code{save-excursion} is often used to keep point in
the location expected by the user. The use of
@code{save-excursion} is good housekeeping.
To make sure the house stays clean, @code{save-excursion} restores the
values of point and mark even if something goes wrong in the code inside
value of point even if something goes wrong in the code inside
of it (or, to be more precise and to use the proper jargon, ``in case of
abnormal exit''). This feature is very helpful.
In addition to recording the values of point and mark,
In addition to recording the value of point,
@code{save-excursion} keeps track of the current buffer, and restores
it, too. This means you can write code that will change the buffer and
have @code{save-excursion} switch you back to the original buffer.
@ -4386,9 +4386,9 @@ For example,
@end smallexample
@item save-excursion
Record the values of point and mark and the current buffer before
evaluating the body of this special form. Restore the values of point
and mark and buffer afterward.
Record the values of point and the current buffer before
evaluating the body of this special form. Restore the value of point and
buffer afterward.
@need 1250
For example,
@ -5201,8 +5201,8 @@ of the two-element list, @code{(oldbuf (current-buffer))}.
The body of the @code{let} expression in @code{append-to-buffer}
consists of a @code{save-excursion} expression.
The @code{save-excursion} function saves the locations of point and
mark, and restores them to those positions after the expressions in the
The @code{save-excursion} function saves the location of point, and restores it
to that position after the expressions in the
body of the @code{save-excursion} complete execution. In addition,
@code{save-excursion} keeps track of the original buffer, and
restores it. This is how @code{save-excursion} is used in
@ -5390,7 +5390,7 @@ Conventionally bound to @kbd{M-.} (that's a period following the
@key{META} key).
@item save-excursion
Save the location of point and mark and restore their values after the
Save the location of point and restore its value after the
arguments to @code{save-excursion} have been evaluated. Also, remember
the current buffer and return to it.
@ -5896,7 +5896,7 @@ the value of point, which will be at the end of the inserted text, is
recorded in the variable @code{newmark}.
After the body of the outer @code{save-excursion} is evaluated, point
and mark are relocated to their original places.
is relocated to its original place.
However, it is convenient to locate a mark at the end of the newly
inserted text and locate point at its beginning. The @code{newmark}
@ -6685,8 +6685,8 @@ restored just before the completion of the function by the
@code{save-restriction} special form.
The call to @code{widen} is followed by @code{save-excursion}, which
saves the location of the cursor (i.e., of point) and of the mark, and
restores them after the code in the body of the @code{save-excursion}
saves the location of the cursor (i.e., of point), and
restores it after the code in the body of the @code{save-excursion}
uses the @code{beginning-of-line} function to move point.
(Note that the @code{(widen)} expression comes between the
@ -6757,8 +6757,8 @@ it, and @code{count-lines} counts only the lines @emph{before} the
current line.
After @code{count-lines} has done its job, and the message has been
printed in the echo area, the @code{save-excursion} restores point and
mark to their original positions; and @code{save-restriction} restores
printed in the echo area, the @code{save-excursion} restores point to
its original position; and @code{save-restriction} restores
the original narrowing, if any.
@node narrow Exercise

View file

@ -1,3 +1,8 @@
2015-03-25 Stefan Monnier <monnier@iro.umontreal.ca>
* positions.texi (Excursions, Narrowing): `save-excursion' does not
save&restore the mark any more.
2015-03-24 Paul Eggert <eggert@cs.ucla.edu>
* numbers.texi (Float Basics): Improve ldexp documentation.

View file

@ -825,8 +825,8 @@ is zero or less.
It is often useful to move point ``temporarily'' within a localized
portion of the program. This is called an @dfn{excursion}, and it is
done with the @code{save-excursion} special form. This construct
remembers the initial identity of the current buffer, and its values
of point and the mark, and restores them after the excursion
remembers the initial identity of the current buffer, and its value
of point, and restores them after the excursion
completes. It is the standard way to move point within one part of a
program and avoid affecting the rest of the program, and is used
thousands of times in the Lisp sources of Emacs.
@ -841,18 +841,18 @@ Configurations} and in @ref{Frame Configurations}. @c frameset?
@cindex mark excursion
@cindex point excursion
This special form saves the identity of the current buffer and the
values of point and the mark in it, evaluates @var{body}, and finally
restores the buffer and its saved values of point and the mark. All
three saved values are restored even in case of an abnormal exit via
value of point in it, evaluates @var{body}, and finally
restores the buffer and its saved value of point. both saved values are
restored even in case of an abnormal exit via
@code{throw} or error (@pxref{Nonlocal Exits}).
The value returned by @code{save-excursion} is the result of the last
form in @var{body}, or @code{nil} if no body forms were given.
@end defspec
Because @code{save-excursion} only saves point and mark for the
Because @code{save-excursion} only saves point for the
buffer that was current at the start of the excursion, any changes
made to point and/or mark in other buffers, during the excursion, will
made to point in other buffers, during the excursion, will
remain in effect afterward. This frequently leads to unintended
consequences, so the byte compiler warns if you call @code{set-buffer}
during an excursion:
@ -888,11 +888,6 @@ type @code{nil}. @xref{Marker Insertion Types}. Therefore, when the
saved point value is restored, it normally comes before the inserted
text.
Although @code{save-excursion} saves the location of the mark, it does
not prevent functions which modify the buffer from setting
@code{deactivate-mark}, and thus causing the deactivation of the mark
after the command finishes. @xref{The Mark}.
@node Narrowing
@section Narrowing
@cindex narrowing
@ -980,7 +975,7 @@ restores the restrictions on the original buffer (the buffer whose
restrictions it saved from), but it does not restore the identity of the
current buffer.
@code{save-restriction} does @emph{not} restore point and the mark; use
@code{save-restriction} does @emph{not} restore point; use
@code{save-excursion} for that. If you use both @code{save-restriction}
and @code{save-excursion} together, @code{save-excursion} should come
first (on the outside). Otherwise, the old point value would be

View file

@ -617,6 +617,8 @@ a typographically-correct documents.
* Incompatible Lisp Changes in Emacs 25.1
** `save-excursion' does not save&restore the mark any more.
** read-buffer-function can now be called with a 4th argument (`predicate').
** completion-table-dynamic stays in the minibuffer.

View file

@ -1,3 +1,9 @@
2015-03-25 Stefan Monnier <monnier@iro.umontreal.ca>
* editfns.c (save_excursion_save): Don't save the mark.
(save_excursion_restore): Don't restore the mark.
(Fsave_excursion): Fix docstring accordingly.
2015-03-24 Paul Eggert <eggert@cs.ucla.edu>
Fix minor ldexp issues

View file

@ -849,14 +849,11 @@ save_excursion_save (void)
{
return make_save_obj_obj_obj_obj
(Fpoint_marker (),
/* Do not copy the mark if it points to nowhere. */
(XMARKER (BVAR (current_buffer, mark))->buffer
? Fcopy_marker (BVAR (current_buffer, mark), Qnil)
: Qnil),
Qnil,
/* Selected window if current buffer is shown in it, nil otherwise. */
(EQ (XWINDOW (selected_window)->contents, Fcurrent_buffer ())
? selected_window : Qnil),
BVAR (current_buffer, mark_active));
Qnil);
}
/* Restore saved buffer before leaving `save-excursion' special form. */
@ -864,8 +861,8 @@ save_excursion_save (void)
void
save_excursion_restore (Lisp_Object info)
{
Lisp_Object tem, tem1, omark, nmark;
struct gcpro gcpro1, gcpro2, gcpro3;
Lisp_Object tem, tem1;
struct gcpro gcpro1;
tem = Fmarker_buffer (XSAVE_OBJECT (info, 0));
/* If we're unwinding to top level, saved buffer may be deleted. This
@ -873,8 +870,7 @@ save_excursion_restore (Lisp_Object info)
if (NILP (tem))
goto out;
omark = nmark = Qnil;
GCPRO3 (info, omark, nmark);
GCPRO1 (info);
Fset_buffer (tem);
@ -883,34 +879,6 @@ save_excursion_restore (Lisp_Object info)
Fgoto_char (tem);
unchain_marker (XMARKER (tem));
/* Mark marker. */
tem = XSAVE_OBJECT (info, 1);
omark = Fmarker_position (BVAR (current_buffer, mark));
if (NILP (tem))
unchain_marker (XMARKER (BVAR (current_buffer, mark)));
else
{
Fset_marker (BVAR (current_buffer, mark), tem, Fcurrent_buffer ());
nmark = Fmarker_position (tem);
unchain_marker (XMARKER (tem));
}
/* Mark active. */
tem = XSAVE_OBJECT (info, 3);
tem1 = BVAR (current_buffer, mark_active);
bset_mark_active (current_buffer, tem);
/* If mark is active now, and either was not active
or was at a different place, run the activate hook. */
if (! NILP (tem))
{
if (! EQ (omark, nmark))
run_hook (intern ("activate-mark-hook"));
}
/* If mark has ceased to be active, run deactivate hook. */
else if (! NILP (tem1))
run_hook (intern ("deactivate-mark-hook"));
/* If buffer was visible in a window, and a different window was
selected, and the old selected window is still showing this
buffer, restore point in that window. */
@ -932,18 +900,12 @@ save_excursion_restore (Lisp_Object info)
}
DEFUN ("save-excursion", Fsave_excursion, Ssave_excursion, 0, UNEVALLED, 0,
doc: /* Save point, mark, and current buffer; execute BODY; restore those things.
doc: /* Save point, and current buffer; execute BODY; restore those things.
Executes BODY just like `progn'.
The values of point, mark and the current buffer are restored
The values of point and the current buffer are restored
even in case of abnormal exit (throw or error).
The state of activation of the mark is also restored.
This construct does not save `deactivate-mark', and therefore
functions that change the buffer will still cause deactivation
of the mark at the end of the command. To prevent that, bind
`deactivate-mark' with `let'.
If you only want to save the current buffer but not point nor mark,
If you only want to save the current buffer but not point,
then just use `save-current-buffer', or even `with-current-buffer'.
usage: (save-excursion &rest BODY) */)