emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

scratch/fix-locked-narrowing 79ce185ad1 6/7: Update the documentation ab


From: Gregory Heytings
Subject: scratch/fix-locked-narrowing 79ce185ad1 6/7: Update the documentation about labeled (locked) narrowing
Date: Wed, 8 Feb 2023 20:49:37 -0500 (EST)

branch: scratch/fix-locked-narrowing
commit 79ce185ad1373845781646812638d4872b8aee69
Author: Gregory Heytings <gregory@heytings.org>
Commit: Gregory Heytings <gregory@heytings.org>

    Update the documentation about labeled (locked) narrowing
    
    * src/xdisp.c (syms_of_xdisp) <fontification-functions>: Update
    docstring.
    
    * src/keyboard.c (syms_of_keyboard) <pre-command-hook>:
    (syms_of_keyboard) <post-command-hook>: Update docstring.
    
    * src/editfns.c:
    (narrowing_locks): Explain why an alist is used instead of a
    buffer-local variable.
    (reset_outermost_narrowings): Point to recipes that demonstrate
    why it is necessary to restore the user narrowing bounds when
    redisplay starts.
    (Fwiden): Update docstring.
    (Fnarrow_to_region): Update docstring.
    (Finternal__lock_narrowing): Update docstring.
    (Finternal__unlock_narrowing): Update docstring.
    (Fsave_restriction): Update docstring.
    
    * src/buffer.c (syms_of_buffer)
    <long-line-optimizations-region-size>: Update docstring.
    (syms_of_buffer) <long-line-optimizations-bol-search-limit>:
    Update docstring.
    
    * lisp/subr.el (with-narrowing): Update docstring.
    (without-narrowing): Update docstring.
    
    * etc/NEWS: Mention the 'long-line-optimizations-region-size' and
    'long-line-optimizations-bol-search-limit' options.
    Announce the 'with-narrowing' and 'without-narrowing' forms.
    
    * doc/lispref/positions.texi (Narrowing): Update the documentation
    of 'narrow-to-region', 'widen' and 'save-restriction'.  Document
    the 'with-narrowing' and 'without-narrowing' special forms.
    
    * doc/lispref/display.texi (Auto Faces): Update the documentation.
    
    * doc/lispref/commands.texi (Command Overview): Document the fact
    that the buffer is narrowed around 'pre-command-hook' and
    'post-command-hook' when the buffer text includes very long lines.
---
 doc/lispref/commands.texi  |  6 ++++
 doc/lispref/display.texi   | 10 +++---
 doc/lispref/positions.texi | 82 +++++++++++++++++++++++++++++++++++++++-------
 etc/NEWS                   | 16 +++++++--
 lisp/subr.el               | 14 +++++---
 src/buffer.c               | 35 ++++++++++----------
 src/editfns.c              | 74 ++++++++++++++++++-----------------------
 src/keyboard.c             | 24 ++++++--------
 src/xdisp.c                | 11 +++----
 9 files changed, 170 insertions(+), 102 deletions(-)

diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi
index dc78adc452..be34027d21 100644
--- a/doc/lispref/commands.texi
+++ b/doc/lispref/commands.texi
@@ -99,6 +99,12 @@ is removed from the hook.
 emacs, The GNU Emacs Manual}) runs these two hooks just as a keyboard
 command does.
 
+  Note that, when the buffer text includes very long lines, these two
+hooks are called as if they were in a @code{with-narrowing} form (see
+@ref{Narrowing}), with a
+@code{long-line-optimizations-in-command-hooks} label and with the
+buffer narrowed to a portion around point.
+
 @node Defining Commands
 @section Defining Commands
 @cindex defining commands
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index c5374e1481..1b7ef00663 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -3501,11 +3501,11 @@ function finishes are the ones that really matter.
 For efficiency, we recommend writing these functions so that they
 usually assign faces to around 400 to 600 characters at each call.
 
