From: Gregory Heytings <gregory@heytings.org>
To: 56393@debbugs.gnu.org
Subject: bug#56393: Actually fix the long lines display bug
Date: Tue, 05 Jul 2022 09:28:04 +0000 [thread overview]
Message-ID: <38c1a310405bd4bbe370@heytings.org> (raw)
In-Reply-To: <38c1a31040d2d2bc47ae@heytings.org>
[-- Attachment #1: Type: text/plain, Size: 98 bytes --]
Sorry, something was missing in the previous patch, here is the complete
one, with a bug number.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Actually-fix-the-long-lines-display-bug.patch --]
[-- Type: text/x-diff; name=Actually-fix-the-long-lines-display-bug.patch, Size: 31587 bytes --]
From bfb148ccacccb724723de45b86c110be33a93175 Mon Sep 17 00:00:00 2001
From: Gregory Heytings <gregory@heytings.org>
Date: Tue, 5 Jul 2022 09:23:57 +0000
Subject: [PATCH] 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.
* src/buffer.c (init_buffer_once, syms_of_buffer): New internal variable
for the minor mode.
* src/fileio.c (Finsert_file_contents): Automatically enter the minor mode
when appropriate.
(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/search.c (find_newline1): Make it externally visible.
* src/lisp.h: Make find_newline1 externally visible.
* src/xdisp.c (decode_mode_spec): Indicate when the minor mode is active
in the modeline.
* 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 | 92 ++++++++++++++++++++++++++++++++
lisp/isearch.el | 32 +++++++----
lisp/{ => obsolete}/longlines.el | 1 +
lisp/x-dnd.el | 65 +++++++++++++++-------
src/buffer.c | 5 ++
src/buffer.h | 3 ++
src/fileio.c | 25 +++++++++
src/keyboard.c | 28 ++++++++++
src/lisp.h | 2 +
src/search.c | 2 +-
src/xdisp.c | 7 ++-
16 files changed, 274 insertions(+), 100 deletions(-)
rename lisp/{ => obsolete}/longlines.el (99%)
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 @@ Display
* 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 @@ Narrowing
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 @@ Top
* 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 @@ Lossage
* 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 @@ Emergency Escape
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 7967190c6e..30c71e7f0c 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -324,9 +324,6 @@ startup. Previously, these functions ignored
\f
* 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..fa5040776d 100644
--- a/lisp/bindings.el
+++ b/lisp/bindings.el
@@ -400,10 +400,14 @@ mode-line-modes
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 '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 8812175014..abdeea7a80 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -2648,6 +2648,98 @@ find-file-literally
(confirm-nonexistent-file-or-buffer))))
(switch-to-buffer (find-file-noselect filename nil t)))
\f
+(defcustom auto-narrow-display-length 30000
+ "Number of characters to which display is restricted in `auto-narrow-mode'."
+ :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 '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 'explicit
+ widen-automatically auto-narrow--widen-automatically
+ isearch-widen-automatically auto-narrow--isearch-widen-automatically))
+ (if (eq this-command 'widen)
+ (setq auto-narrow--narrowing 'auto))
+ (when (and (not (eq auto-narrow--narrowing '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 'explicit)))
+ (unless auto-narrow--initialized
+ (setq auto-narrow--narrowing '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)
+ (put 'auto-narrow--narrowing 'permanent-local t))
+ (if auto-narrow-mode
+ (auto-narrow-post-command-function)
+ (when (not (eq auto-narrow--narrowing 'explicit))
+ (widen))
+ (setq auto-narrow--narrowing nil)))
+\f
(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 @@ isearch-allow-prefix
: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 @@ isearch-search
(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/lisp/x-dnd.el b/lisp/x-dnd.el
index 3fd2d70cb6..9c1c98a1bf 100644
--- a/lisp/x-dnd.el
+++ b/lisp/x-dnd.el
@@ -135,7 +135,11 @@ x-dnd-direct-save-function
If the first argument is nil, the second is the name of the file
that was dropped."
:version "29.1"
- :type 'function
+ :type '(choice (const :tag "Prompt for name before saving"
+ x-dnd-save-direct)
+ (const :tag "Save and open immediately without prompting"
+ x-dnd-save-direct-immediately)
+ (function :tag "Other function"))
:group 'x)
(defcustom x-dnd-copy-types '("chromium/x-renderer-taint")
@@ -186,18 +190,21 @@ x-dnd-empty-state
(declare-function x-register-dnd-atom "xselect.c")
+(defvar x-fast-protocol-requests)
+
(defun x-dnd-init-frame (&optional frame)
"Setup drag and drop for FRAME (i.e. create appropriate properties)."
(when (eq 'x (window-system frame))
- (x-register-dnd-atom "DndProtocol" frame)
- (x-register-dnd-atom "_MOTIF_DRAG_AND_DROP_MESSAGE" frame)
- (x-register-dnd-atom "XdndEnter" frame)
- (x-register-dnd-atom "XdndPosition" frame)
- (x-register-dnd-atom "XdndLeave" frame)
- (x-register-dnd-atom "XdndDrop" frame)
- (x-register-dnd-atom "_DND_PROTOCOL" frame)
- (x-dnd-init-xdnd-for-frame frame)
- (x-dnd-init-motif-for-frame frame)))
+ (let ((x-fast-protocol-requests (not x-dnd-debug-errors)))
+ (x-register-dnd-atom "DndProtocol" frame)
+ (x-register-dnd-atom "_MOTIF_DRAG_AND_DROP_MESSAGE" frame)
+ (x-register-dnd-atom "XdndEnter" frame)
+ (x-register-dnd-atom "XdndPosition" frame)
+ (x-register-dnd-atom "XdndLeave" frame)
+ (x-register-dnd-atom "XdndDrop" frame)
+ (x-register-dnd-atom "_DND_PROTOCOL" frame)
+ (x-dnd-init-xdnd-for-frame frame)
+ (x-dnd-init-motif-for-frame frame))))
(defun x-dnd-get-state-cons-for-frame (frame-or-window)
"Return the entry in `x-dnd-current-state' for a frame or window."
@@ -430,8 +437,6 @@ x-dnd-drop-data
(select-frame frame)
(funcall handler window action data))))))
-(defvar x-fast-protocol-requests)
-
(defun x-dnd-handle-drag-n-drop-event (event)
"Receive drag and drop events (X client messages).
Currently XDND, Motif and old KDE 1.x protocols are recognized."
@@ -1361,6 +1366,27 @@ x-dnd-save-direct
(revert-buffer)
(find-file name))))
+(defun x-dnd-save-direct-immediately (need-name name)
+ "Save and open a dropped file, like `x-dnd-save-direct'.
+NEED-NAME tells whether or not the file was not yet saved. NAME
+is either the name of the file, or the name the drop source wants
+us to save under.
+
+Unlike `x-dnd-save-direct', do not prompt for the name by which
+to save the file. Simply save it in the current directory."
+ (if need-name
+ (let ((file-name (expand-file-name name)))
+ (when (file-exists-p file-name)
+ (unless (y-or-n-p (format-message
+ "File `%s' exists; overwrite? " file-name))
+ (setq file-name nil)))
+ file-name)
+ ;; TODO: move this to dired.el once a platform-agonistic
+ ;; interface can be found.
+ (if (derived-mode-p 'dired-mode)
+ (revert-buffer)
+ (find-file name))))
+
(defun x-dnd-handle-octet-stream-for-drop (save-to)
"Save the contents of the XDS selection to SAVE-TO.
Return non-nil if successful, nil otherwise."
@@ -1402,15 +1428,14 @@ x-dnd-handle-xds-drop
desired-name
(or file-name-coding-system
default-file-name-coding-system)))
- (setq save-to (expand-file-name
- (funcall x-dnd-direct-save-function
- t desired-name))
- save-to-remote save-to)
- (if (file-remote-p save-to)
- (setq hostname (file-remote-p save-to 'host)
- save-to (file-local-name save-to))
- (setq hostname (system-name)))
+ (let ((name (funcall x-dnd-direct-save-function
+ t desired-name)))
+ (setq save-to name save-to-remote name))
(when save-to
+ (if (file-remote-p save-to)
+ (setq hostname (file-remote-p save-to 'host)
+ save-to (file-local-name save-to))
+ (setq hostname (system-name)))
(with-selected-window window
(let ((uri (format "file://%s%s" hostname save-to)))
(x-change-window-property "XdndDirectSave0"
diff --git a/src/buffer.c b/src/buffer.c
index 509ce51b55..cbc246067d 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -5276,6 +5276,7 @@ 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), idx); ++idx;
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
@@ -6363,6 +6364,10 @@ from (abs POSITION). If POSITION is positive, point was at the front
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",
+ &BVAR (current_buffer, auto_narrow__narrowing), 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..a6abc6ece8 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -561,6 +561,9 @@ #define BVAR(buf, field) ((buf)->field ## _)
in the display of this buffer. */
Lisp_Object extra_line_spacing_;
+ /* Narrowing type when auto-narrow mode is in effect. */
+ Lisp_Object auto_narrow__narrowing_;
+
/* Cursor type to display in non-selected windows.
t means to use hollow box cursor.
See `cursor-type' for other values. */
diff --git a/src/fileio.c b/src/fileio.c
index 10d4b8bc15..9d2cf2ae00 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -4997,6 +4997,20 @@ because (1) it preserves some marker positions (in unchanged portions
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))
+ {
+ ptrdiff_t cur, next, found, max = 0;
+ for (cur = PT; cur < PT + inserted; cur = next)
+ {
+ next = find_newline1 (cur, CHAR_TO_BYTE (cur), 0, -1, 1,
+ &found, NULL, true);
+ if (next - cur > max) max = next - cur;
+ if (!found) break;
+ }
+ if (max > XFIXNUM (Vauto_narrow_long_line_threshold))
+ safe_call (1, Qauto_narrow_mode);
+ }
+
unbind_to (count1, Qnil);
}
@@ -6638,6 +6652,17 @@ do (file-exists-p FILENAME) and FILENAME is handled by HANDLER, then
/* 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 not entered automatically. */);
+ 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 @@ syms_of_keyboard (void)
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/lisp.h b/src/lisp.h
index e4a49b8ef9..289141296c 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4761,6 +4761,8 @@ fast_string_match_ignore_case (Lisp_Object regexp, Lisp_Object string)
ptrdiff_t);
extern ptrdiff_t fast_looking_at (Lisp_Object, ptrdiff_t, ptrdiff_t,
ptrdiff_t, ptrdiff_t, Lisp_Object);
+extern ptrdiff_t find_newline1 (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
+ ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool);
extern ptrdiff_t find_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
ptrdiff_t, ptrdiff_t *, ptrdiff_t *, bool);
extern void scan_newline (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t,
diff --git a/src/search.c b/src/search.c
index 9d6bd074e1..b5d6a442c0 100644
--- a/src/search.c
+++ b/src/search.c
@@ -3192,7 +3192,7 @@ DEFUN ("regexp-quote", Fregexp_quote, Sregexp_quote, 1, 1, 0,
}
/* Like find_newline, but doesn't use the cache, and only searches forward. */
-static ptrdiff_t
+ptrdiff_t
find_newline1 (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
ptrdiff_t end_byte, ptrdiff_t count, ptrdiff_t *counted,
ptrdiff_t *bytepos, bool allow_quit)
diff --git a/src/xdisp.c b/src/xdisp.c
index 4089525e10..d782659b92 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -27667,7 +27667,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 (EQ (BVAR (current_buffer, auto_narrow__narrowing), intern ("auto")))
+ return " Auto-Narrow";
+ else
+ return " Narrow";
+ }
break;
/* Display the "degree of travel" of the window through the buffer. */
--
2.35.1
next prev parent reply other threads:[~2022-07-05 9:28 UTC|newest]
Thread overview: 205+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-07-05 8:49 bug#56393: Actually fix the long lines display bug Gregory Heytings
2022-07-05 9:28 ` Gregory Heytings [this message]
2022-07-05 9:58 ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-07-05 10:17 ` Gregory Heytings
2022-07-05 11:24 ` Lars Ingebrigtsen
2022-07-05 12:16 ` Gregory Heytings
2022-07-05 12:59 ` Gerd Möllmann
2022-07-07 11:29 ` Gerd Möllmann
2022-07-07 13:36 ` Eli Zaretskii
2022-07-07 14:10 ` Eli Zaretskii
2022-07-08 5:49 ` Gerd Möllmann
2022-07-08 6:55 ` Eli Zaretskii
2022-07-08 7:01 ` Gerd Möllmann
2022-07-08 21:41 ` Gregory Heytings
2022-07-09 7:03 ` Eli Zaretskii
2022-07-09 8:56 ` Gregory Heytings
2022-07-09 9:20 ` Eli Zaretskii
2022-07-09 9:23 ` Eli Zaretskii
2022-07-09 9:32 ` Gregory Heytings
2022-07-09 9:30 ` Eli Zaretskii
2022-07-09 9:49 ` Gregory Heytings
2022-07-09 10:01 ` Eli Zaretskii
2022-07-09 10:50 ` Gregory Heytings
2022-07-09 11:16 ` Eli Zaretskii
2022-07-09 11:48 ` Gregory Heytings
2022-07-09 11:59 ` Eli Zaretskii
2022-07-09 12:07 ` Gregory Heytings
2022-07-09 12:34 ` Eli Zaretskii
2022-07-09 12:36 ` Gregory Heytings
2022-07-09 12:09 ` Ihor Radchenko
2022-07-09 12:37 ` Eli Zaretskii
2022-07-09 10:54 ` Eli Zaretskii
2022-07-09 11:09 ` Eli Zaretskii
2022-07-09 11:12 ` Gregory Heytings
2022-07-09 11:20 ` Gregory Heytings
2022-07-09 12:29 ` Lars Ingebrigtsen
2022-07-09 12:38 ` Gregory Heytings
2022-07-16 19:39 ` Gregory Heytings
2022-07-17 15:21 ` Eli Zaretskii
2022-07-17 15:37 ` Gregory Heytings
2022-07-17 16:00 ` Eli Zaretskii
2022-07-18 10:19 ` Gregory Heytings
2022-07-18 12:20 ` Eli Zaretskii
2022-07-18 12:58 ` Gregory Heytings
2022-07-18 13:33 ` Eli Zaretskii
2022-07-18 14:00 ` Gregory Heytings
2022-07-18 14:10 ` Gregory Heytings
2022-07-18 14:22 ` Eli Zaretskii
2022-07-18 14:34 ` Gregory Heytings
2022-07-18 16:06 ` Gregory Heytings
2022-07-18 16:21 ` Gregory Heytings
2022-07-18 17:04 ` Eli Zaretskii
2022-07-18 17:07 ` Gregory Heytings
2022-07-18 17:09 ` Eli Zaretskii
2022-07-18 18:33 ` Gregory Heytings
2022-07-18 16:48 ` Eli Zaretskii
2022-07-18 17:11 ` Gregory Heytings
2022-07-18 17:19 ` Eli Zaretskii
2022-07-18 18:17 ` Gregory Heytings
2022-07-18 18:26 ` Gregory Heytings
2022-07-18 18:56 ` Eli Zaretskii
2022-07-18 20:14 ` Gregory Heytings
2022-07-19 2:34 ` Eli Zaretskii
2022-07-19 5:39 ` Gregory Heytings
2022-07-19 12:00 ` Eli Zaretskii
2022-07-19 12:07 ` Gerd Möllmann
2022-07-19 12:49 ` Gregory Heytings
2022-07-19 13:16 ` Eli Zaretskii
2022-07-19 13:42 ` Gregory Heytings
2022-07-19 13:56 ` Eli Zaretskii
2022-07-19 14:06 ` Gregory Heytings
2022-07-19 14:15 ` Lars Ingebrigtsen
2022-07-19 14:24 ` Gregory Heytings
[not found] ` <364167b2-83e-c5af-1981-221d53e33ce6@heytings.org>
2022-07-19 21:55 ` Gregory Heytings
2022-07-19 14:19 ` Eli Zaretskii
2022-07-19 14:33 ` Gregory Heytings
2022-07-19 16:14 ` Eli Zaretskii
2022-07-19 21:40 ` Gregory Heytings
2022-07-20 12:07 ` Eli Zaretskii
2022-07-20 13:06 ` Gregory Heytings
2022-07-20 13:23 ` Eli Zaretskii
2022-07-20 13:42 ` Gregory Heytings
2022-07-20 15:54 ` Eli Zaretskii
2022-07-20 17:33 ` Gregory Heytings
2022-07-21 6:32 ` Eli Zaretskii
2022-07-21 7:39 ` Gregory Heytings
2022-07-21 7:49 ` Gregory Heytings
2022-07-21 8:00 ` Eli Zaretskii
2022-07-21 7:56 ` Eli Zaretskii
2022-07-21 8:20 ` Gregory Heytings
2022-07-21 8:58 ` Eli Zaretskii
2022-07-21 9:00 ` Gregory Heytings
2022-07-21 9:18 ` Lars Ingebrigtsen
2022-07-21 11:56 ` Gregory Heytings
2022-07-21 12:22 ` Eli Zaretskii
[not found] ` <bce7aad8-6872-97ec-77ac-6a593ff66a27@heytings.org>
2022-07-19 12:57 ` Gregory Heytings
2022-07-21 9:42 ` Eli Zaretskii
2022-07-08 5:47 ` Gerd Möllmann
2022-07-08 5:56 ` Eli Zaretskii
2022-07-08 6:25 ` Gerd Möllmann
2022-07-08 7:19 ` Eli Zaretskii
2022-07-07 18:38 ` Gregory Heytings
2022-07-08 5:59 ` Gerd Möllmann
2022-07-05 12:54 ` Eli Zaretskii
2022-07-05 13:53 ` Gregory Heytings
2022-07-05 14:14 ` Eli Zaretskii
2022-07-05 14:30 ` Gregory Heytings
2022-07-05 15:21 ` Robert Pluim
2022-07-05 15:46 ` Eli Zaretskii
2022-07-05 16:21 ` Gregory Heytings
2022-07-05 16:34 ` Eli Zaretskii
2022-07-05 23:09 ` Lars Ingebrigtsen
2022-07-05 23:12 ` Gregory Heytings
2022-07-06 12:29 ` Eli Zaretskii
2022-07-06 13:01 ` Gregory Heytings
2022-07-06 13:25 ` Eli Zaretskii
2022-07-06 13:56 ` Gregory Heytings
2022-07-06 14:09 ` Eli Zaretskii
2022-07-06 14:41 ` Gregory Heytings
2022-07-06 16:19 ` Eli Zaretskii
2022-07-06 16:57 ` Gregory Heytings
2022-07-06 17:50 ` Eli Zaretskii
2022-07-07 0:28 ` Ihor Radchenko
2022-07-07 5:43 ` Eli Zaretskii
2022-07-07 0:38 ` Gregory Heytings
2022-07-07 5:53 ` Eli Zaretskii
2022-07-07 8:23 ` Gregory Heytings
2022-07-07 10:10 ` Eli Zaretskii
2022-07-07 18:08 ` Gregory Heytings
2022-07-09 6:20 ` Eli Zaretskii
2022-07-09 8:24 ` Gregory Heytings
2022-07-09 9:13 ` Eli Zaretskii
2022-07-09 9:39 ` Gregory Heytings
2022-07-09 9:59 ` Eli Zaretskii
2022-07-09 10:20 ` Gregory Heytings
2022-07-09 10:41 ` Eli Zaretskii
2022-07-09 11:09 ` Gregory Heytings
2022-07-09 11:18 ` Eli Zaretskii
2022-07-09 11:38 ` Gregory Heytings
2022-07-09 11:48 ` Eli Zaretskii
2022-07-09 12:01 ` Gregory Heytings
2022-07-09 12:24 ` Eli Zaretskii
2022-07-09 12:31 ` Gregory Heytings
2022-07-07 14:25 ` Drew Adams
2022-07-07 15:58 ` Eli Zaretskii
2022-07-07 17:50 ` Eli Zaretskii
2022-07-07 18:46 ` Gregory Heytings
2022-07-07 19:05 ` Eli Zaretskii
2022-07-07 18:49 ` Gregory Heytings
2022-07-06 13:34 ` Stefan Kangas
2022-07-06 14:10 ` Gregory Heytings
2022-07-06 14:37 ` Stefan Kangas
2022-07-06 14:47 ` Gregory Heytings
2022-07-06 15:03 ` Stefan Kangas
2022-07-06 15:31 ` Gregory Heytings
2022-07-06 15:50 ` Eli Zaretskii
2022-07-05 23:10 ` Gregory Heytings
2022-07-06 9:49 ` Gerd Möllmann
2022-07-06 10:21 ` Gregory Heytings
2022-07-06 11:31 ` Lars Ingebrigtsen
2022-07-06 12:13 ` Gregory Heytings
2022-07-06 12:44 ` Gregory Heytings
2022-07-07 7:48 ` Lars Ingebrigtsen
2022-07-06 12:50 ` Eli Zaretskii
2022-07-06 13:16 ` Phil Sainty
2022-07-06 13:45 ` Gregory Heytings
2022-07-06 14:05 ` Phil Sainty
2022-07-06 12:39 ` Eli Zaretskii
2022-07-06 13:06 ` Gregory Heytings
2022-07-06 13:32 ` Eli Zaretskii
2022-07-06 14:05 ` Gregory Heytings
2022-07-06 14:13 ` Eli Zaretskii
2022-07-06 14:27 ` Gregory Heytings
2022-07-06 16:53 ` Eli Zaretskii
2022-07-06 17:17 ` Gregory Heytings
2022-07-06 17:30 ` Eli Zaretskii
2022-07-06 21:53 ` Gregory Heytings
2022-07-07 7:47 ` Lars Ingebrigtsen
2022-07-18 9:44 ` bug#56393: Soon also looking at your branch Gerd Möllmann
2022-07-18 10:11 ` Michael Albinus
2022-07-18 10:26 ` Gerd Möllmann
2022-07-18 11:43 ` Michael Albinus
2022-07-18 12:15 ` Gerd Möllmann
2022-07-18 12:19 ` Michael Albinus
2022-07-18 10:49 ` Gregory Heytings
2022-07-19 8:21 ` bug#56393: Actually fix the long lines display bug Gerd Möllmann
2022-07-19 8:53 ` Gregory Heytings
2022-07-19 8:58 ` Gregory Heytings
2022-07-19 9:31 ` bug#56393: Resetting long_line_optimization_p to 0 Gerd Möllmann
2022-07-19 9:51 ` Gregory Heytings
2022-07-19 11:20 ` Gerd Möllmann
2022-07-20 6:58 ` bug#56393: Actually fix the long lines display bug Gerd Möllmann
2022-07-20 9:13 ` Gregory Heytings
2022-07-19 12:21 ` Eli Zaretskii
2022-07-19 9:17 ` bug#56393: Auto narrowing autside of redisplay Gerd Möllmann
2022-07-19 9:51 ` Gregory Heytings
2022-07-19 10:56 ` bug#56393: Actually fix the long lines display bug Gerd Möllmann
2022-07-19 9:25 ` bug#56393: Turn on narrowing in redisplay_window Gerd Möllmann
2022-07-19 9:52 ` Gregory Heytings
2022-07-19 11:26 ` Gerd Möllmann
2022-07-19 12:43 ` Eli Zaretskii
2022-07-20 6:30 ` bug#56393: Actually fix the long lines display bug Gerd Möllmann
2022-07-20 9:08 ` Gregory Heytings
2022-07-19 12:48 ` Eli Zaretskii
2022-07-20 6:32 ` Gerd Möllmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=38c1a310405bd4bbe370@heytings.org \
--to=gregory@heytings.org \
--cc=56393@debbugs.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.