emacs-diffs
[Top][All Lists]
Advanced

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

feature/long-lines-improvements 5e296283f5: Add locked narrowing around


From: Gregory Heytings
Subject: feature/long-lines-improvements 5e296283f5: Add locked narrowing around pre- and post-command-hook
Date: Sun, 31 Jul 2022 16:43:13 -0400 (EDT)

branch: feature/long-lines-improvements
commit 5e296283f57b21e962e6e6860e448905f99f281e
Author: Gregory Heytings <gregory@heytings.org>
Commit: Gregory Heytings <gregory@heytings.org>

    Add locked narrowing around pre- and post-command-hook
    
    * src/keyboard.c (safe_run_hooks_maybe_narrowed): New function.
    (command_loop_1): Use it for 'pre-command-hook' and 'post-command-hook'.
    (syms_of_keyboard): Update docstrings of 'pre-command-hook' and
    'post-command-hook'.
    
    * src/lisp.h: Prototype of the new function.
---
 src/keyboard.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++---------
 src/lisp.h     |  1 +
 2 files changed, 49 insertions(+), 9 deletions(-)

diff --git a/src/keyboard.c b/src/keyboard.c
index 2863058d63..094119340e 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1295,7 +1295,8 @@ command_loop_1 (void)
       /* Note that the value cell will never directly contain nil
         if the symbol is a local variable.  */
       if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks))
-       safe_run_hooks (Qpost_command_hook);
+       safe_run_hooks_maybe_narrowed (Qpost_command_hook,
+                                      XWINDOW (selected_window));
 
       /* If displaying a message, resize the echo area window to fit
         that message's size exactly.  */
@@ -1461,7 +1462,9 @@ command_loop_1 (void)
       }
       Vthis_command = cmd;
       Vreal_this_command = cmd;
-      safe_run_hooks (Qpre_command_hook);
+
+      safe_run_hooks_maybe_narrowed (Qpre_command_hook,
+                                    XWINDOW (selected_window));
 
       already_adjusted = 0;
 
@@ -1513,7 +1516,8 @@ command_loop_1 (void)
           }
       kset_last_prefix_arg (current_kboard, Vcurrent_prefix_arg);
 
-      safe_run_hooks (Qpost_command_hook);
+      safe_run_hooks_maybe_narrowed (Qpost_command_hook,
+                                    XWINDOW (selected_window));
 
       /* If displaying a message, resize the echo area window to fit
         that message's size exactly.  Do this only if the echo area
@@ -1895,6 +1899,25 @@ safe_run_hooks (Lisp_Object hook)
   unbind_to (count, Qnil);
 }
 
+void
+safe_run_hooks_maybe_narrowed (Lisp_Object hook, struct window *w)
+{
+  specpdl_ref count = SPECPDL_INDEX ();
+
+  specbind (Qinhibit_quit, Qt);
+
+  if (current_buffer->long_line_optimizations_p)
+    {
+      ptrdiff_t begv = get_narrowed_begv (w, PT);
+      ptrdiff_t zv = get_narrowed_zv (w, PT);
+      if (!begv) begv = BEGV;
+      Fnarrow_to_region (make_fixnum (begv), make_fixnum (zv), Qt);
+    }
+
+  run_hook_with_args (2, ((Lisp_Object []) {hook, hook}), 
safe_run_hook_funcall);
+  unbind_to (count, Qnil);
+}
+
 
 /* Nonzero means polling for input is temporarily suppressed.  */
 
@@ -12622,23 +12645,39 @@ Buffer modification stores t in this variable.  */);
 
   DEFVAR_LISP ("pre-command-hook", Vpre_command_hook,
               doc: /* Normal hook run before each command is executed.
-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.
+
+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, and the
+narrowing is locked (see `narrow-to-region'), so that these hook
+functions cannot use `widen' to gain access to other portions of
+buffer text.
 
 See also `post-command-hook'.  */);
   Vpre_command_hook = Qnil;
 
   DEFVAR_LISP ("post-command-hook", Vpost_command_hook,
               doc: /* Normal hook run after each command is executed.
-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.
+
+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.
 
 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, and the
+narrowing is locked (see `narrow-to-region'), so that these hook
+functions cannot use `widen' to gain access to other portions of
+buffer text.
+
 See also `pre-command-hook'.  */);
   Vpost_command_hook = Qnil;
 
diff --git a/src/lisp.h b/src/lisp.h
index 8fcc9b6e75..7136bb3dc1 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4829,6 +4829,7 @@ extern bool detect_input_pending (void);
 extern bool detect_input_pending_ignore_squeezables (void);
 extern bool detect_input_pending_run_timers (bool);
 extern void safe_run_hooks (Lisp_Object);
+extern void safe_run_hooks_maybe_narrowed (Lisp_Object, struct window *);
 extern void cmd_error_internal (Lisp_Object, const char *);
 extern Lisp_Object command_loop_2 (Lisp_Object);
 extern Lisp_Object read_menu_command (void);



reply via email to

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