-When the buffer text includes very long lines, these functions are
-called with the buffer narrowed to a relatively small region around
-@var{pos}, and with narrowing locked, so the functions cannot use
-@code{widen} to gain access to the rest of the buffer.
-@xref{Narrowing}.
+Note that, when the buffer text includes very long lines, these
+functions are called as if they were in a @code{with-narrowing} form
+(see @ref{Narrowing}), with a
+@code{long-line-optimizations-in-fontification-functions} label and
+with the buffer narrowed to a portion around @var{pos}.
 @end defvar
 
 @node Basic Faces
diff --git a/doc/lispref/positions.texi b/doc/lispref/positions.texi
index f382443624..e7d5c610d6 100644
--- a/doc/lispref/positions.texi
+++ b/doc/lispref/positions.texi
@@ -1037,11 +1037,13 @@ positions.
 In an interactive call, @var{start} and @var{end} are set to the bounds
 of the current region (point and the mark, with the smallest first).
 
-Note that, in rare circumstances, Emacs may decide to leave, for
-performance reasons, the accessible portion of the buffer unchanged
-after a call to @code{narrow-to-region}.  This can happen when a Lisp
-program is called via low-level hooks, such as
-@code{jit-lock-functions}, @code{post-command-hook}, etc.
+However, when the narrowing has been set by @code{with-narrowing} with
+a label argument (see below), @code{narrow-to-region} can be used only
+within the limits of that narrowing.  If @var{start} or @var{end} are
+outside these limits, the corresponding limit set by
+@code{with-narrowing} is used instead.  To gain access to other
+portions of the buffer, use @code{without-narrowing} with the same
+label.
 @end deffn
 
 @deffn Command narrow-to-page &optional move-count
@@ -1065,13 +1067,13 @@ It is equivalent to the following expression:
 @example
 (narrow-to-region 1 (1+ (buffer-size)))
 @end example
-@end deffn
 
-Note that, in rare circumstances, Emacs may decide to leave, for
-performance reasons, the accessible portion of the buffer unchanged
-after a call to @code{widen}.  This can happen when a Lisp program is
-called via low-level hooks, such as @code{jit-lock-functions},
-@code{post-command-hook}, etc.
+However, when a narrowing has been set by @code{with-narrowing} with a
+label argument (see below), the limits set by @code{with-narrowing}
+are restored, instead of canceling the narrowing.  To gain access to
+other portions of the buffer, use @code{without-narrowing} with the
+same label.
+@end deffn
 
 @defun buffer-narrowed-p
 This function returns non-@code{nil} if the buffer is narrowed, and
@@ -1086,6 +1088,9 @@ in effect.  The state of narrowing is restored even in 
the event of an
 abnormal exit via @code{throw} or error (@pxref{Nonlocal Exits}).
 Therefore, this construct is a clean way to narrow a buffer temporarily.
 
+This construct also saves and restores the narrowings that were set by
+@code{with-narrowing} with a label argument (see below).
+
 The value returned by @code{save-restriction} is that returned by the
 last form in @var{body}, or @code{nil} if no body forms were given.
 
@@ -1135,3 +1140,58 @@ This is the contents of foo@point{}
 @end group
 @end example
 @end defspec
+
+@defspec with-narrowing start end [:label label] body
+This special form saves the current bounds of the accessible portion
+of the buffer, sets the accessible portion to start at @var{start} and
+end at @var{end}, evaluates the @var{body} forms, and restores the
+saved bounds.  In that case it is equivalent to
+
+@example
+(save-restriction
+  (narrow-to-region start end)
+  body)
+@end example
+
+When the optional @var{label} symbol argument is present however, the
+narrowing is labeled.  A labeled narrowing differs from a non-labeled
+one in several ways:
+
+@itemize @bullet
+@item
+During the evaluation of the @var{body} form, @code{narrow-to-region}
+and @code{widen} can be used only within the @var{start} and @var{end}
+limits.
+
+@item
+To lift the restriction introduced by @code{with-narrowing} and gain
+access to other portions of the buffer, use @code{without-narrowing}
+with the same @var{label} argument.  (Another way to gain access to
+other portions of the buffer is to use an indirect buffer
+(@pxref{Indirect Buffers}).)
+
+@item
+Labeled narrowings can be nested.
+
+@item
+Labeled narrowings can only be used in Lisp programs: they are never
+visible on display, and never interfere with narrowings set by the
+user.
+@end itemize
+@end defspec
+
+@defspec without-narrowing [:label label] body
+This special form saves the current bounds of the accessible portion
+of the buffer, widens the buffer, evaluates the @var{body} forms, and
+restores the saved bounds.  In that case it is equivalent to
+
+@example
+(save-restriction
+  (widen)
+  body)
+@end example
+
+When the optional @var{label} argument is present however, the
+narrowing set by @code{with-narrowing} with the same @var{label}
+argument are lifted.
+@end defspec
diff --git a/etc/NEWS b/etc/NEWS
index 2d15e39036..01e7f2cfb0 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -615,8 +615,12 @@ with 'C-x x t', or try disabling all known slow minor 
modes with
 and the major mode with 'M-x so-long-mode', or visit the file with
 'M-x find-file-literally' instead of the usual 'C-x C-f'.
 
