[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
feature/fix-the-long-lines-display-bug 38b3780f6e: Actually fix the long
From: |
Gregory Heytings |
Subject: |
feature/fix-the-long-lines-display-bug 38b3780f6e: Actually fix the long lines display bug (bug#56393). |
Date: |
Tue, 5 Jul 2022 18:45:04 -0400 (EDT) |
branch: feature/fix-the-long-lines-display-bug
commit 38b3780f6e1bdcbb2a9a7dde76fa55da36e2774f
Author: Gregory Heytings <gregory@heytings.org>
Commit: Gregory Heytings <gregory@heytings.org>
Actually fix the long lines display bug (bug#56393).
* lisp/files.el (auto-narrow-mode): New minor mode.
(auto-narrow-pre-command-function, auto-narrow-post-command-function):
New auxiliary functions for the minor mode.
(auto-narrow-display-length, auto-narrow-widen-automatically): New
defcustoms for the minor mode.
(auto-narrow--widen-automatically, auto-narrow--isearch-widen-automatically,
auto-narrow--initialized): New internal variables for the minor mode.
* src/buffer.h (struct buffer): New internal variable for the minor mode.
(bset_auto_narrow__narrowing_state, BUFFER_AUTO_NARROWED_P): New
auxiliary functions.
* src/buffer.c (init_buffer_once, syms_of_buffer): New internal variable
for the minor mode. Update the docstring of mode-line-format.
* src/fileio.c (Finsert_file_contents): Detect whether the minor mode should
be entered when the buffer is displayed.
(syms_of_fileio): New defcustom for the minor mode.
* src/keyboard.c (syms_of_keyboard): New hook functions for the minor mode.
(command_loop_1): Execute the hook functions.
* src/xdisp.c (redisplay_window): Enter the minor mode when the buffer is
displayed.
(decode_mode_spec): Indicate when the minor mode is active
in the modeline. Indicate the buffer position relative to the whole buffer.
(set_vertical_scroll_bar): Indicate the buffer position relative to the
whole buffer.
(syms_of_xdisp): Two new symbols.
* lisp/isearch.el (isearch-widen-automatically): New defcustom.
(isearch-search): Use the new defcustom.
* lisp/bindings.el (mode-line-modes): Do not propertize the indication
in the modeline when the new minor mode is active.
* etc/NEWS: Announce the new minor mode, and remove the unobsoletion
indication for 'longlines-mode'.
* lisp/longlines.el: Reobsolete longlines-mode.
* doc/emacs/display.texi (Auto-Narrowing): New section, describing the new
minor mode.
(Display): Entry for the new section.
* doc/emacs/trouble.texi (Long Lines): Remove the section.
(Lossage): Remove the entry for the Long Lines section.
* doc/emacs/emacs.texi (Top): Remove the entry for the Long Lines section.
---
doc/emacs/display.texi | 25 ++++++++
doc/emacs/emacs.texi | 1 -
doc/emacs/trouble.texi | 59 -------------------
etc/NEWS | 15 ++++-
lisp/bindings.el | 12 ++--
lisp/files.el | 97 +++++++++++++++++++++++++++++++
lisp/isearch.el | 32 ++++++----
lisp/{ => obsolete}/longlines.el | 1 +
src/buffer.c | 9 ++-
src/buffer.h | 14 +++++
src/fileio.c | 21 +++++++
src/keyboard.c | 28 +++++++++
src/xdisp.c | 122 +++++++++++++++++++++++++++++----------
13 files changed, 328 insertions(+), 108 deletions(-)
diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi
index cadac7e453..9fe9533e88 100644
--- a/doc/emacs/display.texi
+++ b/doc/emacs/display.texi
@@ -19,6 +19,8 @@ the text is displayed.
* Horizontal Scrolling:: Moving text left and right in a window.
* Narrowing:: Restricting display and editing to a portion
of the buffer.
+* Auto-Narrowing:: Automatically restrict display to a portion of
+ the buffer.
* View Mode:: Viewing read-only buffers.
* Follow Mode:: Follow mode lets two windows scroll as one.
* Faces:: How to change the display style using faces.
@@ -467,6 +469,29 @@ this command asks for confirmation and gives you the
option of enabling it;
if you enable the command, confirmation will no longer be required for
it. @xref{Disabling}.
+@node Auto-Narrowing
+@findex auto-narrow-mode
+@vindex auto-narrow-long-line-threshold
+@vindex auto-narrow-display-length
+@vindex auto-narrow-widen-automatically
+
+ When a file with extremely long lines is opened or inserted in a
+buffer, Emacs automatically enters auto-narrow mode, and the word
+@samp{Auto-Narrow} appears in the mode line. This means that Emacs
+restricts display, but not editing, to a portion of the buffer above
+and below point. All editing commands, including narrowing commands,
+remain available, and they act on the whole buffer. For example,
+@kbd{M->} moves point to the end of the buffer, and not, as would
+happen with ordinary narrowing, to the end of the portion of the
+buffer to which display is currently restricted.
+
+ The behavior of auto-narrow mode is controlled by three variables:
+@code{auto-narrow-long-line-threshold} is the line length above which
+auto-narrow move is entered, @code{auto-narrow-display-length} is the
+number of characters to which display is restricted, and
+@code{auto-narrow-widen-automatically} is a list of commands for which
+display is widened before they are executed.
+
@node View Mode
@section View Mode
@cindex View mode
diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi
index 5e72699bbe..b43c966f87 100644
--- a/doc/emacs/emacs.texi
+++ b/doc/emacs/emacs.texi
@@ -1190,7 +1190,6 @@ Dealing with Emacs Trouble
* Crashing:: What Emacs does when it crashes.
* After a Crash:: Recovering editing in an Emacs session that crashed.
* Emergency Escape:: What to do if Emacs stops responding.
-* Long Lines:: Mitigating slowness due to extremely long lines.
* DEL Does Not Delete:: What to do if @key{DEL} doesn't delete.
Reporting Bugs
diff --git a/doc/emacs/trouble.texi b/doc/emacs/trouble.texi
index f06b93759d..887e5c6170 100644
--- a/doc/emacs/trouble.texi
+++ b/doc/emacs/trouble.texi
@@ -158,7 +158,6 @@ Emacs.
* Crashing:: What Emacs does when it crashes.
* After a Crash:: Recovering editing in an Emacs session that crashed.
* Emergency Escape:: What to do if Emacs stops responding.
-* Long Lines:: Mitigating slowness due to extremely long lines.
* DEL Does Not Delete:: What to do if @key{DEL} doesn't delete.
@end menu
@@ -433,64 +432,6 @@ program.
emergency escape---but there are cases where it won't work, when a
system call hangs or when Emacs is stuck in a tight loop in C code.
-@node Long Lines
-@subsection Long Lines
-@cindex long lines
-
- For a variety of reasons (some of which are fundamental to the Emacs
-redisplay code and the complex range of possibilities it handles;
-others of which are due to modes and features which do not scale well
-in unusual circumstances), Emacs can perform poorly when extremely
-long lines are present (where ``extremely long'' usually means at
-least many thousands of characters).
-
-@cindex @code{so-long} mode
-@findex global-so-long-mode
-@vindex so-long-action
- A particular problem is that Emacs may ``hang'' for a long time at
-the point of visiting a file with extremely long lines. This can be
-mitigated by enabling the @file{so-long} library, which detects when a
-visited file contains abnormally long lines, and takes steps to
-disable features which are liable to cause slowness in that situation.
-To enable this library, type @kbd{M-x global-so-long-mode @key{RET}},
-or turn on the @code{global-so-long-mode} in your init file
-(@pxref{Init File}), or customize the @code{global-so-long-mode}
-option. You can tailor this mode's operation by customizing the
-variable @code{so-long-action}.
-
- The @file{so-long} library can also significantly improve
-performance when moving and editing in a buffer with long lines.
-Performance is still likely to degrade as you get deeper into the long
-lines, but the improvements from using this library can nevertheless
-be substantial.
-
-@findex so-long-commentary
- Use @kbd{M-x so-long-commentary} to view the documentation for this
-library and learn more about how to enable and configure it.
-
-@vindex max-redisplay-ticks
- If even @code{so-long-mode} doesn't help making Emacs responsive
-enough, or if you'd rather not disable the display-related features
-that @code{so-long-mode} turns off, you can instead customize the
-variable @code{max-redisplay-ticks} to a non-zero value. Then Emacs
-will abort redisplay of a window and commands, like @kbd{C-n} and
-@kbd{M-v}, which use the display code to do their job, if processing a
-window needs more low-level display operations than the value of this
-variable. The display of the offending window will then remain
-outdated, and possibly incomplete, on the screen, but Emacs should
-otherwise be responsive, and you could then switch to another buffer,
-or kill the problematic buffer, or turn on @code{so-long-mode} or
-@code{so-long-minor-mode} in that buffer. When the display of a
-window is aborted due to this reason, the buffer shown in that window
-will not have any of its windows redisplayed until the buffer is
-modified or until you type @kbd{C-l} (@pxref{Recentering}) in one of
-that buffer's windows.
-
- If you decide to customize this variable to a non-zero value, we
-recommend to use a value between 100,000 and 1,000,000, depending on
-your patience and the speed of your system. The default value is
-zero, which disables this feature.
-
@node DEL Does Not Delete
@subsection If @key{DEL} Fails to Delete
@cindex @key{DEL} vs @key{BACKSPACE}
diff --git a/etc/NEWS b/etc/NEWS
index 7a1b7a856a..51d31bcf17 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -324,9 +324,6 @@ startup. Previously, these functions ignored
* Changes in Emacs 29.1
----
-** 'longlines-mode' is no longer obsolete.
-
+++
** New command to change the font size globally.
To increase the font size, type 'C-x C-M-+' or 'C-x C-M-='; to
@@ -901,6 +898,18 @@ Formerly it invoked 'just-one-space'. The actions
performed by
'cycle-spacing' and their order can now be customized via the user
option 'cycle-spacing-actions'.
++++
+** Emacs is now capable of editing files with arbitarily long lines.
+When a file with long lines is opened or inserted in a buffer, Emacs
+automatically enters auto-narrow mode. This means that Emacs
+restricts display, but not editing, to a portion of the buffer above
+and below point. All editing commands, including narrowing commands,
+remain available, and they act on the whole buffer. The behavior of
+that mode is controlled by three variables:
+auto-narrow-long-line-threshold, auto-narrow-display-length and
+auto-narrow-widen-automatically. To disable that feature, set
+auto-narrow-long-line-threshold to nil in your init file.
+
---
** 'zap-to-char' and 'zap-up-to-char' are case-sensitive for upper-case chars.
These commands now behave as case-sensitive for interactive calls when
diff --git a/lisp/bindings.el b/lisp/bindings.el
index 0cf1834a4f..3f7abcdbaa 100644
--- a/lisp/bindings.el
+++ b/lisp/bindings.el
@@ -400,10 +400,14 @@ mouse-1: Display minor mode menu\n\
mouse-2: Show help for minor mode\n\
mouse-3: Toggle minor modes"
local-map ,mode-line-minor-mode-keymap)
- (propertize "%n" 'help-echo "mouse-2: Remove narrowing from buffer"
- 'mouse-face 'mode-line-highlight
- 'local-map (make-mode-line-mouse-map
- 'mouse-2 #'mode-line-widen))
+ '(:eval
+ (if (not (eq auto-narrow--narrowing-state 'auto))
+ (propertize "%n"
+ 'help-echo "mouse-2: Remove narrowing from buffer"
+ 'mouse-face 'mode-line-highlight
+ 'local-map (make-mode-line-mouse-map
+ 'mouse-2 #'mode-line-widen))
+ "%n"))
")"
(propertize "%]" 'help-echo recursive-edit-help-echo)
" "))
diff --git a/lisp/files.el b/lisp/files.el
index 31e450355f..0e6f1a935d 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -2688,6 +2688,103 @@ the file contents into it using
`insert-file-contents-literally'."
(confirm-nonexistent-file-or-buffer))))
(switch-to-buffer (find-file-noselect filename nil t)))
+(defcustom auto-narrow-display-length 30000
+ "Number of characters to which display is restricted in `auto-narrow-mode'.
+
+When `auto-narrow-mode' is in effect, the number of characters
+displayed above and below point is one third of
+`auto-narrow-display-line-length', except at the beginning and
+end of the buffer."
+ :group 'files
+ :group 'find-file
+ :version "29.1"
+ :type 'integer)
+
+(defcustom auto-narrow-widen-automatically
+ '( move-beginning-of-line move-end-of-line backward-sentence forward-sentence
+ backward-sexp forward-sexp beginning-of-defun end-of-defun
+ beginning-of-buffer end-of-buffer goto-char goto-line
+ mark-sexp mark-defun mark-paragraph mark-whole-buffer mark-page
+ exchange-point-and-mark pop-global-mark set-mark-command jump-to-register
+ bookmark-jump)
+ "Commands for which display is automatically widened in `auto-narrow-mode'."
+ :group 'files
+ :group 'find-file
+ :version "29.1"
+ :type '(repeat function))
+
+(defvar-local auto-narrow--widen-automatically nil
+ "Internal variable used by `auto-narrow-mode'.")
+
+(defvar-local auto-narrow--isearch-widen-automatically nil
+ "Internal variable used by `auto-narrow-mode'.")
+
+(defvar-local auto-narrow--initialized nil
+ "Internal variable used by `auto-narrow-mode'.")
+
+(defun auto-narrow-pre-command-function ()
+ "Conditionally widen display when `auto-narrow-mode' is in effect."
+ (when auto-narrow-mode
+ (unless auto-narrow--initialized
+ (setq auto-narrow--widen-automatically widen-automatically
+ auto-narrow--isearch-widen-automatically
isearch-widen-automatically
+ auto-narrow--narrowing-state 'auto
+ auto-narrow--initialized t))
+ (setq-local widen-automatically t
+ isearch-widen-automatically t)
+ (if (memq this-command '(narrow-to-region narrow-to-defun narrow-to-page))
+ (setq auto-narrow--narrowing-state 'explicit
+ widen-automatically auto-narrow--widen-automatically
+ isearch-widen-automatically
auto-narrow--isearch-widen-automatically))
+ (if (eq this-command 'widen)
+ (setq auto-narrow--narrowing-state 'auto))
+ (when (and (not (eq auto-narrow--narrowing-state 'explicit))
+ (memq this-command auto-narrow-widen-automatically))
+ (widen))))
+
+(defun auto-narrow-post-command-function ()
+ "Update display narrowing when `auto-narrow-mode' is in effect."
+ (when (and auto-narrow-mode
+ (not (eq auto-narrow--narrowing-state 'explicit)))
+ (unless auto-narrow--initialized
+ (setq auto-narrow--narrowing-state 'auto))
+ (let (point cur-point-min buf-point-min buf-point-max size)
+ (setq point (point) cur-point-min (point-min)
+ size (/ auto-narrow-display-length 3))
+ (save-restriction
+ (widen)
+ (setq buf-point-min (point-min) buf-point-max (point-max)))
+ (let* ((pos (* (min (max (/ point size) 1)
+ (1- (/ buf-point-max size)))
+ size))
+ (begin (max (- pos size) buf-point-min))
+ (end (min (+ begin (* 3 size)) buf-point-max)))
+ (when (or (not (buffer-narrowed-p))
+ (not (= begin cur-point-min)))
+ (narrow-to-region begin end))))))
+
+(setq auto-narrow-long-line-threshold 30000
+ auto-narrow-pre-command-function #'auto-narrow-pre-command-function
+ auto-narrow-post-command-function #'auto-narrow-post-command-function)
+
+(define-minor-mode auto-narrow-mode
+ "Automatically narrow the display of a buffer above and below point.
+
+This mode is automatically entered when a file with one or more lines
+longer than `auto-narrow-long-line-threshold' is opened or inserted
+in a buffer. It restricts display, but not editing, to
+`auto-narrow-display-length' characters. Display is widened before
+executing any of the commands listed in `auto-narrow-widen-automatically'."
+ :group 'files
+ :version "29.1"
+ :after-hook (progn (put 'auto-narrow-mode 'permanent-local t))
+ (if auto-narrow-mode
+ (auto-narrow-post-command-function)
+ (when (not (eq auto-narrow--narrowing-state 'explicit))
+ (widen))
+ (setq auto-narrow--narrowing-state nil
+ auto-narrow--initialized nil)))
+
(defun after-find-file (&optional error warn noauto
_after-find-file-from-revert-buffer
nomodes)
diff --git a/lisp/isearch.el b/lisp/isearch.el
index db7b53c014..a6e034df6b 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -3037,6 +3037,13 @@ search. This option is ignored \(presumed t) when
:type 'boolean
:group 'isearch)
+(defcustom isearch-widen-automatically nil
+ "Whether a narrowed buffer can be widened when isearch fails.
+This option has no effect when `widen-automatically' is nil."
+ :version "29.1"
+ :type 'boolean
+ :group 'isearch)
+
(defun isearch-string-out-of-window (isearch-point)
"Test whether the search string is currently outside of the window.
Return nil if it's completely visible, or if point is visible,
@@ -3649,17 +3656,20 @@ Optional third argument, if t, means if fail just
return nil (no error).
(while retry
(setq isearch-success
(isearch-search-string isearch-string nil t))
- ;; Clear RETRY unless the search predicate says
- ;; to skip this search hit.
- (if (or (not isearch-success)
- (funcall isearch-filter-predicate
- (match-beginning 0) (match-end 0)))
- (setq retry nil)
- ;; Advance point on empty matches before retrying
- (when (= (match-beginning 0) (match-end 0))
- (if (if isearch-forward (eobp) (bobp))
- (setq retry nil isearch-success nil)
- (forward-char (if isearch-forward 1 -1))))))
+ (if (and (not isearch-success) (buffer-narrowed-p)
+ isearch-widen-automatically widen-automatically)
+ (widen)
+ ;; Clear RETRY unless the search predicate says
+ ;; to skip this search hit.
+ (if (or (not isearch-success)
+ (funcall isearch-filter-predicate
+ (match-beginning 0) (match-end 0)))
+ (setq retry nil)
+ ;; Advance point on empty matches before retrying
+ (when (= (match-beginning 0) (match-end 0))
+ (if (if isearch-forward (eobp) (bobp))
+ (setq retry nil isearch-success nil)
+ (forward-char (if isearch-forward 1 -1)))))))
(setq isearch-just-started nil)
(when isearch-success
(setq isearch-other-end
diff --git a/lisp/longlines.el b/lisp/obsolete/longlines.el
similarity index 99%
rename from lisp/longlines.el
rename to lisp/obsolete/longlines.el
index a6cf93a039..d44a634e2e 100644
--- a/lisp/longlines.el
+++ b/lisp/obsolete/longlines.el
@@ -6,6 +6,7 @@
;; Alex Schroeder <alex@gnu.org>
;; Chong Yidong <cyd@stupidchicken.com>
;; Maintainer: emacs-devel@gnu.org
+;; Obsolete-since: 24.4
;; Keywords: convenience, wp
;; This file is part of GNU Emacs.
diff --git a/src/buffer.c b/src/buffer.c
index 509ce51b55..d5b4292a21 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -5276,6 +5276,9 @@ init_buffer_once (void)
XSETFASTINT (BVAR (&buffer_local_flags, tab_line_format), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, cursor_type), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, extra_line_spacing), idx); ++idx;
+ XSETFASTINT (BVAR (&buffer_local_flags, auto_narrow__narrowing_state), idx);
+ /* Make this one a permanent local. */
+ buffer_permanent_local_flags[idx++] = 1;
XSETFASTINT (BVAR (&buffer_local_flags, cursor_in_non_selected_windows),
idx); ++idx;
/* buffer_local_flags contains no pointers, so it's safe to treat it
@@ -5662,7 +5665,7 @@ A string is printed verbatim in the mode line except for
%-constructs:
%p -- print percent of buffer above top of window, or Top, Bot or All.
%P -- print percent of buffer above bottom of window, perhaps plus Top,
or print Bottom or All.
- %n -- print Narrow if appropriate.
+ %n -- print Narrow or Auto-Narrow if appropriate.
%t -- visited file is text or binary (if OS supports this distinction).
%z -- print mnemonics of keyboard, terminal, and buffer coding systems.
%Z -- like %z, but including the end-of-line format.
@@ -6363,6 +6366,10 @@ see `display-graphic-p'.
If value is a floating point number, it specifies the spacing relative
to the default frame line height. A value of nil means add no extra space.
*/);
+ DEFVAR_PER_BUFFER ("auto-narrow--narrowing-state",
+ &BVAR (current_buffer, auto_narrow__narrowing_state), Qnil,
+ doc: /* Internal variable used by `auto-narrow-mode'. */);
+
DEFVAR_PER_BUFFER ("cursor-in-non-selected-windows",
&BVAR (current_buffer, cursor_in_non_selected_windows),
Qnil,
doc: /* Non-nil means show a cursor in non-selected
windows.
diff --git a/src/buffer.h b/src/buffer.h
index 135eaf72d3..19faa844e0 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -561,6 +561,9 @@ struct buffer
in the display of this buffer. */
Lisp_Object extra_line_spacing_;
+ /* Narrowing state when auto-narrow mode is in effect. */
+ Lisp_Object auto_narrow__narrowing_state_;
+
/* Cursor type to display in non-selected windows.
t means to use hollow box cursor.
See `cursor-type' for other values. */
@@ -832,6 +835,11 @@ bset_width_table (struct buffer *b, Lisp_Object val)
{
b->width_table_ = val;
}
+INLINE void
+bset_auto_narrow__narrowing_state (struct buffer *b, Lisp_Object val)
+{
+ b->auto_narrow__narrowing_state_ = val;
+}
/* BUFFER_CEILING_OF (resp. BUFFER_FLOOR_OF), when applied to n, return
the max (resp. min) p such that
@@ -1112,6 +1120,12 @@ BUFFER_CHECK_INDIRECTION (struct buffer *b)
}
}
+INLINE bool
+BUFFER_AUTO_NARROWED_P (struct buffer *b)
+{
+ return EQ (BVAR (b, auto_narrow__narrowing_state), Qauto);
+}
+
/* This structure holds the default values of the buffer-local variables
that have special slots in each buffer.
The default value occupies the same slot in this structure
diff --git a/src/fileio.c b/src/fileio.c
index 10d4b8bc15..bb6f73fe39 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -4997,6 +4997,16 @@ by calling `format-decode', which see. */)
Otherwise start with an empty undo_list. */
bset_undo_list (current_buffer, EQ (old_undo, Qt) ? Qt : Qnil);
+ if (!noninteractive
+ && !NILP (Vauto_narrow_long_line_threshold)
+ && !NILP (CALLN
+ (Fgtr,
+ Fcar (Fcdr (Fbuffer_line_statistics (Fcurrent_buffer ()))),
+ Vauto_narrow_long_line_threshold)))
+ {
+ bset_auto_narrow__narrowing_state (current_buffer, Qneeded);
+ }
+
unbind_to (count1, Qnil);
}
@@ -6638,6 +6648,17 @@ This includes interactive calls to `delete-file' and
/* Lisp function for recursively deleting directories. */
DEFSYM (Qdelete_directory, "delete-directory");
+ DEFVAR_LISP ("auto-narrow-long-line-threshold",
+ Vauto_narrow_long_line_threshold,
+ doc: /* Line length above which `auto-narrow-mode' is entered.
+When non-nil, and when a file with one or more lines longer than
+`auto-narrow-long-line-threshold' is opened or inserted in a buffer,
+`auto-narrow-mode' is automatically enabled.
+When nil, `auto-narrow-mode' is disabled. */);
+ Vauto_narrow_long_line_threshold = Qnil;
+
+ DEFSYM (Qauto_narrow_mode, "auto-narrow-mode");
+
DEFSYM (Qsubstitute_env_in_file_name, "substitute-env-in-file-name");
DEFSYM (Qget_buffer_window_list, "get-buffer-window-list");
diff --git a/src/keyboard.c b/src/keyboard.c
index bed8307b6f..38aa64774d 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1290,6 +1290,9 @@ command_loop_1 (void)
if (NILP (Vmemory_full))
{
+ if (!NILP (Vauto_narrow_post_command_function) && !NILP (Vrun_hooks))
+ safe_run_hooks (Qauto_narrow_post_command_function);
+
/* Make sure this hook runs after commands that get errors and
throw to top level. */
/* Note that the value cell will never directly contain nil
@@ -1472,6 +1475,8 @@ command_loop_1 (void)
Vreal_this_command = cmd;
safe_run_hooks (Qpre_command_hook);
+ safe_run_hooks (Qauto_narrow_pre_command_function);
+
already_adjusted = 0;
if (NILP (Vthis_command))
@@ -1522,6 +1527,8 @@ command_loop_1 (void)
}
kset_last_prefix_arg (current_kboard, Vcurrent_prefix_arg);
+ safe_run_hooks (Qauto_narrow_post_command_function);
+
safe_run_hooks (Qpost_command_hook);
/* If displaying a message, resize the echo area window to fit
@@ -12040,6 +12047,11 @@ syms_of_keyboard (void)
DEFSYM (Qpre_command_hook, "pre-command-hook");
DEFSYM (Qpost_command_hook, "post-command-hook");
+ DEFSYM (Qauto_narrow_pre_command_function,
+ "auto-narrow-pre-command-function");
+ DEFSYM (Qauto_narrow_post_command_function,
+ "auto-narrow-post-command-function");
+
DEFSYM (Qundo_auto__add_boundary, "undo-auto--add-boundary");
DEFSYM (Qundo_auto__undoably_changed_buffers,
"undo-auto--undoably-changed-buffers");
@@ -12604,6 +12616,22 @@ avoid making Emacs unresponsive while the user types.
See also `pre-command-hook'. */);
Vpost_command_hook = Qnil;
+ DEFVAR_LISP ("auto-narrow-pre-command-function",
+ Vauto_narrow_pre_command_function,
+ doc: /* Function executed before each command is executed in
`auto-narrow-mode'.
+If non-nil, and `auto-narrow-mode' is enabled, the function is
+called before each command is executed, after `pre-command-hook'.
+It is called without arguments. */);
+ Vauto_narrow_pre_command_function = Qnil;
+
+ DEFVAR_LISP ("auto-narrow-post-command-function",
+ Vauto_narrow_post_command_function,
+ doc: /* Function executed after each command is executed in
`auto-narrow-mode'.
+If non-nil, and `auto-narrow-mode' is enabled, the function is
+called after each command is executed, before `post-command-hook'.
+It is called without arguments. */);
+ Vauto_narrow_post_command_function = Qnil;
+
#if 0
DEFVAR_LISP ("echo-area-clear-hook", ...,
doc: /* Normal hook run when clearing the echo area. */);
diff --git a/src/xdisp.c b/src/xdisp.c
index 4089525e10..be51a0eb13 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -18872,11 +18872,20 @@ set_vertical_scroll_bar (struct window *w)
&& NILP (echo_area_buffer[0])))
{
struct buffer *buf = XBUFFER (w->contents);
- whole = BUF_ZV (buf) - BUF_BEGV (buf);
- start = marker_position (w->start) - BUF_BEGV (buf);
- /* I don't think this is guaranteed to be right. For the
- moment, we'll pretend it is. */
- end = BUF_Z (buf) - w->window_end_pos - BUF_BEGV (buf);
+ if (! BUFFER_AUTO_NARROWED_P (current_buffer))
+ {
+ whole = BUF_ZV (buf) - BUF_BEGV (buf);
+ start = marker_position (w->start) - BUF_BEGV (buf);
+ /* I don't think this is guaranteed to be right. For the
+ moment, we'll pretend it is. */
+ end = BUF_Z (buf) - w->window_end_pos - BUF_BEGV (buf);
+ }
+ else
+ {
+ whole = BUF_Z (buf) - BUF_BEG (buf);
+ start = marker_position (w->start) - BUF_BEG (buf);
+ end = BUF_Z (buf) - w->window_end_pos - BUF_BEG (buf);
+ }
if (end < start)
end = start;
@@ -19133,6 +19142,14 @@ redisplay_window (Lisp_Object window, bool
just_this_one_p)
variables. */
set_buffer_internal_1 (XBUFFER (w->contents));
+ if (EQ (BVAR (current_buffer, auto_narrow__narrowing_state), Qneeded))
+ {
+ safe_call (1, Qauto_narrow_mode);
+ /* Normally set by auto-narrow-mode, set it here anyway as a safety
measure. */
+ bset_auto_narrow__narrowing_state (current_buffer, Qauto);
+ message1 ("Auto-Narrow mode enabled in current buffer");
+ }
+
current_matrix_up_to_date_p
= (w->window_end_valid
&& !current_buffer->clip_changed
@@ -27667,7 +27684,12 @@ decode_mode_spec (struct window *w, register int c,
int field_width,
case 'n':
if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
- return " Narrow";
+ {
+ if (! BUFFER_AUTO_NARROWED_P (b))
+ return " Narrow";
+ else
+ return " Auto-Narrow";
+ }
break;
/* Display the "degree of travel" of the window through the buffer. */
@@ -27675,17 +27697,27 @@ decode_mode_spec (struct window *w, register int c,
int field_width,
{
ptrdiff_t toppos = marker_position (w->start);
ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
- ptrdiff_t begv = BUF_BEGV (b);
- ptrdiff_t zv = BUF_ZV (b);
+ ptrdiff_t beg, z;
- if (zv <= botpos)
- return toppos <= begv ? "All" : "Bottom";
- else if (toppos <= begv)
+ if (! BUFFER_AUTO_NARROWED_P (b))
+ {
+ beg = BUF_BEGV (b);
+ z = BUF_ZV (b);
+ }
+ else
+ {
+ beg = BUF_BEG (b);
+ z = BUF_Z (b);
+ }
+
+ if (z <= botpos)
+ return toppos <= beg ? "All" : "Bottom";
+ else if (toppos <= beg)
return "Top";
else
{
sprintf (decode_mode_spec_buf, "%2d%%",
- percent99 (toppos - begv, (toppos - begv) + (zv - botpos)));
+ percent99 (toppos - beg, (toppos - beg) + (z - botpos)));
return decode_mode_spec_buf;
}
}
@@ -27694,17 +27726,27 @@ decode_mode_spec (struct window *w, register int c,
int field_width,
case 'p':
{
ptrdiff_t pos = marker_position (w->start);
- ptrdiff_t begv = BUF_BEGV (b);
- ptrdiff_t zv = BUF_ZV (b);
+ ptrdiff_t beg, z;
- if (w->window_end_pos <= BUF_Z (b) - zv)
- return pos <= begv ? "All" : "Bottom";
- else if (pos <= begv)
+ if (! BUFFER_AUTO_NARROWED_P (b))
+ {
+ beg = BUF_BEGV (b);
+ z = BUF_ZV (b);
+ }
+ else
+ {
+ beg = BUF_BEG (b);
+ z = BUF_Z (b);
+ }
+
+ if (w->window_end_pos <= BUF_Z (b) - z)
+ return pos <= beg ? "All" : "Bottom";
+ else if (pos <= beg)
return "Top";
else
{
sprintf (decode_mode_spec_buf, "%2d%%",
- percent99 (pos - begv, zv - begv));
+ percent99 (pos - beg, z - beg));
return decode_mode_spec_buf;
}
}
@@ -27714,16 +27756,26 @@ decode_mode_spec (struct window *w, register int c,
int field_width,
{
ptrdiff_t toppos = marker_position (w->start);
ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
- ptrdiff_t begv = BUF_BEGV (b);
- ptrdiff_t zv = BUF_ZV (b);
+ ptrdiff_t beg, z;
- if (zv <= botpos)
- return toppos <= begv ? "All" : "Bottom";
+ if (! BUFFER_AUTO_NARROWED_P (b))
+ {
+ beg = BUF_BEGV (b);
+ z = BUF_ZV (b);
+ }
+ else
+ {
+ beg = BUF_BEG (b);
+ z = BUF_Z (b);
+ }
+
+ if (z <= botpos)
+ return toppos <= beg ? "All" : "Bottom";
else
{
sprintf (decode_mode_spec_buf,
- &"Top%2d%%"[begv < toppos ? sizeof "Top" - 1 : 0],
- percent99 (botpos - begv, zv - begv));
+ &"Top%2d%%"[beg < toppos ? sizeof "Top" - 1 : 0],
+ percent99 (botpos - beg, z - beg));
return decode_mode_spec_buf;
}
}
@@ -27734,15 +27786,25 @@ decode_mode_spec (struct window *w, register int c,
int field_width,
{
ptrdiff_t toppos = marker_position (w->start);
ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
- ptrdiff_t begv = BUF_BEGV (b);
- ptrdiff_t zv = BUF_ZV (b);
+ ptrdiff_t beg, z;
int top_perc, bot_perc;
- if ((toppos <= begv) && (zv <= botpos))
+ if (! BUFFER_AUTO_NARROWED_P (b))
+ {
+ beg = BUF_BEGV (b);
+ z = BUF_ZV (b);
+ }
+ else
+ {
+ beg = BUF_BEG (b);
+ z = BUF_Z (b);
+ }
+
+ if ((toppos <= beg) && (z <= botpos))
return "All ";
- top_perc = toppos <= begv ? 0 : percent99 (toppos - begv, zv - begv);
- bot_perc = zv <= botpos ? 100 : percent99 (botpos - begv, zv - begv);
+ top_perc = toppos <= beg ? 0 : percent99 (toppos - beg, z - beg);
+ bot_perc = z <= botpos ? 100 : percent99 (botpos - beg, z - beg);
if (top_perc == bot_perc)
sprintf (decode_mode_spec_buf, "%d%%", top_perc);
@@ -35830,6 +35892,8 @@ be let-bound around code that needs to disable messages
temporarily. */);
DEFSYM (Qinhibit_point_motion_hooks, "inhibit-point-motion-hooks");
DEFSYM (Qeval, "eval");
DEFSYM (QCdata, ":data");
+ DEFSYM (Qneeded, "needed");
+ DEFSYM (Qauto, "auto");
/* Names of text properties relevant for redisplay. */
DEFSYM (Qdisplay, "display");