-Note that the display optimizations in these cases may cause the
-buffer to be occasionally mis-fontified.
+In buffers in which these display optimizations are in effect, the
+'fontification-functions', 'pre-command-hook' and 'post-command-hook'
+hooks are executed on a narrowed portion of the buffer, whose size is
+controlled by the options 'long-line-optimizations-region-size' and
+'long-line-optimizations-bol-search-limit'.  This may, in particular,
+cause occasional mis-fontifications in these buffers.
 
 The new function 'long-line-optimizations-p' returns non-nil when
 these optimizations are in effect in the current buffer.
@@ -3814,6 +3818,14 @@ TIMEOUT is the idle time after which to deactivate the 
transient map.
 The default timeout value can be defined by the new variable
 'set-transient-map-timeout'.
 
++++
+** New forms 'with-narrowing' and 'without-narrowing'.
+These forms can be used as enhanced alternatives to the
+'save-restriction' form combined with, respectively,
+'narrow-to-region' and 'widen'.  They also accept an optional label
+argument, with which labeled narrowings can be created and lifted.
+See the "(elisp) Narrowing" node for details.
+
 ** Connection Local Variables
 
 +++
diff --git a/lisp/subr.el b/lisp/subr.el
index af3f1f1abd..7ed0cb02a7 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -3946,11 +3946,11 @@ See also `locate-user-emacs-file'.")
 
 The current restrictions, if any, are restored upon return.
 
-With the optional :locked TAG argument, inside BODY,
-`narrow-to-region' and `widen' can be used only within the START
-and END limits, unless the restrictions are unlocked by calling
-`narrowing-unlock' with TAG.  See `narrowing-lock' for a more
-detailed description.
+When the optional :label LABEL argument is present, in which
+LABEL is a symbol, inside BODY, `narrow-to-region' and `widen'
+can be used only within the START and END limits.  To gain access
+to other portions of the buffer, use `without-narrowing' with the
+same LABEL argument.
 
 \(fn START END [:label LABEL] BODY)"
   (if (eq (car rest) :label)
@@ -3971,6 +3971,10 @@ detailed description.
 
 The current restrictions, if any, are restored upon return.
 
+When the optional :label LABEL argument is present, the
+restrictions set by `with-narrowing' with the same LABEL argument
+are lifted.
+
 \(fn [:label LABEL] BODY)"
   (if (eq (car rest) :label)
       `(internal--without-narrowing (lambda () ,@(cddr rest))
diff --git a/src/buffer.c b/src/buffer.c
index 07723a7c6f..755061d0de 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -5918,18 +5918,18 @@ There is no reason to change that value except for 
debugging purposes.  */);
 
   DEFVAR_INT ("long-line-optimizations-region-size",
              long_line_optimizations_region_size,
-             doc: /* Region size for locked narrowing in buffers with long 
lines.
+             doc: /* Region size for narrowing in buffers with long lines.
 
-This variable has effect only in buffers which contain one or more
-lines whose length is above `long-line-threshold', which see.  For
-performance reasons, in such buffers, low-level hooks such as
-`fontification-functions' or `post-command-hook' are executed on a
-narrowed buffer, with a narrowing locked with `narrowing-lock'.  This
-variable specifies the size of the narrowed region around point.
+This variable has effect only in buffers in which
+`long-line-optimizations-p' is non-nil.  For performance reasons, in
+such buffers, the `fontification-functions', `pre-command-hook' and
+`post-command-hook' hooks are executed on a narrowed buffer around
+point, as if they were called in a `with-narrowing' form with a label.
+This variable specifies the size of the narrowed region around point.
 
 To disable that narrowing, set this variable to 0.
 
-See also `long-line-locked-narrowing-bol-search-limit'.
+See also `long-line-optimizations-bol-search-limit'.
 
 There is no reason to change that value except for debugging purposes.  */);
   long_line_optimizations_region_size = 500000;
@@ -5938,15 +5938,16 @@ There is no reason to change that value except for 
debugging purposes.  */);
              long_line_optimizations_bol_search_limit,
              doc: /* Limit for beginning of line search in buffers with long 
lines.
 
-This variable has effect only in buffers which contain one or more
-lines whose length is above `long-line-threshold', which see.  For
-performance reasons, in such buffers, low-level hooks such as
-`fontification-functions' or `post-command-hook' are executed on a
-narrowed buffer, with a narrowing locked with `narrowing-lock'.  The
-variable `long-line-locked-narrowing-region-size' specifies the size
-of the narrowed region around point.  This variable, which should be a
-small integer, specifies the number of characters by which that region
-can be extended backwards to make it start at the beginning of a line.
+This variable has effect only in buffers in which
+`long-line-optimizations-p' is non-nil.  For performance reasons, in
+such buffers, the `fontification-functions', `pre-command-hook' and
+`post-command-hook' hooks are executed on a narrowed buffer around
+point, as if they were called in a `with-narrowing' form with a label.
+The variable `long-line-optimizations-region-size' specifies the
+size of the narrowed region around point.  This variable, which should
+be a small integer, specifies the number of characters by which that
+region can be extended backwards to make it start at the beginning of
+a line.
 
 There is no reason to change that value except for debugging purposes.  */);
   long_line_optimizations_bol_search_limit = 128;
diff --git a/src/editfns.c b/src/editfns.c
index e1c5750280..64906671be 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -2659,7 +2659,11 @@ DEFUN ("delete-and-extract-region", 
Fdelete_and_extract_region,
    the (uninterned) Qoutermost_narrowing tag and records the narrowing
    bounds that were set by the user and that are visible on display.
    This alist is used internally by narrow-to-region, widen,
-   narrowing-lock, narrowing-unlock and save-restriction.  */
+   internal--lock-narrowing, internal--unlock-narrowing and
+   save-restriction.  For efficiency reasons, an alist is used instead
+   of a buffer-local variable: otherwise reset_outermost_narrowings,
+   which is called during each redisplay cycle, would have to loop
+   through all live buffers.  */
 static Lisp_Object narrowing_locks;
 
 /* Add BUF with its LOCKS in the narrowing_locks alist.  */
@@ -2763,7 +2767,10 @@ unwind_reset_outermost_narrowing (Lisp_Object buf)
    In particular, this function is called when redisplay starts, so
    that if a Lisp function executed during redisplay calls (redisplay)
    while a locked narrowing is in effect, the locked narrowing will
-   not be visible on display.  */
+   not be visible on display.
+   See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=57207#140 and
+   https://debbugs.gnu.org/cgi/bugreport.cgi?bug=57207#254 for example
+   recipes that demonstrate why this is necessary.  */
 void
 reset_outermost_narrowings (void)
 {
@@ -2829,10 +2836,12 @@ narrow_to_region_locked (Lisp_Object begv, Lisp_Object 
zv, Lisp_Object tag)
 DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
        doc: /* Remove restrictions (narrowing) from current buffer.
 
-This allows the buffer's full text to be seen and edited, unless
-restrictions have been locked with `narrowing-lock', which see, in
-which case the narrowing that was current when `narrowing-lock' was
-called is restored.  */)
+This allows the buffer's full text to be seen and edited.
+
+However, when restrictions have been set by `with-narrowing' with a
+label, `widen' restores the narrowing limits set by `with-narrowing'.
+To gain access to other portions of the buffer, use
+`without-narrowing' with the same label.  */)
   (void)
 {
   Fset (Qoutermost_narrowing, Qnil);
@@ -2879,11 +2888,12 @@ When calling from Lisp, pass two arguments START and 
END:
 positions (integers or markers) bounding the text that should
 remain visible.
 
-When restrictions have been locked with `narrowing-lock', which see,
-`narrow-to-region' can be used only within the limits of the
-restrictions that were current when `narrowing-lock' was called.  If
-the START or END arguments are outside these limits, the corresponding
-limit of the locked restriction is used instead of the argument.  */)
+However, when restrictions have been set by `with-narrowing' with a
+label, `narrow-to-region' can be used only within the limits of these
+restrictions.  If the START or END arguments are outside these limits,
+the corresponding limit set by `with-narrowing' is used instead of the
+argument.  To gain access to other portions of the buffer, use
+`without-narrowing' with the same label.  */)
   (Lisp_Object start, Lisp_Object end)
 {
   EMACS_INT s = fix_position (start), e = fix_position (end);
@@ -2912,7 +2922,7 @@ limit of the locked restriction is used instead of the 
argument.  */)
 
   /* Record the accessible range of the buffer when narrow-to-region
      is called, that is, before applying the narrowing.  It is used
-     only by narrowing-lock.  */
+     only by internal--lock-narrowing.  */
   Fset (Qoutermost_narrowing, list3 (Qoutermost_narrowing,
                                     Fpoint_min_marker (),
                                     Fpoint_max_marker ()));
@@ -2934,30 +2944,16 @@ limit of the locked restriction is used instead of the 
argument.  */)
 
 DEFUN ("internal--lock-narrowing", Finternal__lock_narrowing,
        Sinternal__lock_narrowing, 1, 1, 0,
-       doc: /* Lock the current narrowing with TAG.
-
-When restrictions are locked, `narrow-to-region' and `widen' can be
-used only within the limits of the restrictions that were current when
-`narrowing-lock' was called, unless the lock is removed by calling
-`narrowing-unlock' with TAG.
-
-Locking restrictions should be used sparingly, after carefully
-considering the potential adverse effects on the code that will be
-executed within locked restrictions.  It is typically meant to be used
-around portions of code that would become too slow, and make Emacs
-unresponsive, if they were executed in a large buffer.  For example,
-restrictions are locked by Emacs around low-level hooks such as
-`fontification-functions' or `post-command-hook'.
-
-Locked restrictions are never visible on display, and can therefore
-not be used as a stronger variant of normal restrictions.  */)
+       doc: /* Lock the current narrowing with LABEL.
+
+This is an internal function used by `with-narrowing'.  */)
   (Lisp_Object tag)
 {
   Lisp_Object buf = Fcurrent_buffer ();
   Lisp_Object outermost_narrowing
     = buffer_local_value (Qoutermost_narrowing, buf);
-  /* If narrowing-lock is called without being preceded by
-     narrow-to-region, do nothing.  */
+  /* If internal--lock-narrowing is ever called without being preceded
+     by narrow-to-region, do nothing.  */
   if (NILP (outermost_narrowing))
     return Qnil;
   if (NILP (narrowing_lock_peek_tag (buf)))
@@ -2970,15 +2966,9 @@ not be used as a stronger variant of normal 
restrictions.  */)
 
 DEFUN ("internal--unlock-narrowing", Finternal__unlock_narrowing,
        Sinternal__unlock_narrowing, 1, 1, 0,
-       doc: /* Unlock a narrowing locked with (narrowing-lock TAG).
-
-Unlocking restrictions locked with `narrowing-lock' should be used
-sparingly, after carefully considering the reasons why restrictions
-were locked.  Restrictions are typically locked around portions of
-code that would become too slow, and make Emacs unresponsive, if they
-were executed in a large buffer.  For example, restrictions are locked
-by Emacs around low-level hooks such as `fontification-functions' or
-`post-command-hook'.  */)
+       doc: /* Unlock a narrowing locked with LABEL.
+
+This is an internal function used by `without-narrowing'.  */)
   (Lisp_Object tag)
 {
   Lisp_Object buf = Fcurrent_buffer ();
@@ -3085,8 +3075,8 @@ DEFUN ("save-restriction", Fsave_restriction, 
Ssave_restriction, 0, UNEVALLED, 0
 The buffer's restrictions make parts of the beginning and end invisible.
 \(They are set up with `narrow-to-region' and eliminated with `widen'.)
 This special form, `save-restriction', saves the current buffer's
-restrictions, as well as their locks if they have been locked with
-`narrowing-lock', when it is entered, and restores them when it is exited.
+restrictions, including those that were set by `with-narrowing' with a
+label argument, when it is entered, and restores them when it is exited.
 So any `narrow-to-region' within BODY lasts only until the end of the form.
 The old restrictions settings are restored even in case of abnormal exit
 \(throw or error).
diff --git a/src/keyboard.c b/src/keyboard.c
index 4417aa97d2..1d0b907bd8 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -12731,13 +12731,11 @@ If an unhandled error happens in running this hook, 
the function in
 which the error occurred is unconditionally removed, since otherwise
 the error might happen repeatedly and make Emacs nonfunctional.
 
-Note that, when the current buffer contains one or more lines whose
-length is above `long-line-threshold', these hook functions are called
-with the buffer narrowed to a small portion around point (whose size
-is specified by `long-line-locked-narrowing-region-size'), and the
-narrowing is locked (see `narrowing-lock'), so that these hook
-functions cannot use `widen' to gain access to other portions of
-buffer text.
+Note that, when `long-line-optimizations-p' is non-nil in the buffer,
+these functions are called as if they were in a `with-narrowing' form,
+with a `long-line-optimizations-in-command-hooks' label and with the
+buffer narrowed to a portion around point whose size is specified by
+`long-line-optimizations-region-size'.
 
 See also `post-command-hook'.  */);
   Vpre_command_hook = Qnil;
@@ -12753,13 +12751,11 @@ It is a bad idea to use this hook for expensive 
processing.  If
 unavoidable, wrap your code in `(while-no-input (redisplay) CODE)' to
 avoid making Emacs unresponsive while the user types.
 
-Note that, when the current buffer contains one or more lines whose
-length is above `long-line-threshold', these hook functions are called
-with the buffer narrowed to a small portion around point (whose size
-is specified by `long-line-locked-narrowing-region-size'), and the
-narrowing is locked (see `narrowing-lock'), so that these hook
-functions cannot use `widen' to gain access to other portions of
-buffer text.
+Note that, when `long-line-optimizations-p' is non-nil in the buffer,
+these functions are called as if they were in a `with-narrowing' form,
+with a `long-line-optimizations-in-command-hooks' label and with the
+buffer narrowed to a portion around point whose size is specified by
+`long-line-optimizations-region-size'.
 
 See also `pre-command-hook'.  */);
   Vpost_command_hook = Qnil;
diff --git a/src/xdisp.c b/src/xdisp.c
index 8034b20d5f..1450b869d2 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -36777,12 +36777,11 @@ Each function is called with one argument POS.  
Functions must
 fontify a region starting at POS in the current buffer, and give
 fontified regions the property `fontified' with a non-nil value.
 
-Note that, when the buffer contains one or more lines whose length is
-above `long-line-threshold', these functions are called with the
-buffer narrowed to a small portion around POS (whose size is specified
-by `long-line-locked-narrowing-region-size'), and the narrowing is
-locked (see `narrowing-lock'), so that these functions cannot use
-`widen' to gain access to other portions of buffer text.  */);
+Note that, when `long-line-optimizations-p' is non-nil in the buffer,
+these functions are called as if they were in a `with-narrowing' form,
+with a `long-line-optimizations-in-fontification-functions' label and
+with the buffer narrowed to a portion around POS whose size is
+specified by `long-line-optimizations-region-size'.  */);
   Vfontification_functions = Qnil;
   Fmake_variable_buffer_local (Qfontification_functions);
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]