unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#56393: Actually fix the long lines display bug
@ 2022-07-05  8:49 Gregory Heytings
  2022-07-05  9:28 ` Gregory Heytings
  2022-07-18  9:44 ` bug#56393: Soon also looking at your branch Gerd Möllmann
  0 siblings, 2 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-05  8:49 UTC (permalink / raw)
  To: 56393

[-- Attachment #1: Type: text/plain, Size: 15 bytes --]


Please review.

[-- 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: 46767 bytes --]

From fed107327ce38c5416ae52b70edd673d37e68695 Mon Sep 17 00:00:00 2001
From: Gregory Heytings <gregory@heytings.org>
Date: Tue, 5 Jul 2022 08:44:04 +0000
Subject: [PATCH] Actually fix the long lines display bug.

* 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/longlines.el      | 502 -----------------------------------------
 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 +-
 15 files changed, 228 insertions(+), 582 deletions(-)
 delete mode 100644 lisp/longlines.el

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/longlines.el
deleted file mode 100644
index a6cf93a039..0000000000
--- a/lisp/longlines.el
+++ /dev/null
@@ -1,502 +0,0 @@
-;;; longlines.el --- automatically wrap long lines   -*- lexical-binding: t; -*-
-
-;; Copyright (C) 2000-2001, 2004-2022 Free Software Foundation, Inc.
-
-;; Authors:    Kai Grossjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE>
-;;             Alex Schroeder <alex@gnu.org>
-;;             Chong Yidong <cyd@stupidchicken.com>
-;; Maintainer: emacs-devel@gnu.org
-;; Keywords: convenience, wp
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Some text editors save text files with long lines, and they
-;; automatically break these lines at whitespace, without actually
-;; inserting any newline characters.  When doing `M-q' in Emacs, you
-;; are inserting newline characters.  Longlines mode provides a file
-;; format which wraps the long lines when reading a file and unwraps
-;; the lines when saving the file.  It can also wrap and unwrap
-;; automatically as editing takes place.
-
-;; Special thanks to Rod Smith for many useful bug reports.
-
-;;; Code:
-;;; Options
-
-(defgroup longlines nil
-  "Automatic wrapping of long lines when loading files."
-  :group 'fill)
-
-(defcustom longlines-auto-wrap t
-  "Non-nil means long lines are automatically wrapped after each command.
-Otherwise, you can perform filling using `fill-paragraph' or
-`auto-fill-mode'.  In any case, the soft newlines will be removed
-when the file is saved to disk."
-  :type 'boolean)
-
-(defcustom longlines-wrap-follows-window-size nil
-  "Non-nil means wrapping and filling happen at the edge of the window.
-Otherwise, `fill-column' is used, regardless of the window size.  This
-does not work well when the buffer is displayed in multiple windows
-with differing widths.
-
-If the value is an integer, that specifies the distance from the
-right edge of the window at which wrapping occurs.  For any other
-non-nil value, wrapping occurs 2 characters from the right edge."
-  :type 'boolean)
-
-(defcustom longlines-show-hard-newlines nil
-  "Non-nil means each hard newline is marked on the screen.
-\(The variable `longlines-show-effect' controls what they look like.)
-You can also enable the display temporarily, using the command
-`longlines-show-hard-newlines'."
-  :type 'boolean)
-
-(defcustom longlines-show-effect (propertize "¶\n" 'face 'escape-glyph)
-  "A string to display when showing hard newlines.
-This is used when `longlines-show-hard-newlines' is on."
-  :type 'string)
-
-(defcustom longlines-breakpoint-chars " ;,|"
-  "A bag of separator chars for longlines."
-  :type 'string)
-
-;;; Internal variables
-
-(defvar longlines-wrap-beg nil)
-(defvar longlines-wrap-end nil)
-(defvar longlines-wrap-point nil)
-(defvar longlines-showing nil)
-(defvar longlines-decoded nil)
-
-(make-variable-buffer-local 'longlines-wrap-beg)
-(make-variable-buffer-local 'longlines-wrap-end)
-(make-variable-buffer-local 'longlines-wrap-point)
-(make-variable-buffer-local 'longlines-showing)
-(make-variable-buffer-local 'longlines-decoded)
-
-;;; Mode
-
-(defvar message-indent-citation-function)
-
-;;;###autoload
-(define-minor-mode longlines-mode
-  "Toggle Long Lines mode in this buffer.
-
-When Long Lines mode is enabled, long lines are wrapped if they
-extend beyond `fill-column'.  The soft newlines used for line
-wrapping will not show up when the text is yanked or saved to
-disk.
-
-If the variable `longlines-auto-wrap' is non-nil, lines are
-automatically wrapped whenever the buffer is changed.  You can
-always call `fill-paragraph' to fill individual paragraphs.
-
-If the variable `longlines-show-hard-newlines' is non-nil, hard
-newlines are indicated with a symbol."
-  :lighter " ll"
-  (if longlines-mode
-      ;; Turn on longlines mode
-      (progn
-        (use-hard-newlines 1 'never)
-        (set (make-local-variable 'require-final-newline) nil)
-        (add-to-list 'buffer-file-format 'longlines)
-        (add-hook 'change-major-mode-hook #'longlines-mode-off nil t)
-	(add-hook 'before-revert-hook #'longlines-before-revert-hook nil t)
-        (make-local-variable 'buffer-substring-filters)
-        (make-local-variable 'longlines-auto-wrap)
-	(set (make-local-variable 'isearch-search-fun-function)
-	     #'longlines-search-function)
-	(set (make-local-variable 'replace-search-function)
-	     #'longlines-search-forward)
-	(set (make-local-variable 'replace-re-search-function)
-	     #'longlines-re-search-forward)
-        (add-to-list 'buffer-substring-filters 'longlines-encode-string)
-        (when longlines-wrap-follows-window-size
-	  (let ((dw (if (and (integerp longlines-wrap-follows-window-size)
-			     (>= longlines-wrap-follows-window-size 0)
-			     (< longlines-wrap-follows-window-size
-				(window-width)))
-			longlines-wrap-follows-window-size
-		      2)))
-	    (set (make-local-variable 'fill-column)
-		 (- (window-width) dw)))
-          (add-hook 'window-configuration-change-hook
-                    #'longlines-window-change-function nil t))
-        (let ((buffer-undo-list t)
-              (inhibit-read-only t)
-	      (inhibit-modification-hooks t)
-              (mod (buffer-modified-p))
-	      buffer-file-name buffer-file-truename)
-          ;; Turning off undo is OK since (spaces + newlines) is
-          ;; conserved, except for a corner case in
-          ;; longlines-wrap-lines that we'll never encounter from here
-	  (save-restriction
-	    (widen)
-	    (unless longlines-decoded
-	      (longlines-decode-buffer)
-	      (setq longlines-decoded t))
-	    (longlines-wrap-region (point-min) (point-max)))
-          (set-buffer-modified-p mod))
-        (when (and longlines-show-hard-newlines
-                   (not longlines-showing))
-          (longlines-show-hard-newlines))
-
-	;; Hacks to make longlines play nice with various modes.
-	(cond ((eq major-mode 'mail-mode)
-	       (declare-function mail-indent-citation "sendmail" ())
-	       (add-hook 'mail-setup-hook #'longlines-decode-buffer nil t)
-	       (or mail-citation-hook
-		   (add-hook 'mail-citation-hook #'mail-indent-citation nil t))
-	       (add-hook 'mail-citation-hook #'longlines-decode-region nil t))
-	      ((eq major-mode 'message-mode)
-	       (add-hook 'message-setup-hook #'longlines-decode-buffer nil t)
-	       (make-local-variable 'message-indent-citation-function)
-	       (if (not (listp message-indent-citation-function))
-		   (setq message-indent-citation-function
-			 (list message-indent-citation-function)))
-	       (add-hook 'message-indent-citation-function
-			 #'longlines-decode-region t t)))
-
-	(add-hook 'after-change-functions #'longlines-after-change-function nil t)
-	(add-hook 'post-command-hook #'longlines-post-command-function nil t)
-        (when longlines-auto-wrap
-          (auto-fill-mode 0)))
-    ;; Turn off longlines mode
-    (setq buffer-file-format (delete 'longlines buffer-file-format))
-    (if longlines-showing
-        (longlines-unshow-hard-newlines))
-    (let ((buffer-undo-list t)
-	  (inhibit-modification-hooks t)
-          (inhibit-read-only t)
-	  buffer-file-name buffer-file-truename)
-      (if longlines-decoded
-	  (save-restriction
-	    (widen)
-	    (longlines-encode-region (point-min) (point-max))
-	    (setq longlines-decoded nil))))
-    (remove-hook 'change-major-mode-hook #'longlines-mode-off t)
-    (remove-hook 'after-change-functions #'longlines-after-change-function t)
-    (remove-hook 'post-command-hook #'longlines-post-command-function t)
-    (remove-hook 'before-revert-hook #'longlines-before-revert-hook t)
-    (remove-hook 'window-configuration-change-hook
-                 #'longlines-window-change-function t)
-    (when longlines-wrap-follows-window-size
-      (kill-local-variable 'fill-column))
-    (kill-local-variable 'isearch-search-fun-function)
-    (kill-local-variable 'replace-search-function)
-    (kill-local-variable 'replace-re-search-function)
-    (kill-local-variable 'require-final-newline)
-    (kill-local-variable 'buffer-substring-filters)
-    (kill-local-variable 'use-hard-newlines)))
-
-(defun longlines-mode-off ()
-  "Turn off longlines mode.
-This function exists to be called by `change-major-mode-hook' when the
-major mode changes."
-  (longlines-mode 0))
-
-;;; Showing the effect of hard newlines in the buffer
-
-(defun longlines-show-hard-newlines (&optional arg)
-  "Make hard newlines visible by adding a face.
-With optional argument ARG, make the hard newlines invisible again."
-  (interactive "P")
-    (if arg
-        (longlines-unshow-hard-newlines)
-      (setq longlines-showing t)
-      (longlines-show-region (point-min) (point-max))))
-
-(defun longlines-show-region (beg end)
-  "Make hard newlines between BEG and END visible."
-  (let* ((pmin (min beg end))
-         (pmax (max beg end))
-         (pos (text-property-not-all pmin pmax 'hard nil))
-	 (mod (buffer-modified-p))
-	 (buffer-undo-list t)
-	 (inhibit-read-only t)
-	 (inhibit-modification-hooks t)
-	 buffer-file-name buffer-file-truename)
-    (while pos
-      (put-text-property pos (1+ pos) 'display
-			 (copy-sequence longlines-show-effect))
-      (setq pos (text-property-not-all (1+ pos) pmax 'hard nil)))
-    (restore-buffer-modified-p mod)))
-
-(defun longlines-unshow-hard-newlines ()
-  "Make hard newlines invisible again."
-  (interactive)
-  (setq longlines-showing nil)
-  (let ((pos (text-property-not-all (point-min) (point-max) 'hard nil))
-	(mod (buffer-modified-p))
-	(buffer-undo-list t)
-	(inhibit-read-only t)
-	(inhibit-modification-hooks t)
-	buffer-file-name buffer-file-truename)
-    (while pos
-      (remove-text-properties pos (1+ pos) '(display nil))
-      (setq pos (text-property-not-all (1+ pos) (point-max) 'hard nil)))
-    (restore-buffer-modified-p mod)))
-
-;;; Wrapping the paragraphs
-
-(defun longlines-wrap-region (beg end)
-  "Wrap each successive line, starting with the line before BEG.
-Stop when we reach lines after END that don't need wrapping, or the
-end of the buffer."
-  (let ((mod (buffer-modified-p)))
-    (setq longlines-wrap-point (point))
-    (goto-char beg)
-    (forward-line -1)
-    ;; Two successful longlines-wrap-line's in a row mean successive
-    ;; lines don't need wrapping.
-    (while (null (and (longlines-wrap-line)
-		      (or (eobp)
-			  (and (>= (point) end)
-			       (longlines-wrap-line))))))
-    (goto-char longlines-wrap-point)
-    (set-buffer-modified-p mod)))
-
-(defun longlines-wrap-line ()
-  "If the current line needs to be wrapped, wrap it and return nil.
-If wrapping is performed, point remains on the line.  If the line does
-not need to be wrapped, move point to the next line and return t."
-  (if (longlines-set-breakpoint fill-column)
-      (progn (insert-before-markers-and-inherit ?\n)
-             nil)
-    (if (longlines-merge-lines-p)
-        (progn (end-of-line)
-     ;; After certain commands (e.g. kill-line), there may be two
-     ;; successive soft newlines in the buffer.  In this case, we
-     ;; replace these two newlines by a single space.  Unfortunately,
-     ;; this breaks the conservation of (spaces + newlines), so we
-     ;; have to fiddle with longlines-wrap-point.
-               (if (or (prog1 (bolp) (forward-char 1)) (eolp))
-	           (progn
-	             (delete-char -1)
-	             (if (> longlines-wrap-point (point))
-		         (setq longlines-wrap-point
-		               (1- longlines-wrap-point))))
-	         (delete-char -1))
-               nil)
-      (forward-line 1)
-      t)))
-
-(defun longlines-set-breakpoint (target-column)
-  "Place point where we should break the current line, and return t.
-If the line should not be broken, return nil; point remains on the
-line."
-  (move-to-column target-column)
-  (let ((non-breakpoint-re (format "[^%s]" longlines-breakpoint-chars)))
-    (if (and (re-search-forward non-breakpoint-re (line-end-position) t 1)
-             (> (current-column) target-column))
-        ;; This line is too long.  Can we break it?
-        (or (longlines-find-break-backward)
-            (progn (move-to-column target-column)
-                   (longlines-find-break-forward))))))
-
-(defun longlines-find-break-backward ()
-  "Move point backward to the first available breakpoint and return t.
-If no breakpoint is found, return nil."
-  (let ((breakpoint-re (format "[%s]" longlines-breakpoint-chars)))
-    (when (and (re-search-backward breakpoint-re (line-beginning-position) t 1)
-               (save-excursion
-                 (skip-chars-backward longlines-breakpoint-chars
-                                      (line-beginning-position))
-                 (null (bolp))))
-      (forward-char 1)
-      (if (and fill-nobreak-predicate
-               (run-hook-with-args-until-success 'fill-nobreak-predicate))
-          (progn
-            (skip-chars-backward longlines-breakpoint-chars
-                                 (line-beginning-position))
-            (longlines-find-break-backward))
-        t))))
-
-(defun longlines-find-break-forward ()
-  "Move point forward to the first available breakpoint and return t.
-If no break point is found, return nil."
-  (let ((breakpoint-re (format "[%s]" longlines-breakpoint-chars)))
-    (and (re-search-forward breakpoint-re (line-end-position) t 1)
-         (progn
-           (skip-chars-forward longlines-breakpoint-chars (line-end-position))
-           (null (eolp)))
-         (if (and fill-nobreak-predicate
-                  (run-hook-with-args-until-success 'fill-nobreak-predicate))
-             (longlines-find-break-forward)
-           t))))
-
-(defun longlines-merge-lines-p ()
-  "Return t if part of the next line can fit onto the current line.
-Otherwise, return nil.  Text cannot be moved across hard newlines."
-  (save-excursion
-    (end-of-line)
-    (and (null (eobp))
-         (null (get-text-property (point) 'hard))
-         (let ((space (- fill-column (current-column))))
-           (forward-line 1)
-           (longlines-set-breakpoint (max 0 (1- space)))))))
-
-(defun longlines-decode-region (&optional beg end)
-  "Turn all newlines between BEG and END into hard newlines.
-If BEG and END are nil, the point and mark are used."
-  (if (null beg) (setq beg (point)))
-  (if (null end) (setq end (mark t)))
-  (save-excursion
-    (let ((reg-max (max beg end)))
-      (goto-char (min beg end))
-      (while (search-forward "\n" reg-max t)
-	(set-hard-newline-properties
-	 (match-beginning 0) (match-end 0))))))
-
-(defun longlines-decode-buffer ()
-  "Turn all newlines in the buffer into hard newlines."
-  (longlines-decode-region (point-min) (point-max)))
-
-(defun longlines-encode-region (beg end &optional _buffer)
-  "Remove each soft newline between BEG and END.
-Hard newlines are left intact.  The optional argument BUFFER exists for
-compatibility with `format-alist', and is ignored."
-  (save-excursion
-    (let ((reg-max (max beg end))
-	  (mod (buffer-modified-p)))
-      (goto-char (min beg end))
-      (while (search-forward "\n" reg-max t)
-	(let ((pos (match-beginning 0)))
-	  (unless (get-text-property pos 'hard)
-            (remove-text-properties pos (1+ pos) '(hard nil))
-            (delete-region pos (1+ pos)))))
-      (set-buffer-modified-p mod)
-      end)))
-
-(defun longlines-encode-string (string)
-  "Return a copy of STRING with each soft newline replaced by a space.
-Hard newlines are left intact."
-  (let* ((str (copy-sequence string))
-         (pos (string-search "\n" str)))
-    (while pos
-      (if (null (get-text-property pos 'hard str))
-          (aset str pos ? ))
-      (setq pos (string-search "\n" str (1+ pos))))
-    str))
-
-;;; Auto wrap
-
-(defun longlines-auto-wrap (&optional arg)
-  "Toggle automatic line wrapping.
-With optional argument ARG, turn on line wrapping if and only if
-ARG is positive.
-If automatic line wrapping is turned on, wrap the entire buffer."
-  (interactive "P")
-  (setq arg (if arg
-		(> (prefix-numeric-value arg) 0)
-	      (not longlines-auto-wrap)))
-  (if arg
-      (progn
-	(setq longlines-auto-wrap t)
-	(longlines-wrap-region (point-min) (point-max))
-	(message "Auto wrap enabled."))
-    (setq longlines-auto-wrap nil)
-    (message "Auto wrap disabled.")))
-
-(defun longlines-after-change-function (beg end _len)
-  "Update `longlines-wrap-beg' and `longlines-wrap-end'.
-This is called by `after-change-functions' to keep track of the region
-that has changed."
-  (when (and longlines-auto-wrap (not undo-in-progress))
-    (setq longlines-wrap-beg
-          (if longlines-wrap-beg (min longlines-wrap-beg beg) beg))
-    (setq longlines-wrap-end
-          (if longlines-wrap-end (max longlines-wrap-end end) end))))
-
-(defun longlines-post-command-function ()
-  "Perform line wrapping on the parts of the buffer that have changed.
-This is called by `post-command-hook' after each command."
-  (when (and longlines-auto-wrap longlines-wrap-beg)
-    (if (or (eq this-command 'yank)
-	    (eq this-command 'yank-pop))
-	(longlines-decode-region (point) (mark t)))
-    (if longlines-showing
-	(longlines-show-region longlines-wrap-beg longlines-wrap-end))
-    (unless (or (eq this-command 'fill-paragraph)
-                (eq this-command 'fill-region))
-      (longlines-wrap-region longlines-wrap-beg longlines-wrap-end))
-    (setq longlines-wrap-beg nil)
-    (setq longlines-wrap-end nil)))
-
-(defun longlines-window-change-function ()
-  "Re-wrap the buffer if the window width has changed.
-This is called by `window-configuration-change-hook'."
-  (let ((dw (if (and (integerp longlines-wrap-follows-window-size)
-		     (>= longlines-wrap-follows-window-size 0)
-		     (< longlines-wrap-follows-window-size (window-width)))
-		longlines-wrap-follows-window-size
-	      2)))
-    (when (/= fill-column (- (window-width) dw))
-      (setq fill-column (- (window-width) dw))
-      (longlines-wrap-region (point-min) (point-max)))))
-
-;;; Isearch
-
-(defun longlines-search-function ()
-  (cond
-   ((or isearch-regexp-function isearch-regexp) (isearch-search-fun-default))
-   (isearch-forward #'longlines-search-forward)
-   (t #'longlines-search-backward)))
-
-(defun longlines-search-forward (string &optional bound noerror count)
-  (let ((search-spaces-regexp " *[ \n]"))
-    (re-search-forward (regexp-quote string) bound noerror count)))
-
-(defun longlines-search-backward (string &optional bound noerror count)
-  (let ((search-spaces-regexp " *[ \n]"))
-    (re-search-backward (regexp-quote string) bound noerror count)))
-
-(defun longlines-re-search-forward (string &optional bound noerror count)
-  (let ((search-spaces-regexp " *[ \n]"))
-    (re-search-forward string bound noerror count)))
-
-;;; Loading and saving
-
-(defun longlines-before-revert-hook ()
-  (add-hook 'after-revert-hook #'longlines-after-revert-hook nil t)
-  (longlines-mode 0))
-
-(defun longlines-after-revert-hook ()
-  (remove-hook 'after-revert-hook #'longlines-after-revert-hook t)
-  (longlines-mode 1))
-
-(add-to-list
- 'format-alist
- (list 'longlines "Automatically wrap long lines." nil nil
-       #'longlines-encode-region t nil))
-
-;;; Unloading
-
-(defun longlines-unload-function ()
-  "Unload the longlines library."
-  (save-current-buffer
-    (dolist (buffer (buffer-list))
-      (set-buffer buffer)
-      (longlines-mode-off)))
-  ;; continue standard unloading
-  nil)
-
-(provide 'longlines)
-
-;;; longlines.el ends here
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


^ permalink raw reply related	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-05  8:49 bug#56393: Actually fix the long lines display bug Gregory Heytings
@ 2022-07-05  9:28 ` Gregory Heytings
  2022-07-05  9:58   ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2022-07-18  9:44 ` bug#56393: Soon also looking at your branch Gerd Möllmann
  1 sibling, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-05  9:28 UTC (permalink / raw)
  To: 56393

[-- 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


^ permalink raw reply related	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-05  9:28 ` Gregory Heytings
@ 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
  0 siblings, 1 reply; 205+ messages in thread
From: Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-07-05  9:58 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: 56393

Gregory Heytings <gregory@heytings.org> writes:

> Sorry, something was missing in the previous patch, here is the
> complete one, with a bug number.

This one seems to include the last change to x-dnd.el.






^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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:54       ` Eli Zaretskii
  0 siblings, 2 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-05 10:17 UTC (permalink / raw)
  To: 56393

[-- Attachment #1: Type: text/plain, Size: 158 bytes --]


>
> This one seems to include the last change to x-dnd.el.
>

Gosh!  After including too little, I included too much.  The attached one 
is correct (I hope).

[-- 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: 26758 bytes --]

From 55cdec5d60025451826dae21c20d1e61244bc6aa Mon Sep 17 00:00:00 2001
From: Gregory Heytings <gregory@heytings.org>
Date: Tue, 5 Jul 2022 10:14:24 +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 +
 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 ++-
 15 files changed, 229 insertions(+), 80 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/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


^ permalink raw reply related	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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:54       ` Eli Zaretskii
  1 sibling, 1 reply; 205+ messages in thread
From: Lars Ingebrigtsen @ 2022-07-05 11:24 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: 56393

Gregory Heytings <gregory@heytings.org> writes:

> +  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.

Oh, that's an interesting approach.  I haven't tried your patch, but it
sounds like it'd do the trick.

> +      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);

You could also use Fbuffer_line_statistics here, which I think should be
faster.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-05 11:24       ` Lars Ingebrigtsen
@ 2022-07-05 12:16         ` Gregory Heytings
  2022-07-05 12:59           ` Gerd Möllmann
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-05 12:16 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: 56393

[-- Attachment #1: Type: text/plain, Size: 263 bytes --]


>
> I haven't tried your patch, but it sounds like it'd do the trick.
>

It does indeed, even with a 1GB long line.

>
> You could also use Fbuffer_line_statistics here, which I think should be 
> faster.
>

Thanks, this simplifies the patch a bit, see attached.

[-- Attachment #2: Actually-fix-the-long-lines-display-bug.patch --]
[-- Type: text/x-diff, Size: 25209 bytes --]

From fbda3883e067c274d82e5a1a9b1dc4189cc05767 Mon Sep 17 00:00:00 2001
From: Gregory Heytings <gregory@heytings.org>
Date: Tue, 5 Jul 2022 12:07:07 +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/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 +
 src/buffer.c                     |  5 ++
 src/buffer.h                     |  3 ++
 src/fileio.c                     | 22 ++++++++
 src/keyboard.c                   | 28 ++++++++++
 src/xdisp.c                      |  7 ++-
 13 files changed, 223 insertions(+), 79 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/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..e6c51da0d9 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -4997,6 +4997,17 @@ 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)
+	  && !NILP (CALLN
+		    (Fgtr,
+		     Fcar (Fcdr (Fbuffer_line_statistics (Fcurrent_buffer ()))),
+		     Vauto_narrow_long_line_threshold)))
+	{
+	  safe_call (1, Qauto_narrow_mode);
+	  message1 ("Auto-Narrow mode enabled in current buffer");
+	}
+
       unbind_to (count1, Qnil);
     }
 
@@ -6638,6 +6649,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/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


^ permalink raw reply related	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-05 10:17     ` Gregory Heytings
  2022-07-05 11:24       ` Lars Ingebrigtsen
@ 2022-07-05 12:54       ` Eli Zaretskii
  2022-07-05 13:53         ` Gregory Heytings
  1 sibling, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-05 12:54 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: 56393

> Date: Tue, 05 Jul 2022 10:17:37 +0000
> From: Gregory Heytings <gregory@heytings.org>
> 
> Gosh!  After including too little, I included too much.  The attached one 
> is correct (I hope).

Thanks!  It's a good idea, but I wonder how far we can safely take it;
see below.

> 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

This removal is premature, IMO.  We should first establish that this
feature can indeed cope well enough with the important use cases, and
I'm not sure we are there yet.  It is possible that this feature will
be one of several available features that attempt to solve the same
problem in different ways, each way with its own advantages and
disadvantages.

> --- 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.
> -

Likewise here.

> +** Emacs is now capable of editing files with arbitarily long lines.

I'd suggest saying something like

  Emacs now copes better with editing files with extremely long lines.

> +(defcustom auto-narrow-display-length 30000
> +  "Number of characters to which display is restricted in `auto-narrow-mode'."

This should tell how the narrowed region is positioned relative to
point, I think, because without it the doc string tells too little.

> +(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'."

What are the criteria for this default?  (I'm surprised the list is so
short, for the reasons I explain below.)

> +(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)

We might eventually decide to have this turned off by default.

> --- 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);
> +	}
> +

This will invoke auto-narrow-mode for any file that is for some reason
inserted by Emacs into some buffer.  Many Emacs commands insert files
into temporary buffers or buffers that are never meant for display,
and AFAIU the above will narrow such a buffer if a file inserted
happens to have long lines, is that correct?  If so, a Lisp program
that inserts such a file, and then processes it, might fail to do its
job because it will bump into the auto-narrowed restriction.  I think
this is a symptom of a larger problem with this approach; more about
it below.

> +  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.  */);
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  "When nil, `auto-narrow-mode' is disabled."

> --- 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.  */
> [...]
> @@ -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);

AFAIU, this means post-command-hook functions will run with the
current buffer narrowed, right?  That could cause them to fail, if
they for some reason want to access the buffer portions outside the
restriction.

> @@ -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);
> +

And here's a similar problem with pre-command-hook functions.

A similar problem will happen with any Lisp that is run from the
redisplay code: it will only see the narrowed region.

I don't quite see clearly what these general issues could mean, but
they are at least worrisome, I think, because they could potentially
mean significant breakage in many places.  The simple measure of
having a list of commands that automatically widen the buffer is
insufficient, I'm afraid, because the real problem is not on the
command level, it is on the level of Lisp programs which say
save-excursion and then go far away for whatever purposes.  Also for
commands written by users: for example, if someone writes a command
that is a trivial wrapper around goto-line, that command will no
longer automatically widen as goto-line does, right?

Can we come up with a better solution for these potential problems?
Alternatively, maybe you will explain that I'm bothered by a
non-existent problem?

Other observations:

Since the narrowing is basically in effect only during redisplay, it
doesn't help with commands that use display code outside of redisplay
proper.  For example, C-n, C-v, C-l, and other commands are still
extremely sluggish in files with long lines.  E.g., try the file
long-line.xml mentioned here:

  https://debbugs.gnu.org/cgi/bugreport.cgi?bug=45898#80

Or try dragging the mode line of a window showing that file.

Also, the automatic restriction is very visible and causes surprising
effects: (point-min) and (point-max) evaluate to the narrowed region
(so it's basically very hard to know the real size of the buffer), and
scrolling through the buffer causes the scroll-bar thumb move in a
non-monotonic manner: I scroll towards the end of the buffer, but the
thumb sometimes jumps back up, as if I moved towards the beginning.

And sometimes I see that C-n moves point horizontally, i.e. point
stays on the same screen line, instead of the expected vertical
movement.  I guess this is because the restriction violates some
assumptions that Emacs makes regarding horizontal coordinates of some
reference position.

I think at this point it is best to have this feature on a feature
branch, so that people could try it, and so that improving it won't
need to post the entire patch each time anew.

Thanks.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-05 12:16         ` Gregory Heytings
@ 2022-07-05 12:59           ` Gerd Möllmann
  2022-07-07 11:29             ` Gerd Möllmann
  0 siblings, 1 reply; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-05 12:59 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: Lars Ingebrigtsen, 56393

Gregory Heytings <gregory@heytings.org> writes:

>>
>> I haven't tried your patch, but it sounds like it'd do the trick.
>>
>
> It does indeed, even with a 1GB long line.
>
>>
>> You could also use Fbuffer_line_statistics here, which I think
>> should be faster.
>>
>
> Thanks, this simplifies the patch a bit, see attached.

This is very nice, indeed.  I'll take a closer look at your patch in the
next days.  (I'm currently still in the process of getting Emacs to
better integrate with my M1 Mac, and it's kicking and screaming :-).)





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-05 12:54       ` Eli Zaretskii
@ 2022-07-05 13:53         ` Gregory Heytings
  2022-07-05 14:14           ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-05 13:53 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 56393


Thanks for your review; some comments below.

>
> This removal is premature, IMO.  We should first establish that this 
> feature can indeed cope well enough with the important use cases, and 
> I'm not sure we are there yet.  It is possible that this feature will be 
> one of several available features that attempt to solve the same problem 
> in different ways, each way with its own advantages and disadvantages.
>

AFAICS, this patch properly solves the problem indicated in that section. 
So I don't see why it should be kept.

>> -** 'longlines-mode' is no longer obsolete.
>
> Likewise here.
>

This mode was unobsoleted a few days ago, because the conclusion was that 
there was no better mechanism available to cope with large files.  Now 
there is.

>> +** Emacs is now capable of editing files with arbitarily long lines.
>
> I'd suggest saying something like
>
> Emacs now copes better with editing files with extremely long lines.
>

As I just said to Lars, Emacs can now handle files with 1GB long lines 
just fine, as if it were a small file.  I used

for I in $(seq 1 60); do cat dictionary.json; done > hugedictionary.json

So I think this title is appropriate.

>> +(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'."
>
> What are the criteria for this default?  (I'm surprised the list is so 
> short, for the reasons I explain below.)
>

The review I asked was in particular meant to add commands in these 
defaults.  I reviewed all ordinary editing commands, but I may have missed 
some of them.  Please tell me which command you'd like to add in that 
list.  (Also note that isearch commands are handled with their own 
mechanism.)

>> +(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)
>
> We might eventually decide to have this turned off by default.
>

Sorry, but no.

>
> This will invoke auto-narrow-mode for any file that is for some reason 
> inserted by Emacs into some buffer.  Many Emacs commands insert files 
> into temporary buffers or buffers that are never meant for display, and 
> AFAIU the above will narrow such a buffer if a file inserted happens to 
> have long lines, is that correct?
>

It might, everything is possible with software.  Let's see if it happens 
in practice and take the appropriate measure if it happens.  And the cure 
for these potential cases is easy: (let ((auto-narrow-long-line-threshold 
nil)) ...)

>
> I don't quite see clearly what these general issues could mean, but they 
> are at least worrisome, I think, because they could potentially mean 
> significant breakage in many places.
>

Again, let's see if it happens in practice and take the appropriate 
measure if it actually happens.

>
> Also for commands written by users: for example, if someone writes a 
> command that is a trivial wrapper around goto-line, that command will no 
> longer automatically widen as goto-line does, right?
>

Indeed, that's the purpose of the auto-narrow-widen-automatically 
defcustom: users can easily add their own commands to that list.

>
> Alternatively, maybe you will explain that I'm bothered by a 
> non-existent problem?
>

What I think is that you are bothered with a potential problem which is 
far less important than seeing Emacs becoming unresponsive.

>
> Since the narrowing is basically in effect only during redisplay, it 
> doesn't help with commands that use display code outside of redisplay 
> proper.  For example, C-n, C-v, C-l, and other commands are still 
> extremely sluggish in files with long lines.  E.g., try the file 
> long-line.xml mentioned here:
>
> https://debbugs.gnu.org/cgi/bugreport.cgi?bug=45898#80
>

Did you actually try the patch?  This is (one of) the files I used while 
designing this code, and navigation commands work perfectly well (on a 
seven year old laptop).  In that particular XML file, you can turn off 
font-lock-mode to make navigation even faster (instantaneous).

>
> Also, the automatic restriction is very visible and causes surprising 
> effects: (point-min) and (point-max) evaluate to the narrowed region (so 
> it's basically very hard to know the real size of the buffer), and 
> scrolling through the buffer causes the scroll-bar thumb move in a 
> non-monotonic manner: I scroll towards the end of the buffer, but the 
> thumb sometimes jumps back up, as if I moved towards the beginning.
>

Indeed.  Users will see the "Auto-Narrow" indication in the modeline with 
which they can easily find an explanation for that behavior.  If this 
behavior is problematic, it could be fixed by using the dimensions of the 
whole buffer when updating the scroll bar (and perhaps also the modeline), 
when auto-narrow-mode is active.

>
> I think at this point it is best to have this feature on a feature 
> branch, so that people could try it, and so that improving it won't need 
> to post the entire patch each time anew.
>

Okay, will do.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-05 13:53         ` Gregory Heytings
@ 2022-07-05 14:14           ` Eli Zaretskii
  2022-07-05 14:30             ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-05 14:14 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: 56393

> Date: Tue, 05 Jul 2022 13:53:36 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: 56393@debbugs.gnu.org
> 
> >> -** 'longlines-mode' is no longer obsolete.
> >
> > Likewise here.
> >
> 
> This mode was unobsoleted a few days ago, because the conclusion was that 
> there was no better mechanism available to cope with large files.  Now 
> there is.

Well, the cursor motion problems I mentioned? longlines doesn't have
them.

> > This will invoke auto-narrow-mode for any file that is for some reason 
> > inserted by Emacs into some buffer.  Many Emacs commands insert files 
> > into temporary buffers or buffers that are never meant for display, and 
> > AFAIU the above will narrow such a buffer if a file inserted happens to 
> > have long lines, is that correct?
> 
> It might, everything is possible with software.  Let's see if it happens 
> in practice and take the appropriate measure if it happens.

I did try this, and it does happen.  Here:

  (with-temp-buffer
    (insert-file-contents "long-line.xml")
    (point-max))

(where long-line.xml is the file whose URL I've shown in my message).
This gives me 30001, whereas the correct value is 306666.

> And the cure for these potential cases is easy: (let
> ((auto-narrow-long-line-threshold nil)) ...)

Where do you suggest doing this?

> > I don't quite see clearly what these general issues could mean, but they 
> > are at least worrisome, I think, because they could potentially mean 
> > significant breakage in many places.
> >
> 
> Again, let's see if it happens in practice and take the appropriate 
> measure if it actually happens.

See above.  I think it will happen quite a lot in the wild.

> > Also for commands written by users: for example, if someone writes a 
> > command that is a trivial wrapper around goto-line, that command will no 
> > longer automatically widen as goto-line does, right?
> 
> Indeed, that's the purpose of the auto-narrow-widen-automatically 
> defcustom: users can easily add their own commands to that list.

That means the list will be very long and users will have to
constantly update it.  E.g., whenever they install a new package or
even a new version of a package.

> > Alternatively, maybe you will explain that I'm bothered by a 
> > non-existent problem?
> 
> What I think is that you are bothered with a potential problem which is 
> far less important than seeing Emacs becoming unresponsive.

I'm not sure.  A broken command might be important, especially if this
feature is going to be on by default.

> > Since the narrowing is basically in effect only during redisplay, it 
> > doesn't help with commands that use display code outside of redisplay 
> > proper.  For example, C-n, C-v, C-l, and other commands are still 
> > extremely sluggish in files with long lines.  E.g., try the file 
> > long-line.xml mentioned here:
> >
> > https://debbugs.gnu.org/cgi/bugreport.cgi?bug=45898#80
> 
> Did you actually try the patch?

Yes.

> > Also, the automatic restriction is very visible and causes surprising 
> > effects: (point-min) and (point-max) evaluate to the narrowed region (so 
> > it's basically very hard to know the real size of the buffer), and 
> > scrolling through the buffer causes the scroll-bar thumb move in a 
> > non-monotonic manner: I scroll towards the end of the buffer, but the 
> > thumb sometimes jumps back up, as if I moved towards the beginning.
> 
> Indeed.  Users will see the "Auto-Narrow" indication in the modeline with 
> which they can easily find an explanation for that behavior.  If this 
> behavior is problematic, it could be fixed by using the dimensions of the 
> whole buffer when updating the scroll bar (and perhaps also the modeline), 
> when auto-narrow-mode is active.

I think it should be fixed, yes.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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
  0 siblings, 2 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-05 14:30 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 56393


>
> I did try this, and it does happen.  Here:
>
>  (with-temp-buffer
>    (insert-file-contents "long-line.xml")
>    (point-max))
>
> (where long-line.xml is the file whose URL I've shown in my message). 
> This gives me 30001, whereas the correct value is 306666.
>

That's of course not what I meant with "in practice".  What I meant is: 
are there actual uses of "(with-temp-buffer (insert-file-contents ..." 
which insert actual files with sufficiently long lines?  Such files are 
not so common.  As I said, if that's the case, it's easy to add a "(let 
((auto-narrow-long-line-threshold nil))" around the code, in this case 
either in the with-temp-buffer macro or in the code above.

>
> I think it will happen quite a lot in the wild.
>

Let's see if it does before reaching a conclusion.

>
> That means the list will be very long and users will have to constantly 
> update it.  E.g., whenever they install a new package or even a new 
> version of a package.
>

Packages can take care of this by themselves, can't they?  When the 
package is loaded, (add-to-list auto-narrow-widen-automatically 
the-package-command).

>>> Also, the automatic restriction is very visible and causes surprising 
>>> effects: (point-min) and (point-max) evaluate to the narrowed region 
>>> (so it's basically very hard to know the real size of the buffer), and 
>>> scrolling through the buffer causes the scroll-bar thumb move in a 
>>> non-monotonic manner: I scroll towards the end of the buffer, but the 
>>> thumb sometimes jumps back up, as if I moved towards the beginning.
>>
>> Indeed.  Users will see the "Auto-Narrow" indication in the modeline 
>> with which they can easily find an explanation for that behavior.  If 
>> this behavior is problematic, it could be fixed by using the dimensions 
>> of the whole buffer when updating the scroll bar (and perhaps also the 
>> modeline), when auto-narrow-mode is active.
>
> I think it should be fixed, yes.
>

Okay, I'll see what I can do.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-05 14:30             ` Gregory Heytings
@ 2022-07-05 15:21               ` Robert Pluim
  2022-07-05 15:46               ` Eli Zaretskii
  1 sibling, 0 replies; 205+ messages in thread
From: Robert Pluim @ 2022-07-05 15:21 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: Eli Zaretskii, 56393

>>>>> On Tue, 05 Jul 2022 14:30:08 +0000, Gregory Heytings <gregory@heytings.org> said:

    >> 
    >> I did try this, and it does happen.  Here:
    >> 
    >> (with-temp-buffer
    >> (insert-file-contents "long-line.xml")
    >> (point-max))
    >> 
    >> (where long-line.xml is the file whose URL I've shown in my
    >> message). This gives me 30001, whereas the correct value is 306666.
    >> 

    Gregory> That's of course not what I meant with "in practice".  What I meant
    Gregory> is: are there actual uses of "(with-temp-buffer (insert-file-contents
    Gregory> ..." which insert actual files with sufficiently long lines?  Such
    Gregory> files are not so common.  As I said, if that's the case, it's easy to
    Gregory> add a "(let ((auto-narrow-long-line-threshold nil))" around the code,
    Gregory> in this case either in the with-temp-buffer macro or in the code
    Gregory> above.

.newsrc.eld can have very long lines (mine is 2.7M, for only 21
lines). You break Gnus weʼll be coming for you with pitchforks 🙂
(although I think gnus uses `read', not `insert-file-contents')

Robert
-- 





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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
  1 sibling, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-05 15:46 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: 56393

> Date: Tue, 05 Jul 2022 14:30:08 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: 56393@debbugs.gnu.org
> 
> 
> >  (with-temp-buffer
> >    (insert-file-contents "long-line.xml")
> >    (point-max))
> >
> > (where long-line.xml is the file whose URL I've shown in my message). 
> > This gives me 30001, whereas the correct value is 306666.
> >
> 
> That's of course not what I meant with "in practice".  What I meant is: 
> are there actual uses of "(with-temp-buffer (insert-file-contents ..." 
> which insert actual files with sufficiently long lines?  Such files are 
> not so common.

JSON files are quite frequently like that, for example.  (One of the
files mentioned in bug#45898 is such a file.)

> As I said, if that's the case, it's easy to add a "(let
> ((auto-narrow-long-line-threshold nil))" around the code, in this
> case either in the with-temp-buffer macro or in the code above.

These macros are called a lot, and I don't think it's a good idea to
tell all their callers to make such changes.

> > That means the list will be very long and users will have to constantly 
> > update it.  E.g., whenever they install a new package or even a new 
> > version of a package.
> 
> Packages can take care of this by themselves, can't they?  When the 
> package is loaded, (add-to-list auto-narrow-widen-automatically 
> the-package-command).

I don't like this.  And neither will package maintainers, I think.

I think we should try to work out a solution that only affects the C
code in the display engine, such that any Lisp called from the various
hooks and places in display code is not affected, and neither are
pre-command-hook and post-command-hook.  That should have almost the
same effect, performance-wise, but be much safer than the automatic
narrowing that affects everything in Emacs as long as the narrowing is
in effect.

IOW, replace all BEGV and ZV in display code with a couple of new
macros, which effectively "narrow" the buffer, as far as the display
engine is concerned.  Then set the limits of this restriction in
redisplay_window, and remove it when the window's redisplay is done.
Or something along these lines.

> >>> Also, the automatic restriction is very visible and causes surprising 
> >>> effects: (point-min) and (point-max) evaluate to the narrowed region 
> >>> (so it's basically very hard to know the real size of the buffer), and 
> >>> scrolling through the buffer causes the scroll-bar thumb move in a 
> >>> non-monotonic manner: I scroll towards the end of the buffer, but the 
> >>> thumb sometimes jumps back up, as if I moved towards the beginning.
> >>
> >> Indeed.  Users will see the "Auto-Narrow" indication in the modeline 
> >> with which they can easily find an explanation for that behavior.  If 
> >> this behavior is problematic, it could be fixed by using the dimensions 
> >> of the whole buffer when updating the scroll bar (and perhaps also the 
> >> modeline), when auto-narrow-mode is active.
> >
> > I think it should be fixed, yes.
> >
> 
> Okay, I'll see what I can do.

Thanks.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-05 15:46               ` Eli Zaretskii
@ 2022-07-05 16:21                 ` Gregory Heytings
  2022-07-05 16:34                   ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-05 16:21 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 56393


>> As I said, if that's the case, it's easy to add a "(let 
>> ((auto-narrow-long-line-threshold nil))" around the code, in this case 
>> either in the with-temp-buffer macro or in the code above.
>
> These macros are called a lot, and I don't think it's a good idea to 
> tell all their callers to make such changes.
>

As I said, this can also be done inside the with-temp-buffer macro.  A 
(very quick) review of calls to insert-file-contents in Emacs core and 
ELPA tells me that that the majority of these calls are inside a 
with-temp-buffer or with-current-buffer (with a temporary buffer).

>
> I think we should try to work out a solution that only affects the C 
> code in the display engine, such that any Lisp called from the various 
> hooks and places in display code is not affected, and neither are 
> pre-command-hook and post-command-hook.  That should have almost the 
> same effect, performance-wise, but be much safer than the automatic 
> narrowing that affects everything in Emacs as long as the narrowing is 
> in effect.
>
> IOW, replace all BEGV and ZV in display code with a couple of new 
> macros, which effectively "narrow" the buffer, as far as the display 
> engine is concerned.  Then set the limits of this restriction in 
> redisplay_window, and remove it when the window's redisplay is done. Or 
> something along these lines.
>

I guess this means, in essence, to throw away the patch?  Or do I 
interpret what you wrote too negatively?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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:10                     ` Gregory Heytings
  0 siblings, 2 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-05 16:34 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: 56393

> Date: Tue, 05 Jul 2022 16:21:57 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: 56393@debbugs.gnu.org
> 
> 
> >> As I said, if that's the case, it's easy to add a "(let 
> >> ((auto-narrow-long-line-threshold nil))" around the code, in this case 
> >> either in the with-temp-buffer macro or in the code above.
> >
> > These macros are called a lot, and I don't think it's a good idea to 
> > tell all their callers to make such changes.
> >
> 
> As I said, this can also be done inside the with-temp-buffer macro.  A 
> (very quick) review of calls to insert-file-contents in Emacs core and 
> ELPA tells me that that the majority of these calls are inside a 
> with-temp-buffer or with-current-buffer (with a temporary buffer).

with-current-buffer can be legitimately called to insert stuff into a
buffer that is displayed.  The macro doesn't know.

> > I think we should try to work out a solution that only affects the C 
> > code in the display engine, such that any Lisp called from the various 
> > hooks and places in display code is not affected, and neither are 
> > pre-command-hook and post-command-hook.  That should have almost the 
> > same effect, performance-wise, but be much safer than the automatic 
> > narrowing that affects everything in Emacs as long as the narrowing is 
> > in effect.
> >
> > IOW, replace all BEGV and ZV in display code with a couple of new 
> > macros, which effectively "narrow" the buffer, as far as the display 
> > engine is concerned.  Then set the limits of this restriction in 
> > redisplay_window, and remove it when the window's redisplay is done. Or 
> > something along these lines.
> 
> I guess this means, in essence, to throw away the patch?  Or do I 
> interpret what you wrote too negatively?

It means I think the idea is good, but the main part of the
implementation should be on a different level, not using narrowing,
which has a too global effect.

But I'd like to hear more opinions, including from Gerd.  I didn't
think about this long enough to be sure I'm right.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-05 16:34                   ` Eli Zaretskii
@ 2022-07-05 23:09                     ` Lars Ingebrigtsen
  2022-07-05 23:12                       ` Gregory Heytings
  2022-07-05 23:10                     ` Gregory Heytings
  1 sibling, 1 reply; 205+ messages in thread
From: Lars Ingebrigtsen @ 2022-07-05 23:09 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Gregory Heytings, 56393

Would it be feasible to combine Gregory's work here with the new ticks
code?

That is, not enabling the new mode by default in all buffers, but if
we've registered that a particular window has generated a lot of ticks,
then we check the buffer for long lines and then enable the mode in that
buffer.

I.e., postpone enabling the mode until we see that we need it.  That
should make most programmatic usages not trigger the mode.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no






^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-05 16:34                   ` Eli Zaretskii
  2022-07-05 23:09                     ` Lars Ingebrigtsen
@ 2022-07-05 23:10                     ` Gregory Heytings
  2022-07-06  9:49                       ` Gerd Möllmann
                                         ` (2 more replies)
  1 sibling, 3 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-05 23:10 UTC (permalink / raw)
  To: 56393; +Cc: Gerd Möllmann, Eli Zaretskii, Lars Ingebrigtsen


Okay, I've now pushed an improved version of the patch to the 
feature/fix-the-long-lines-display-bug branch.

A few additional comments:

Auto-narrow mode is now entered only when the buffer is actually 
displayed, which solves the problem of (with-temp-buffer 
(insert-file-contents ...) ...) and friends.

The scroll bar and modeline now display information relative to the whole 
buffer.

Instead of the command list in auto-narrow-widen-automatically, a symbol 
property could also be used, which would perhaps be easier to manage for 
users and package maintainers.  That being said, in most cases buffers 
with very long lines will typically be opened literally, so advanced 
editing commands will not be available anyway.

The auto-narrow-pre-command-function and auto-narrow-post-command-function 
could perhaps be moved before pre-command-hook and after 
post-command-hook, but even if that were the case the buffer that 
functions in pre-command-hook and post-command-hook would see would still 
be, in most cases, the narrowed one.

I think it might make sense to automatically disable font-lock-mode when 
auto-narrow is entered, as it seems to be the cause of the remaining 
display slowdowns, and it is not an essential editing feature.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-05 23:09                     ` Lars Ingebrigtsen
@ 2022-07-05 23:12                       ` Gregory Heytings
  2022-07-06 12:29                         ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-05 23:12 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: 56393


>
> Would it be feasible to combine Gregory's work here with the new ticks 
> code?
>
> That is, not enabling the new mode by default in all buffers, but if 
> we've registered that a particular window has generated a lot of ticks, 
> then we check the buffer for long lines and then enable the mode in that 
> buffer.
>
> I.e., postpone enabling the mode until we see that we need it.  That 
> should make most programmatic usages not trigger the mode.
>

Our mails crossed each other: the problem of programmatic usages is now 
solved AFAICS.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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:39                       ` Eli Zaretskii
  2 siblings, 1 reply; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-06  9:49 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: Eli Zaretskii, Lars Ingebrigtsen, 56393

Gregory Heytings <gregory@heytings.org> writes:

> Okay, I've now pushed an improved version of the patch to the
> feature/fix-the-long-lines-display-bug branch.

Just to give some progress feedback - I've got the branch and will take
a closer look ASAP, probably tomorrow.

From a brief look - very nice!

Thank you, Gregory!





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06  9:49                       ` Gerd Möllmann
@ 2022-07-06 10:21                         ` Gregory Heytings
  0 siblings, 0 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-06 10:21 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: Eli Zaretskii, Lars Ingebrigtsen, 56393

[-- Attachment #1: Type: text/plain, Size: 567 bytes --]


>> Okay, I've now pushed an improved version of the patch to the 
>> feature/fix-the-long-lines-display-bug branch.
>
> Just to give some progress feedback - I've got the branch and will take 
> a closer look ASAP, probably tomorrow.
>
> From a brief look - very nice!
>
> Thank you, Gregory!
>

Thank you! 😃

I've made a few more improvements, in particular I added a 
auto-narrow-hook which, by default, turns font-lock-mode off.  Now even 
opening the dictionary.json file non-literally (that is, with JavaScript 
mode enabled) works smoothly.

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-05 23:10                     ` Gregory Heytings
  2022-07-06  9:49                       ` Gerd Möllmann
@ 2022-07-06 11:31                       ` Lars Ingebrigtsen
  2022-07-06 12:13                         ` Gregory Heytings
                                           ` (2 more replies)
  2022-07-06 12:39                       ` Eli Zaretskii
  2 siblings, 3 replies; 205+ messages in thread
From: Lars Ingebrigtsen @ 2022-07-06 11:31 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: Gerd Möllmann, Eli Zaretskii, 56393

Gregory Heytings <gregory@heytings.org> writes:

> Auto-narrow mode is now entered only when the buffer is actually
> displayed, which solves the problem of (with-temp-buffer
> (insert-file-contents ...) ...) and friends.

Great!  I think that'll take care of the vast majority of potential
problems in this area.

I've now tried the branch with a couple of files that Emacs currently
chokes on, and it seems to work well -- for instance, with the
dictionary.json file, I can search for "aan zich" and then edit the JSON
with the normal commands like `C-M-k' to kill a sexps -- which is
totally impossible on the current trunk.

There's some slight hangs when `C-s'-ing the file, but none that last
longer than a second or two.  (Perhaps that has something to do with
`C-s' trying to add highlights to all the matches?)

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 11:31                       ` Lars Ingebrigtsen
@ 2022-07-06 12:13                         ` Gregory Heytings
  2022-07-06 12:44                           ` Gregory Heytings
  2022-07-06 12:50                         ` Eli Zaretskii
  2022-07-06 13:16                         ` Phil Sainty
  2 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-06 12:13 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: Gerd Möllmann, Eli Zaretskii, 56393


Thanks for your feedback!

>
> There's some slight hangs when `C-s'-ing the file, but none that last 
> longer than a second or two.  (Perhaps that has something to do with 
> `C-s' trying to add highlights to all the matches?)
>

Indeed.  I want to preserve normal editing experience as far as possible, 
so I did not touch these values so far.  I tried the four possible t/nil 
combinations for search-highlight and isearch-lazy-highlight, and setting 
isearch-lazy-highlight to nil improves Emacs' response time in such cases. 
Also setting isearch-highlight to nil is better, but only slightly.  I'll 
see what I can do.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-05 23:12                       ` Gregory Heytings
@ 2022-07-06 12:29                         ` Eli Zaretskii
  2022-07-06 13:01                           ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-06 12:29 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: larsi, 56393

> Cc: 56393@debbugs.gnu.org
> Date: Tue, 05 Jul 2022 23:12:45 +0000
> From: Gregory Heytings <gregory@heytings.org>
> 
> 
> >
> > Would it be feasible to combine Gregory's work here with the new ticks 
> > code?
> >
> > That is, not enabling the new mode by default in all buffers, but if 
> > we've registered that a particular window has generated a lot of ticks, 
> > then we check the buffer for long lines and then enable the mode in that 
> > buffer.
> >
> > I.e., postpone enabling the mode until we see that we need it.  That 
> > should make most programmatic usages not trigger the mode.
> >
> 
> Our mails crossed each other: the problem of programmatic usages is now 
> solved AFAICS.

Thanks, it's definitely better now.  However, not all the issues with
Lisp programs are gone, AFAICT.  At least the hooks called from
redisplay, like window-scroll-functions, still see a narrowed buffer.

Functions that are run by timers will also see a narrowed buffer.

I think we should decide what kind of feature this one is supposed to
be.  Is this really the full and complete solution of the long-line
display problems, or is this just a way to prevent Emacs from being
sluggish/not responsive by any means deemed necessary?

If this is supposed to be the complete solution, such that we don't
need any others, then it shouldn't interfere with editing and
shouldn't disable useful features such as font-lock, shouldn't make
commands a no-op (as it does now with 'recenter'), and shouldn't get
in the way of Lisp code that expects to have access to the entire
buffer when it has no reason to expect narrowing.  IOW, it should
affect only the display code and nothing else.

It is also possible and useful to have a partial solution, which makes
redisplay perform reasonably well at a price of disabling some
features and commands, and perhaps breaking some code out there.  But
then IMO it can no longer be the only such feature; instead, it is one
of several alternatives that attempt to unwedge redisplay by taking
different kinds of measures, each one with its advantages and
disadvantages.  As a notable example, if someone needs to search or
edit a large single-line JSON file, longlines.el currently sounds no
worse, and possibly better, than auto-narrow-mode, because it doesn't
disable font-lock and doesn't narrow the buffer, thus cannot affect
Lisp hooks and programs that aren't prepared for this narrowing.
Other solutions we have each one has advantages in other situations.

IOW, we can only consider valid use cases as "unimportant" or "rare
enough" if we are implementing yet another way of trading editing and
text-processing capabilities and features for responsiveness.  The
complete solution, by contrast, should cover _all_ the valid uses, and
should allow the user to use Emacs _as_usual_, without losing any
features, when files have very long lines.  (Here "valid" means
basically any useful Lisp program that doesn't intentionally crash or
infloop.)

If we cannot or don't intend to provide such a complete solution, we
should have several ones, and let the users choose what is best for
them in each situation.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-05 23:10                     ` Gregory Heytings
  2022-07-06  9:49                       ` Gerd Möllmann
  2022-07-06 11:31                       ` Lars Ingebrigtsen
@ 2022-07-06 12:39                       ` Eli Zaretskii
  2022-07-06 13:06                         ` Gregory Heytings
  2 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-06 12:39 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Tue, 05 Jul 2022 23:10:12 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: Eli Zaretskii <eliz@gnu.org>, 
>     Gerd Möllmann <gerd.moellmann@gmail.com>, 
>     Lars Ingebrigtsen <larsi@gnus.org>
> 
> Auto-narrow mode is now entered only when the buffer is actually 
> displayed, which solves the problem of (with-temp-buffer 
> (insert-file-contents ...) ...) and friends.
> 
> The scroll bar and modeline now display information relative to the whole 
> buffer.
> 
> Instead of the command list in auto-narrow-widen-automatically, a symbol 
> property could also be used, which would perhaps be easier to manage for 
> users and package maintainers.  That being said, in most cases buffers 
> with very long lines will typically be opened literally, so advanced 
> editing commands will not be available anyway.
> 
> The auto-narrow-pre-command-function and auto-narrow-post-command-function 
> could perhaps be moved before pre-command-hook and after 
> post-command-hook, but even if that were the case the buffer that 
> functions in pre-command-hook and post-command-hook would see would still 
> be, in most cases, the narrowed one.

One problem I spotted with the current branch is that it's still
sluggish when commands are repeated very fast.  For example, visit the
long-line.xml file, then lean on C-n or <DOWN> arrow -- you will see
that this gets back to the very slow responses after traversing
several lines.  By contrast, pressing C-n one keystroke at a time,
even if I do that as fast as I can (say, 5 keypresses per second)
performs much faster.

The autorepeat rate on this system is about 30 per second.  And this
is an unoptimized build, in case it matters.

Thanks.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 12:13                         ` Gregory Heytings
@ 2022-07-06 12:44                           ` Gregory Heytings
  2022-07-07  7:48                             ` Lars Ingebrigtsen
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-06 12:44 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: Gerd Möllmann, Eli Zaretskii, 56393


>> There's some slight hangs when `C-s'-ing the file, but none that last 
>> longer than a second or two.  (Perhaps that has something to do with 
>> `C-s' trying to add highlights to all the matches?)
>
> Indeed.  I want to preserve normal editing experience as far as 
> possible, so I did not touch these values so far.  I tried the four 
> possible t/nil combinations for search-highlight and 
> isearch-lazy-highlight, and setting isearch-lazy-highlight to nil 
> improves Emacs' response time in such cases. Also setting 
> isearch-highlight to nil is better, but only slightly.  I'll see what I 
> can do.
>

I just pushed a change to the feature branch which should improve isearch 
in that case.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 11:31                       ` Lars Ingebrigtsen
  2022-07-06 12:13                         ` Gregory Heytings
@ 2022-07-06 12:50                         ` Eli Zaretskii
  2022-07-06 13:16                         ` Phil Sainty
  2 siblings, 0 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-06 12:50 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: gerd.moellmann, gregory, 56393

> From: Lars Ingebrigtsen <larsi@gnus.org>
> Cc: 56393@debbugs.gnu.org,  Eli Zaretskii <eliz@gnu.org>,  Gerd
>  Möllmann
>  <gerd.moellmann@gmail.com>
> Date: Wed, 06 Jul 2022 13:31:47 +0200
> 
> There's some slight hangs when `C-s'-ing the file, but none that last
> longer than a second or two.  (Perhaps that has something to do with
> `C-s' trying to add highlights to all the matches?)

If this was in an optimized build, it is worth investigating, IMO:
second or two is quite long for an optimized build.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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:34                             ` Stefan Kangas
  0 siblings, 2 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-06 13:01 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: larsi, 56393


>
> I think we should decide what kind of feature this one is supposed to 
> be.  Is this really the full and complete solution of the long-line 
> display problems, or is this just a way to prevent Emacs from being 
> sluggish/not responsive by any means deemed necessary?
>

As far as I can tell, it's a full and complete solution, which makes a few 
compromises (as few as possible).

>
> If this is supposed to be the complete solution, such that we don't need 
> any others, then it shouldn't interfere with editing and shouldn't 
> disable useful features such as font-lock,
>

Font locking is as far as I can see the main reason why Emacs is still a 
bit sluggish in such cases.  Font locking is surely a useful feature, but 
it's not essential to edit a file.  And users who for some reason prefer 
not to disable font locking can do so by removing turn-off-font-lock-mode 
from the auto-narrow-mode hook.

>
> shouldn't make commands a no-op (as it does now with 'recenter'),
>

It's not no-op, it's no-op when if and only if it is called on a 
temporarily widened buffer when auto-narrow-mode is on.  So you can still 
use C-l as usual everywhere.

>
> and shouldn't get in the way of Lisp code that expects to have access to 
> the entire buffer when it has no reason to expect narrowing.
>

Lisp code that expects to have access to the entire buffer is typically 
embedded in a (save-restriction (widen) ...) form, isn't it?  Or IOW, Lisp 
code that expects to have access to the entire buffer without being 
embedded is such a form has a bug, isn't it?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 12:39                       ` Eli Zaretskii
@ 2022-07-06 13:06                         ` Gregory Heytings
  2022-07-06 13:32                           ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-06 13:06 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>
> One problem I spotted with the current branch is that it's still 
> sluggish when commands are repeated very fast.  For example, visit the 
> long-line.xml file, then lean on C-n or <DOWN> arrow -- you will see 
> that this gets back to the very slow responses after traversing several 
> lines.  By contrast, pressing C-n one keystroke at a time, even if I do 
> that as fast as I can (say, 5 keypresses per second) performs much 
> faster.
>

I don't see that.  On my seven year old laptop, Emacs remains responsive, 
and commands are executed instantaneously.  Did you try M-x 
find-file-literally?  If you don't see the slowdown with M-x 
find-file-literally, it's a slowdown due to the major mode (in this case 
nXML).





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 11:31                       ` Lars Ingebrigtsen
  2022-07-06 12:13                         ` Gregory Heytings
  2022-07-06 12:50                         ` Eli Zaretskii
@ 2022-07-06 13:16                         ` Phil Sainty
  2022-07-06 13:45                           ` Gregory Heytings
  2 siblings, 1 reply; 205+ messages in thread
From: Phil Sainty @ 2022-07-06 13:16 UTC (permalink / raw)
  To: Gregory Heytings
  Cc: Gerd Möllmann, Lars Ingebrigtsen, Eli Zaretskii, 56393

Hi Gregory,

Thanks for this.  I've only had a brief play, but it looks like a
very useful approach.

I can cause it to glitch by visiting a large file and leaning on the
page down key.  After a little while it fails to widen, and I'm left
in some narrowed portion of the buffer until I use a command which
re-triggers it.

I have vague misgivings about the fact that it doesn't care about the
file type or major mode, as it triggers for binary files which are
already handled safely by their major mode (images, archives, docview,
and anything else).  I say "vague" because I also didn't observe any
problems with such examples -- but I don't know whether that is
guaranteed to be true for all file types.

It's not clear to me how seamless this feature is (partly because I've
not had a chance to examine it in detail -- but I won't be able to do
so any time soon).  I see an explicit list of supported commands in
the code though, and I worry about that.  Surely(?) we can't insist
that all commands (if not functions generally?) which need to deal
with the full buffer (including all the custom code out there in
users' configs) should be updated to make them explicitly aware of
this new mode?  That doesn't seem maintainable to me, and I can only
imagine it causing lots of problems.  I always imagined a final
resolution for this issue being something that didn't necessitate
code changes by users.

Is that really needed?  As you're already attacking this in C code,
couldn't the widening and re-narrowing happen automatically for
everything?  I'm (perhaps naively) imagining that the narrowing might
just happen for the duration of each redisplay cycle.

Obviously there is some overlap with so-long.el which is a framework
for "doing a thing" (out of a collection of possible things) if long
lines are detected, and auto-narrow-mode could certainly be the new
default thing to do; so I'm wondering whether or not there's any
benefit to integrating the two things.  So-long is conservative in
when it triggers by comparison, partly to be confident of not causing
unwanted issues, and partly by necessity because its default action
(a major mode) is very disruptive; but its decision making can be
made more aggressive.

I always saw so-long.el as a band-aid until a real fix arrived, so
there may not be any need for any integration if its purpose has been
served.  It would seem possible to do, though, and so if there are
drawbacks of any significance with this new approach then I'd be
inclined to suggest that so-long and longlines would still have a
place, and integrating the new tool into the existing toolkit would
be a good thing.


-Phil






^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 13:01                           ` Gregory Heytings
@ 2022-07-06 13:25                             ` Eli Zaretskii
  2022-07-06 13:56                               ` Gregory Heytings
  2022-07-06 13:34                             ` Stefan Kangas
  1 sibling, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-06 13:25 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: larsi, 56393

> Date: Wed, 06 Jul 2022 13:01:39 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > I think we should decide what kind of feature this one is supposed to 
> > be.  Is this really the full and complete solution of the long-line 
> > display problems, or is this just a way to prevent Emacs from being 
> > sluggish/not responsive by any means deemed necessary?
> 
> As far as I can tell, it's a full and complete solution, which makes a few 
> compromises (as few as possible).

Depending on the compromise, that might or might not qualify as a full
and complete solution.  Font-lock is a very important feature, so
disabling it sounds like a heavy price to pay.  Especially since I
don't understand why: if the buffer is narrowed to 30K characters, why
should font-lock be unable to cope?

> > If this is supposed to be the complete solution, such that we don't need 
> > any others, then it shouldn't interfere with editing and shouldn't 
> > disable useful features such as font-lock,
> 
> Font locking is as far as I can see the main reason why Emacs is still a 
> bit sluggish in such cases.  Font locking is surely a useful feature, but 
> it's not essential to edit a file.

Well, I disagree it's non-essential.

> And users who for some reason prefer not to disable font locking can
> do so by removing turn-off-font-lock-mode from the auto-narrow-mode
> hook.

I'm talking about the defaults here.  The defaults should allow
editing without sacrificing important features (and ideally without
sacrificing anything).  Otherwise, this isn't a solution, it's a
workaround.  Which is also fine, but we should recognize it as such.

> > shouldn't make commands a no-op (as it does now with 'recenter'),
> 
> It's not no-op, it's no-op when if and only if it is called on a 
> temporarily widened buffer when auto-narrow-mode is on.  So you can still 
> use C-l as usual everywhere.

It shouldn't be a no-op under any circumstances.  It's an important
command.

> > and shouldn't get in the way of Lisp code that expects to have access to 
> > the entire buffer when it has no reason to expect narrowing.
> >
> 
> Lisp code that expects to have access to the entire buffer is typically 
> embedded in a (save-restriction (widen) ...) form, isn't it?

No, not necessarily.  Lisp code that doesn't expect to find narrowing
simply does nothing about narrowing.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 13:06                         ` Gregory Heytings
@ 2022-07-06 13:32                           ` Eli Zaretskii
  2022-07-06 14:05                             ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-06 13:32 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Wed, 06 Jul 2022 13:06:26 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: 56393@debbugs.gnu.org, gerd.moellmann@gmail.com, larsi@gnus.org
> 
> > One problem I spotted with the current branch is that it's still 
> > sluggish when commands are repeated very fast.  For example, visit the 
> > long-line.xml file, then lean on C-n or <DOWN> arrow -- you will see 
> > that this gets back to the very slow responses after traversing several 
> > lines.  By contrast, pressing C-n one keystroke at a time, even if I do 
> > that as fast as I can (say, 5 keypresses per second) performs much 
> > faster.
> 
> I don't see that.  On my seven year old laptop, Emacs remains responsive, 
> and commands are executed instantaneously.  Did you try M-x 
> find-file-literally?  If you don't see the slowdown with M-x 
> find-file-literally, it's a slowdown due to the major mode (in this case 
> nXML).

I see the same if I visit literally, just after leaning on C-n
longer.  It starts happening around 15% into the file.

And I don't think I understand what the major mode has to do with
this.  How do you think a major mode can affect C-n when font-lock is
turned off?

Here's the profile of leaning on C-n, in case it's useful:

        1082  94% - command-execute
        1082  94%  - call-interactively
        1077  93%   - funcall-interactively
        1076  93%    - next-line
        1076  93%     - line-move
         418  36%      - line-move-partial
           3   0%       - pos-visible-in-window-p
           2   0%        - eval
           2   0%           if
           1   0%          file-remote-p
           2   0%       + window-screen-lines
           2   0%       + default-line-height
           1   0%         posn-at-point
           1   0%       - window-inside-pixel-edges
           1   0%        + window-edges
         265  23%        line-move-visual
           1   0%    + execute-extended-command
           5   0%   + byte-code
          64   5% + ...
           1   0% + undo-auto--add-boundary





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 13:01                           ` Gregory Heytings
  2022-07-06 13:25                             ` Eli Zaretskii
@ 2022-07-06 13:34                             ` Stefan Kangas
  2022-07-06 14:10                               ` Gregory Heytings
  1 sibling, 1 reply; 205+ messages in thread
From: Stefan Kangas @ 2022-07-06 13:34 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: Eli Zaretskii, Lars Ingebrigtsen, 56393

Gregory Heytings <gregory@heytings.org> writes:

> As far as I can tell, it's a full and complete solution, which makes a few
> compromises (as few as possible).
[...]
> Font locking is as far as I can see the main reason why Emacs is still a
> bit sluggish in such cases.

Surely, a full and complete solution should make *no* compromises, not
even with secondary features.  (And preferably be completely
transparent to Lisp.)





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 13:16                         ` Phil Sainty
@ 2022-07-06 13:45                           ` Gregory Heytings
  2022-07-06 14:05                             ` Phil Sainty
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-06 13:45 UTC (permalink / raw)
  To: Phil Sainty; +Cc: Gerd Möllmann, Lars Ingebrigtsen, Eli Zaretskii, 56393


Hi Phil,

Thanks for your detailed feedback.

>
> I can cause it to glitch by visiting a large file and leaning on the 
> page down key.  After a little while it fails to widen, and I'm left in 
> some narrowed portion of the buffer until I use a command which 
> re-triggers it.
>

That probably means you have a very big frame, you should set 
auto-narrow-display-length to a larger value than its default one (30000).

>
> I see an explicit list of supported commands in the code though, and I 
> worry about that.  Surely(?) we can't insist that all commands (if not 
> functions generally?) which need to deal with the full buffer (including 
> all the custom code out there in users' configs) should be updated to 
> make them explicitly aware of this new mode?  That doesn't seem 
> maintainable to me, and I can only imagine it causing lots of problems.
>

This new mode isn't necessary for ordinary files, so it will be activated 
only rarely.  That already means that it cannot cause "lots of problems". 
I think it's okay if it "breaks" a few commands, especially if the fix is 
only to add these commands to a list or to put a property on them.

>
> So-long is conservative in when it triggers by comparison, partly to be 
> confident of not causing unwanted issues, and partly by necessity 
> because its default action (a major mode) is very disruptive.
>

I see, so-long restricts its action to so-long-target-modes, is that 
correct?  I'm not sure such a restriction is necessary for 
auto-narrow-mode, it does not change anything apart from turning 
font-lock-mode off (by default) and narrowing the buffer.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 13:25                             ` Eli Zaretskii
@ 2022-07-06 13:56                               ` Gregory Heytings
  2022-07-06 14:09                                 ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-06 13:56 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: larsi, 56393


>
> Depending on the compromise, that might or might not qualify as a full 
> and complete solution.  Font-lock is a very important feature, so 
> disabling it sounds like a heavy price to pay.  Especially since I don't 
> understand why: if the buffer is narrowed to 30K characters, why should 
> font-lock be unable to cope?
>

I don't know.  I only observe that it's often unable to cope with such 
cases.  And this is outside of the scope of the long line display bug, 
it's (possibly) a font-lock bug (or an inherent limitation of font-lock). 
I can try to tackle that bug next, if you want.

>> Font locking is as far as I can see the main reason why Emacs is still 
>> a bit sluggish in such cases.  Font locking is surely a useful feature, 
>> but it's not essential to edit a file.
>
> Well, I disagree it's non-essential.
>

Okay.  My opinion is that being able to edit a file normally without nice 
colors on its characters is way better than being unable to edit a file. 
But let's agree to disagree.

>>> shouldn't make commands a no-op (as it does now with 'recenter'),
>>
>> It's not no-op, it's no-op when if and only if it is called on a 
>> temporarily widened buffer when auto-narrow-mode is on.  So you can 
>> still use C-l as usual everywhere.
>
> It shouldn't be a no-op under any circumstances.  It's an important 
> command.
>

It's never a no-op when it is used as a command.  It can become a no-op 
when it is used internally by a command.

>>> and shouldn't get in the way of Lisp code that expects to have access 
>>> to the entire buffer when it has no reason to expect narrowing.
>>
>> Lisp code that expects to have access to the entire buffer is typically 
>> embedded in a (save-restriction (widen) ...) form, isn't it?
>
> No, not necessarily.  Lisp code that doesn't expect to find narrowing 
> simply does nothing about narrowing.
>

Narrowing has been in Emacs since about forever, so as far as I can tell 
functions that were written without taking the possibility that the buffer 
on display is narrowed into account, and that do not work anymore when the 
buffer is narrowed, have a bug.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 13:45                           ` Gregory Heytings
@ 2022-07-06 14:05                             ` Phil Sainty
  0 siblings, 0 replies; 205+ messages in thread
From: Phil Sainty @ 2022-07-06 14:05 UTC (permalink / raw)
  To: Gregory Heytings
  Cc: Gerd Möllmann, Lars Ingebrigtsen, Eli Zaretskii, 56393

On 2022-07-07 01:45, Gregory Heytings wrote:
> I see, so-long restricts its action to so-long-target-modes,
> is that correct?

That's correct.  The so-long-predicate function determines
whether to take action, but the predicate is only called in
the first place if the buffer's major mode derives from one
of the target modes.







^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 13:32                           ` Eli Zaretskii
@ 2022-07-06 14:05                             ` Gregory Heytings
  2022-07-06 14:13                               ` Eli Zaretskii
  2022-07-07  7:47                               ` Lars Ingebrigtsen
  0 siblings, 2 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-06 14:05 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> I don't see that.  On my seven year old laptop, Emacs remains 
>> responsive, and commands are executed instantaneously.  Did you try M-x 
>> find-file-literally?  If you don't see the slowdown with M-x 
>> find-file-literally, it's a slowdown due to the major mode (in this 
>> case nXML).
>
> I see the same if I visit literally, just after leaning on C-n longer. 
> It starts happening around 15% into the file.
>

I can't reproduce that.  Is that with emacs -Q?  What computer do you use? 
I see the same profile, but Emacs remains responsive.

>
> And I don't think I understand what the major mode has to do with this. 
> How do you think a major mode can affect C-n when font-lock is turned 
> off?
>

nXML adds rng-maybe-echo-error-at-point to post-command-hook.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 13:56                               ` Gregory Heytings
@ 2022-07-06 14:09                                 ` Eli Zaretskii
  2022-07-06 14:41                                   ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-06 14:09 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: larsi, 56393

> Date: Wed, 06 Jul 2022 13:56:06 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > Depending on the compromise, that might or might not qualify as a full 
> > and complete solution.  Font-lock is a very important feature, so 
> > disabling it sounds like a heavy price to pay.  Especially since I don't 
> > understand why: if the buffer is narrowed to 30K characters, why should 
> > font-lock be unable to cope?
> 
> I don't know.  I only observe that it's often unable to cope with such 
> cases.  And this is outside of the scope of the long line display bug, 
> it's (possibly) a font-lock bug (or an inherent limitation of font-lock). 
> I can try to tackle that bug next, if you want.

I think we must, because font-lock is run by the display engine, and
if font-lock makes redisplay significantly slower, it's part of the
same problem.

> >> Font locking is as far as I can see the main reason why Emacs is still 
> >> a bit sluggish in such cases.  Font locking is surely a useful feature, 
> >> but it's not essential to edit a file.
> >
> > Well, I disagree it's non-essential.
> >
> 
> Okay.  My opinion is that being able to edit a file normally without nice 
> colors on its characters is way better than being unable to edit a file. 

Oh, we agree here: it's definitely way better.  I'm just saying that a
complete solution cannot force users to make such sacrifices.

> >>> shouldn't make commands a no-op (as it does now with 'recenter'),
> >>
> >> It's not no-op, it's no-op when if and only if it is called on a 
> >> temporarily widened buffer when auto-narrow-mode is on.  So you can 
> >> still use C-l as usual everywhere.
> >
> > It shouldn't be a no-op under any circumstances.  It's an important 
> > command.
> 
> It's never a no-op when it is used as a command.  It can become a no-op 
> when it is used internally by a command.

I understand.  And that means some of those callers will work
differently under auto-narrow-mode than they do without.  Which is not
a good thing to have.

Why is 'recenter' at all relevant, btw?  It isn't called by the
display code, AFAIR, so why do we have to disable it?

> >>> and shouldn't get in the way of Lisp code that expects to have access 
> >>> to the entire buffer when it has no reason to expect narrowing.
> >>
> >> Lisp code that expects to have access to the entire buffer is typically 
> >> embedded in a (save-restriction (widen) ...) form, isn't it?
> >
> > No, not necessarily.  Lisp code that doesn't expect to find narrowing 
> > simply does nothing about narrowing.
> 
> Narrowing has been in Emacs since about forever, so as far as I can tell 
> functions that were written without taking the possibility that the buffer 
> on display is narrowed into account, and that do not work anymore when the 
> buffer is narrowed, have a bug.

I think there's a misunderstanding here: what these Lisp programs
don't expect is to find narrowing that is different from what the user
sees or expects top have.  Narrowing is largely a user-level feature,
so using it for internal purposes is problematic at best.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 13:34                             ` Stefan Kangas
@ 2022-07-06 14:10                               ` Gregory Heytings
  2022-07-06 14:37                                 ` Stefan Kangas
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-06 14:10 UTC (permalink / raw)
  To: Stefan Kangas; +Cc: Eli Zaretskii, Lars Ingebrigtsen, 56393


>> Font locking is as far as I can see the main reason why Emacs is still 
>> a bit sluggish in such cases.
>
> Surely, a full and complete solution should make *no* compromises, not 
> even with secondary features.  (And preferably be completely transparent 
> to Lisp.)
>

Perfect is the enemy of good.  Emacs users have been plagued for decades 
by this bug, asking for a solution without any compromises is simply 
unreasonable.  Even more so as the compromise is, in this case, to disable 
a feature that is outside of the scope of this bug.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 14:05                             ` Gregory Heytings
@ 2022-07-06 14:13                               ` Eli Zaretskii
  2022-07-06 14:27                                 ` Gregory Heytings
  2022-07-07  7:47                               ` Lars Ingebrigtsen
  1 sibling, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-06 14:13 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Wed, 06 Jul 2022 14:05:55 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> 
> >> I don't see that.  On my seven year old laptop, Emacs remains 
> >> responsive, and commands are executed instantaneously.  Did you try M-x 
> >> find-file-literally?  If you don't see the slowdown with M-x 
> >> find-file-literally, it's a slowdown due to the major mode (in this 
> >> case nXML).
> >
> > I see the same if I visit literally, just after leaning on C-n longer. 
> > It starts happening around 15% into the file.
> >
> 
> I can't reproduce that.

Maybe you need to make the file larger?

> Is that with emacs -Q?

Yes, of course.

> What computer do you use? 

A 10-year old 3.4 GHz Core i7.  My Emacs is slightly slower than
normal because it's a 32-bit build --with-wide-int.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 14:13                               ` Eli Zaretskii
@ 2022-07-06 14:27                                 ` Gregory Heytings
  2022-07-06 16:53                                   ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-06 14:27 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393

[-- Attachment #1: Type: text/plain, Size: 509 bytes --]


>> I can't reproduce that.
>
> Maybe you need to make the file larger?
>

How large?  I can't reproduce it with the 20MB dictionary.json file, nor 
with the 1GB hugedictionary.json.  (But I didn't have the patience to lean 
on C-n to reach 15% in hugedictionary.json 😉)

>
> A 10-year old 3.4 GHz Core i7.  My Emacs is slightly slower than normal 
> because it's a 32-bit build --with-wide-int.
>

This may explain that.  Because my laptop has 2.8 GHz Core i7 CPU, so it 
should be slower.

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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:50                                   ` Eli Zaretskii
  0 siblings, 2 replies; 205+ messages in thread
From: Stefan Kangas @ 2022-07-06 14:37 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: Eli Zaretskii, Lars Ingebrigtsen, 56393

Gregory Heytings <gregory@heytings.org> writes:

> Perfect is the enemy of good.  Emacs users have been plagued for decades
> by this bug, asking for a solution without any compromises is simply
> unreasonable.

I'm not asking for more than what you have, which I believe everyone
is very happy to see.  I'm saying that Eli is correct in saying that
we should not treat it as the full and complete solution.

IME, other text editors doesn't choke on files with long lines, nor
require you to disable any features.  The full and complete solution
will make sure Emacs doesn't either.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 14:09                                 ` Eli Zaretskii
@ 2022-07-06 14:41                                   ` Gregory Heytings
  2022-07-06 16:19                                     ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-06 14:41 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: larsi, 56393


>
> I think we must, because font-lock is run by the display engine, and if 
> font-lock makes redisplay significantly slower, it's part of the same 
> problem.
>

I disagree.  It's not the redisplay part that make font-lock slower, but 
how it parses the buffer.  So it's a different problem.

>
> Oh, we agree here: it's definitely way better.  I'm just saying that a 
> complete solution cannot force users to make such sacrifices.
>

Users can reasonably expect and understand that in exceptional 
circumstances a non-essential editing feature is, by default, turned off, 
if the purpose of doing that is to maintain responsiveness.  If you load a 
very big file in a browser (or for that matter in any application), it 
will become sluggish.  Try to open the 1GB hugedictionay.json file with 
vim, nano, VS Code, Atom, and try opening it with the patched Emacs.

(Atom is the only one that displays a warning: "Atom will be unresponsive 
during the loading of very large files. Do you still want to load this 
file?"  If you proceed, Atom becomes unuseable.)

>
> Why is 'recenter' at all relevant, btw?  It isn't called by the display 
> code, AFAIR, so why do we have to disable it?
>

Because commands in auto-narrow-widen-automatically might call "recenter" 
for aesthetic purposes.  One example is end-of-buffer.  Which means that 
what you have is (progn (widen) (recenter)), which takes a few seconds 
without fundamentally changing what is on display.

>
> I think there's a misunderstanding here: what these Lisp programs don't 
> expect is to find narrowing that is different from what the user sees or 
> expects top have.  Narrowing is largely a user-level feature, so using 
> it for internal purposes is problematic at best.
>

Sorry, I don't get what you mean.  Do you have a concrete example of a 
problematic function?

A Lisp program that takes into account the possibility that the user uses 
narrowing and that needs to have access to the whole buffer will use 
(save-restriction (widen) ...).  A Lisp program that requires the user to 
narrow the buffer to work properly will still work, because explicit 
narrowing can still be used with auto-narrow mode.  What are the remaining 
possibilities?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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:50                                   ` Eli Zaretskii
  1 sibling, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-06 14:47 UTC (permalink / raw)
  To: Stefan Kangas; +Cc: Eli Zaretskii, Lars Ingebrigtsen, 56393


>
> IME, other text editors doesn't choke on files with long lines, nor 
> require you to disable any features.  The full and complete solution 
> will make sure Emacs doesn't either.
>

That's wrong, sorry.  Try opening hugedictionary.json in these editors and 
you'll see the effect.  Try opening dictionary.json in VS Code, and you'll 
see a warning: "For performance reasons, document symbols have been 
limited to 5000 items."  I don't know what that exactly means (I don't use 
VS Code), but clearly some limitation has been set automatically for 
performance reasons.  Moreover highlighting is completely (and silently) 
turned off on that file by VS Code.  All this is a very reasonable thing 
to do.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 14:47                                   ` Gregory Heytings
@ 2022-07-06 15:03                                     ` Stefan Kangas
  2022-07-06 15:31                                       ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Stefan Kangas @ 2022-07-06 15:03 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: Eli Zaretskii, Lars Ingebrigtsen, 56393

Gregory Heytings <gregory@heytings.org> wries:

> That's wrong, sorry.  Try opening hugedictionary.json in these editors and
> you'll see the effect.

I was thinking of much smaller files that Emacs chokes on but e.g. vim does not.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 15:03                                     ` Stefan Kangas
@ 2022-07-06 15:31                                       ` Gregory Heytings
  0 siblings, 0 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-06 15:31 UTC (permalink / raw)
  To: Stefan Kangas; +Cc: Eli Zaretskii, Lars Ingebrigtsen, 56393


>> That's wrong, sorry.  Try opening hugedictionary.json in these editors 
>> and you'll see the effect.
>
> I was thinking of much smaller files that Emacs chokes on but e.g. vim 
> does not.
>

Surely, different editors have different limits.  My aim was to set the 
limit as high as possible for Emacs.  As far as I can tell the only limit 
is now RAM.  I just tried:

for I in $(seq 1 600); do cat dictionary.json; done > monsterdictionary.json

which produces a file with a single 11GB (!) long line, and you can edit 
it almost as it it were a 1KB file with Emacs.

That being said, my main point here was that all editors disable 
non-essential features when they open "big" files, for some definition of 
"big".  Both VS Code and Atom (silently) disable most highlighting even 
for the 300KB long-line.xml file (only "short" lines are highlighted), and 
(silently) disable all highlighting for the 19MB dictionary.json file.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 14:37                                 ` Stefan Kangas
  2022-07-06 14:47                                   ` Gregory Heytings
@ 2022-07-06 15:50                                   ` Eli Zaretskii
  1 sibling, 0 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-06 15:50 UTC (permalink / raw)
  To: Stefan Kangas; +Cc: gregory, larsi, 56393

> From: Stefan Kangas <stefan@marxist.se>
> Date: Wed, 6 Jul 2022 16:37:26 +0200
> Cc: Eli Zaretskii <eliz@gnu.org>, Lars Ingebrigtsen <larsi@gnus.org>, 56393@debbugs.gnu.org
> 
> I'm saying that Eli is correct in saying that we should not treat it
> as the full and complete solution.

That's not what I said.  I said if we think this will provide a
complete solution, we should strive to make it that.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 14:41                                   ` Gregory Heytings
@ 2022-07-06 16:19                                     ` Eli Zaretskii
  2022-07-06 16:57                                       ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-06 16:19 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: larsi, 56393

> Date: Wed, 06 Jul 2022 14:41:08 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > I think we must, because font-lock is run by the display engine, and if 
> > font-lock makes redisplay significantly slower, it's part of the same 
> > problem.
> 
> I disagree.  It's not the redisplay part that make font-lock slower, but 
> how it parses the buffer.  So it's a different problem.

How is it different from the code in the display engine that calls
next-single-char-property-change or remove-text-properties, or loops
over all the overlays at certain position calling overlay-get?  In
Emacs nowadays font-lock is almost always called as part of redisplay,
so I don't see how we can separate them and say that this is a
different problem.

> > Oh, we agree here: it's definitely way better.  I'm just saying that a 
> > complete solution cannot force users to make such sacrifices.
> 
> Users can reasonably expect and understand that in exceptional 
> circumstances a non-essential editing feature is, by default, turned off, 
> if the purpose of doing that is to maintain responsiveness.  If you load a 
> very big file in a browser (or for that matter in any application), it 
> will become sluggish.  Try to open the 1GB hugedictionay.json file with 
> vim, nano, VS Code, Atom, and try opening it with the patched Emacs.
> 
> (Atom is the only one that displays a warning: "Atom will be unresponsive 
> during the loading of very large files. Do you still want to load this 
> file?"  If you proceed, Atom becomes unuseable.)

I invite you to look at this from a different aspect angle.  Your idea
is basically to present to the display engine a small portion of the
buffer, whose size is 30K characters.  If you actually cut 30K
characters from any of the files we are using for this work, do you
see Emacs choking on any of them if you don't turn off font-lock and
leave 'recenter' as it behaves on master?  If not, then why doesn't
the same work with auto-narrow-mode?

And if a 30K-character cut is still clunky, then maybe 30K is not the
right default value?  For example, why not use 2 window-fulls before
and after the window (assuming that gives us a smaller chunk)?

The point is that we should try to squeeze the most out of this
narrowing idea, before we start disabling up features.  Because
disabling features is a kind of retreat, an indication that we turned
every stone and couldn't make Emacs fast enough, so we are kinda
giving up.  And it's too early to give up, IMO.

> > Why is 'recenter' at all relevant, btw?  It isn't called by the display 
> > code, AFAIR, so why do we have to disable it?
> 
> Because commands in auto-narrow-widen-automatically might call "recenter" 
> for aesthetic purposes.  One example is end-of-buffer.  Which means that 
> what you have is (progn (widen) (recenter)), which takes a few seconds 
> without fundamentally changing what is on display.

That's what I thought.  And to me this means that you see an example
of a problem I mentioned earlier: code from the display engine is used
in commands that basically have nothing to do with redisplay per se,
and your current implementation doesn't take care of those calls into
the display code by commands like recenter, C-v, C-n, etc.  I think
sooner or later we will need to present a narrowed buffer to them as
well.

> > I think there's a misunderstanding here: what these Lisp programs don't 
> > expect is to find narrowing that is different from what the user sees or 
> > expects top have.  Narrowing is largely a user-level feature, so using 
> > it for internal purposes is problematic at best.
> >
> 
> Sorry, I don't get what you mean.  Do you have a concrete example of a 
> problematic function?

What kind of example do you want to see?  What do you mean by
"problematic" in this context?

> A Lisp program that takes into account the possibility that the user uses 
> narrowing and that needs to have access to the whole buffer will use 
> (save-restriction (widen) ...).  A Lisp program that requires the user to 
> narrow the buffer to work properly will still work, because explicit 
> narrowing can still be used with auto-narrow mode.  What are the remaining 
> possibilities?

When the user narrows the buffer, he/she doesn't expect the parts
outside the restriction to be accessible.  But when the user didn't
narrow, the results of having some part of a command being able to
access only 30K around point _will_ surprise users.

Which is why I'm saying that it is better to restrict the display code
via some other means, and leave the narrowing alone.  After all, it is
our code that deliberately references BEGV and ZV in the display
engine, so using some other values shouldn't be that difficult, I
think.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 14:27                                 ` Gregory Heytings
@ 2022-07-06 16:53                                   ` Eli Zaretskii
  2022-07-06 17:17                                     ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-06 16:53 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Wed, 06 Jul 2022 14:27:48 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > A 10-year old 3.4 GHz Core i7.  My Emacs is slightly slower than normal 
> > because it's a 32-bit build --with-wide-int.
> 
> This may explain that.  Because my laptop has 2.8 GHz Core i7 CPU, so it 
> should be slower.

Then maybe try to increase your keyboard auto-repeat rate?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 16:19                                     ` Eli Zaretskii
@ 2022-07-06 16:57                                       ` Gregory Heytings
  2022-07-06 17:50                                         ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-06 16:57 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: larsi, 56393

[-- Attachment #1: Type: text/plain, Size: 3916 bytes --]


>
> How is it different from the code in the display engine that calls 
> next-single-char-property-change or remove-text-properties, or loops 
> over all the overlays at certain position calling overlay-get?  In Emacs 
> nowadays font-lock is almost always called as part of redisplay, so I 
> don't see how we can separate them and say that this is a different 
> problem.
>

Again, I don't know (my understanding of the font-lock machinery is very 
limited).  I only observe that turning font lock mode off makes things 
significantly better.  And that turning highlighting off in such files is 
what other editors do, too.  So at this point I don't see why it wouldn't 
be a reasonable thing to do.

>
> I invite you to look at this from a different aspect angle.  Your idea 
> is basically to present to the display engine a small portion of the 
> buffer, whose size is 30K characters.  If you actually cut 30K 
> characters from any of the files we are using for this work, do you see 
> Emacs choking on any of them if you don't turn off font-lock and leave 
> 'recenter' as it behaves on master?  If not, then why doesn't the same 
> work with auto-narrow-mode?
>

That's something I already did, and yes, I do see Emacs choking.  Try to 
navigate in the attached 30K file.  Then try again after turning font-lock 
mode off.

(But I do not understand what you mean by "leave 'recenter' as it behaves 
on master".)

>
> For example, why not use 2 window-fulls before and after the window 
> (assuming that gives us a smaller chunk)?
>

That would mean to compute the dimensions of the window in a command-hook. 
I tried to make that hook as efficient as possible, so it is on purpose 
that I used a constant there, with something that seemed a reasonable 
default, instead of computing it again and again.

>
> The point is that we should try to squeeze the most out of this 
> narrowing idea, before we start disabling up features.  Because 
> disabling features is a kind of retreat, an indication that we turned 
> every stone and couldn't make Emacs fast enough, so we are kinda giving 
> up.  And it's too early to give up, IMO.
>

I agree with that idea/direction, but again I think that at least now 
Emacs doesn't do worse than all other editors out there, and in fact it 
does way better.  If all editors turn off highlighting in such cases, that 
must surely be for a good reason.  Highlighting means parsing, and parsing 
is infinitely more expensive than not parsing.

>
> And to me this means that you see an example of a problem I mentioned 
> earlier: code from the display engine is used in commands that basically 
> have nothing to do with redisplay per se, and your current 
> implementation doesn't take care of those calls into the display code by 
> commands like recenter, C-v, C-n, etc.  I think sooner or later we will 
> need to present a narrowed buffer to them as well.
>

You mean, a widened buffer?  Yes, that's a question for which I still 
don't have a clear answer: is it better to "whitelist" commands that will 
always work correctly with a narrowed buffer or to "whitelist" commands 
that may require a widened buffer?  I tend to think that the latter is 
better.

>
> What kind of example do you want to see?  What do you mean by 
> "problematic" in this context?
>

I mean, an actual example of "Lisp code that expects to have access to the 
entire buffer when it has no reason to expect narrowing", that is, Lisp 
code that expects to have access to the entire buffer without using 
(save-restriction (widen) ...).

>
> Which is why I'm saying that it is better to restrict the display code 
> via some other means, and leave the narrowing alone.  After all, it is 
> our code that deliberately references BEGV and ZV in the display engine, 
> so using some other values shouldn't be that difficult, I think.
>

Yes, I've understood that you want to do something else.

[-- Attachment #2: long-line-excerpt.xml --]
[-- Type: application/xml, Size: 30084 bytes --]

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 16:53                                   ` Eli Zaretskii
@ 2022-07-06 17:17                                     ` Gregory Heytings
  2022-07-06 17:30                                       ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-06 17:17 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>>> A 10-year old 3.4 GHz Core i7.  My Emacs is slightly slower than 
>>> normal because it's a 32-bit build --with-wide-int.
>>
>> This may explain that.  Because my laptop has 2.8 GHz Core i7 CPU, so 
>> it should be slower.
>
> Then maybe try to increase your keyboard auto-repeat rate?
>

The default auto-repeat rate on my system is 25.  I tried with 30, 35 and 
40, Emacs is still as responsive.  With 45 your recipe works, I see some 
chokes.  Why is that a problem?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 17:17                                     ` Gregory Heytings
@ 2022-07-06 17:30                                       ` Eli Zaretskii
  2022-07-06 21:53                                         ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-06 17:30 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Wed, 06 Jul 2022 17:17:25 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > Then maybe try to increase your keyboard auto-repeat rate?
> 
> The default auto-repeat rate on my system is 25.  I tried with 30, 35 and 
> 40, Emacs is still as responsive.  With 45 your recipe works, I see some 
> chokes.  Why is that a problem?

Because I think we should understand the reason.  I suspect the buffer
doesn't get narrowed or something.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 16:57                                       ` Gregory Heytings
@ 2022-07-06 17:50                                         ` Eli Zaretskii
  2022-07-07  0:28                                           ` Ihor Radchenko
  2022-07-07  0:38                                           ` Gregory Heytings
  0 siblings, 2 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-06 17:50 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: larsi, 56393

> Date: Wed, 06 Jul 2022 16:57:22 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > How is it different from the code in the display engine that calls 
> > next-single-char-property-change or remove-text-properties, or loops 
> > over all the overlays at certain position calling overlay-get?  In Emacs 
> > nowadays font-lock is almost always called as part of redisplay, so I 
> > don't see how we can separate them and say that this is a different 
> > problem.
> 
> Again, I don't know (my understanding of the font-lock machinery is very 
> limited).

Your understanding of font-lock, or your understanding how it is
invoked from the display code?

I can help with the latter.  When Emacs is about to display some chunk
of text, it checks whether the text has a non-nil 'fontified'
property.  If it does, that chunk of text was already fontified, but
if not, the display engine calls font-lock (via jit-lock.el) to
fontify the next 1500 characters, and puts a non-nil 'fontified'
property on those 1500 characters.  The result is face properties,
which are then actually displayed.

So if font-lock is slow for some reason, it will slow down redisplay.

> I only observe that turning font lock mode off makes things
> significantly better.  And that turning highlighting off in such
> files is what other editors do, too.  So at this point I don't see
> why it wouldn't be a reasonable thing to do.

I think we should understand why it becomes slow before we decide
whether to turn it off or speed it up somehow.  Other editors fontify
text using very different methods, so their limitations are not
necessarily similar to ours.

Btw, what happens if you turn on jit-lock-debug-mode?

> That's something I already did, and yes, I do see Emacs choking.  Try to 
> navigate in the attached 30K file.  Then try again after turning font-lock 
> mode off.
> 
> (But I do not understand what you mean by "leave 'recenter' as it behaves 
> on master".)

I meant disable its disabling.

> > For example, why not use 2 window-fulls before and after the window 
> > (assuming that gives us a smaller chunk)?
> 
> That would mean to compute the dimensions of the window in a command-hook. 
> I tried to make that hook as efficient as possible, so it is on purpose 
> that I used a constant there, with something that seemed a reasonable 
> default, instead of computing it again and again.

The primitives that access the window height and width are simple
accessors to C variables, so they are very cheap.  So I think this
might be a case of premature optimization.

A fixed constant is problematic because it needs to be large enough to
satisfy the largest possible window.  So for many windows we process
too many characters, and slow down redisplay unnecessarily for the
sake of those extreme cases.

> > The point is that we should try to squeeze the most out of this 
> > narrowing idea, before we start disabling up features.  Because 
> > disabling features is a kind of retreat, an indication that we turned 
> > every stone and couldn't make Emacs fast enough, so we are kinda giving 
> > up.  And it's too early to give up, IMO.
> 
> I agree with that idea/direction, but again I think that at least now 
> Emacs doesn't do worse than all other editors out there, and in fact it 
> does way better.  If all editors turn off highlighting in such cases, that 
> must surely be for a good reason.  Highlighting means parsing, and parsing 
> is infinitely more expensive than not parsing.

Again, why give up without trying to fix that?

> > And to me this means that you see an example of a problem I mentioned 
> > earlier: code from the display engine is used in commands that basically 
> > have nothing to do with redisplay per se, and your current 
> > implementation doesn't take care of those calls into the display code by 
> > commands like recenter, C-v, C-n, etc.  I think sooner or later we will 
> > need to present a narrowed buffer to them as well.
> 
> You mean, a widened buffer?

No, a narrowed buffer.  These commands use code from the display
engine, so letting them process a widened buffer means they run
slowly.

> Yes, that's a question for which I still don't have a clear answer:
> is it better to "whitelist" commands that will always work correctly
> with a narrowed buffer or to "whitelist" commands that may require a
> widened buffer?  I tend to think that the latter is better.

I think we need to present a narrowed buffer to display code
regardless of whether it runs by redisplay or by commands like C-n or
C-v or 'recenter'.

> > What kind of example do you want to see?  What do you mean by 
> > "problematic" in this context?
> 
> I mean, an actual example of "Lisp code that expects to have access to the 
> entire buffer when it has no reason to expect narrowing", that is, Lisp 
> code that expects to have access to the entire buffer without using 
> (save-restriction (widen) ...).

Are you saying that you don't believe in the existence of such code?
Every Lisp program expects to see the same narrowing (or lack thereof)
as the user sees.  So anything different is a time bomb waiting to go
off.

> > Which is why I'm saying that it is better to restrict the display code 
> > via some other means, and leave the narrowing alone.  After all, it is 
> > our code that deliberately references BEGV and ZV in the display engine, 
> > so using some other values shouldn't be that difficult, I think.
> 
> Yes, I've understood that you want to do something else.

No, it's the same idea, just implemented differently, and thus without
some of the problems we are discussing.  (But slowness of font-lock
will still need a separate solution -- or the conclusion that we have
no alternative but turn it off.)





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 17:30                                       ` Eli Zaretskii
@ 2022-07-06 21:53                                         ` Gregory Heytings
  0 siblings, 0 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-06 21:53 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> The default auto-repeat rate on my system is 25.  I tried with 30, 35 
>> and 40, Emacs is still as responsive.  With 45 your recipe works, I see 
>> some chokes.  Why is that a problem?
>
> Because I think we should understand the reason.  I suspect the buffer 
> doesn't get narrowed or something.
>

Okay, I'll see if I can find something interesting.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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
  1 sibling, 1 reply; 205+ messages in thread
From: Ihor Radchenko @ 2022-07-07  0:28 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Gregory Heytings, larsi, 56393

Eli Zaretskii <eliz@gnu.org> writes:

>> Again, I don't know (my understanding of the font-lock machinery is very 
>> limited).
>
> Your understanding of font-lock, or your understanding how it is
> invoked from the display code?
>
> I can help with the latter.  When Emacs is about to display some chunk
> of text, it checks whether the text has a non-nil 'fontified'
> property.  If it does, that chunk of text was already fontified, but
> if not, the display engine calls font-lock (via jit-lock.el) to
> fontify the next 1500 characters, and puts a non-nil 'fontified'
> property on those 1500 characters.  The result is face properties,
> which are then actually displayed.

Doesn't font-lock extend the region to be fontified to at least the full
current line? (see font-lock-extend-region-functions and
font-lock-extend-region-wholelines)

Best,
Ihor






^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 17:50                                         ` Eli Zaretskii
  2022-07-07  0:28                                           ` Ihor Radchenko
@ 2022-07-07  0:38                                           ` Gregory Heytings
  2022-07-07  5:53                                             ` Eli Zaretskii
  2022-07-07 14:25                                             ` Drew Adams
  1 sibling, 2 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-07  0:38 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: larsi, 56393


>
> I can help with the latter.  When Emacs is about to display some chunk 
> of text, it checks whether the text has a non-nil 'fontified' property. 
> If it does, that chunk of text was already fontified, but if not, the 
> display engine calls font-lock (via jit-lock.el) to fontify the next 
> 1500 characters, and puts a non-nil 'fontified' property on those 1500 
> characters.  The result is face properties, which are then actually 
> displayed.
>
> So if font-lock is slow for some reason, it will slow down redisplay.
>

Thanks.  I meant the former, but this is very useful nonetheless.  It 
means that the Lisp code which calculates these properties is (or at least 
can be) a bottleneck.  To determine which properties must be placed on 
these 1500 characters, it must presumably look further away, possibly much 
further away.

>
> I think we should understand why it becomes slow before we decide 
> whether to turn it off or speed it up somehow.  Other editors fontify 
> text using very different methods, so their limitations are not 
> necessarily similar to ours.
>

We can try, yes.  But my feeling so far is that this won't get us 
anywhere.

>
> Btw, what happens if you turn on jit-lock-debug-mode?
>

I'll try that.

>> I mean, an actual example of "Lisp code that expects to have access to 
>> the entire buffer when it has no reason to expect narrowing", that is, 
>> Lisp code that expects to have access to the entire buffer without 
>> using (save-restriction (widen) ...).
>
> Are you saying that you don't believe in the existence of such code? 
> Every Lisp program expects to see the same narrowing (or lack thereof) 
> as the user sees.  So anything different is a time bomb waiting to go 
> off.
>

I don't say that I don't believe in the existence of such code.  I get 
your point, and agree that narrow-mode (ab)uses a feature in a way that it 
was never intended to be (ab)used.  But I also say that files with 
extremely long lines are rare, and that it's in my opinion much better to 
see some rare functions fail when opening such files than to see Emacs 
becoming unusable.  Or in other words: if all essential editing commands 
work on these files, that's already a big step forward.

>> Yes, I've understood that you want to do something else.
>
> No, it's the same idea, just implemented differently, and thus without 
> some of the problems we are discussing.  (But slowness of font-lock will 
> still need a separate solution -- or the conclusion that we have no 
> alternative but turn it off.)
>

I tried to do that, and so far I don't see how your alternative approach 
could work.  The problem with long lines is not only that redisplay takes 
forever in some cases, it's also (and perhaps mainly) that commands take 
forever.  With dictionary.json, with point on the last character, C-p 
takes (on my computer) about 26 seconds outside of redisplay.  I don't see 
how we could tell all that code that it should work on a narrowed buffer 
without actually narrowing the buffer.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-07  0:28                                           ` Ihor Radchenko
@ 2022-07-07  5:43                                             ` Eli Zaretskii
  0 siblings, 0 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-07  5:43 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: gregory, larsi, 56393

> From: Ihor Radchenko <yantar92@gmail.com>
> Cc: Gregory Heytings <gregory@heytings.org>,  larsi@gnus.org,
>   56393@debbugs.gnu.org
> Date: Thu, 07 Jul 2022 08:28:07 +0800
> 
> > I can help with the latter.  When Emacs is about to display some chunk
> > of text, it checks whether the text has a non-nil 'fontified'
> > property.  If it does, that chunk of text was already fontified, but
> > if not, the display engine calls font-lock (via jit-lock.el) to
> > fontify the next 1500 characters, and puts a non-nil 'fontified'
> > property on those 1500 characters.  The result is face properties,
> > which are then actually displayed.
> 
> Doesn't font-lock extend the region to be fontified to at least the full
> current line? (see font-lock-extend-region-functions and
> font-lock-extend-region-wholelines)

It's possible that this is indeed the problem.  If that's the case, we
should probably limit that widening as well.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-07  0:38                                           ` Gregory Heytings
@ 2022-07-07  5:53                                             ` Eli Zaretskii
  2022-07-07  8:23                                               ` Gregory Heytings
  2022-07-07 14:25                                             ` Drew Adams
  1 sibling, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-07  5:53 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: larsi, 56393

> Date: Thu, 07 Jul 2022 00:38:22 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > So if font-lock is slow for some reason, it will slow down redisplay.
> >
> 
> Thanks.  I meant the former, but this is very useful nonetheless.  It 
> means that the Lisp code which calculates these properties is (or at least 
> can be) a bottleneck.  To determine which properties must be placed on 
> these 1500 characters, it must presumably look further away, possibly much 
> further away.

That's possible, but limiting that search should in most cases still
produce reasonable fontifications.  At least that's the hope.

> > I think we should understand why it becomes slow before we decide 
> > whether to turn it off or speed it up somehow.  Other editors fontify 
> > text using very different methods, so their limitations are not 
> > necessarily similar to ours.
> 
> We can try, yes.  But my feeling so far is that this won't get us 
> anywhere.

Let's see if your feeling is right, okay?

> > Are you saying that you don't believe in the existence of such code? 
> > Every Lisp program expects to see the same narrowing (or lack thereof) 
> > as the user sees.  So anything different is a time bomb waiting to go 
> > off.
> >
> 
> I don't say that I don't believe in the existence of such code.  I get 
> your point, and agree that narrow-mode (ab)uses a feature in a way that it 
> was never intended to be (ab)used.  But I also say that files with 
> extremely long lines are rare, and that it's in my opinion much better to 
> see some rare functions fail when opening such files than to see Emacs 
> becoming unusable.  Or in other words: if all essential editing commands 
> work on these files, that's already a big step forward.

I think we should defer discussing tradeoffs until we hit a brick wall
of sorts, i.e. get to the point where no significant further
improvements can be made, and we understand why.  The tradeoffs should
be based on such an understanding, because it's not smart giving up
features we could maybe have.

> >> Yes, I've understood that you want to do something else.
> >
> > No, it's the same idea, just implemented differently, and thus without 
> > some of the problems we are discussing.  (But slowness of font-lock will 
> > still need a separate solution -- or the conclusion that we have no 
> > alternative but turn it off.)
> 
> I tried to do that, and so far I don't see how your alternative approach 
> could work.  The problem with long lines is not only that redisplay takes 
> forever in some cases, it's also (and perhaps mainly) that commands take 
> forever.  With dictionary.json, with point on the last character, C-p 
> takes (on my computer) about 26 seconds outside of redisplay.  I don't see 
> how we could tell all that code that it should work on a narrowed buffer 
> without actually narrowing the buffer.

C-p takes an inordinate amount of time in those cases because it calls
functions of the display engine (see vertical-motion).  Limiting the
display code to some small enough region of the buffer will speed that
up as well, since it's the same code in both cases.  The somewhat
tricky part with the likes of C-p is where and how to compute the
restriction.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 14:05                             ` Gregory Heytings
  2022-07-06 14:13                               ` Eli Zaretskii
@ 2022-07-07  7:47                               ` Lars Ingebrigtsen
  1 sibling, 0 replies; 205+ messages in thread
From: Lars Ingebrigtsen @ 2022-07-07  7:47 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, Eli Zaretskii, 56393

Gregory Heytings <gregory@heytings.org> writes:

>> I see the same if I visit literally, just after leaning on C-n
>> longer. It starts happening around 15% into the file.
>
> I can't reproduce that.  Is that with emacs -Q?  What computer do you
> use? I see the same profile, but Emacs remains responsive.

I can't reproduce it with dictionary.json, either -- but I do see
sluggishness if I go to the end of the buffer, and then lean on `C-p'.

But if I visit the file literally, then `C-p' is fast, so js-mode is
apparently having an effect on `C-p' here.  (Or perhaps it's because the
buffer is multibyte when not visiting literally and unibyte when
visiting literally.)

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-06 12:44                           ` Gregory Heytings
@ 2022-07-07  7:48                             ` Lars Ingebrigtsen
  0 siblings, 0 replies; 205+ messages in thread
From: Lars Ingebrigtsen @ 2022-07-07  7:48 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: Gerd Möllmann, Eli Zaretskii, 56393

Gregory Heytings <gregory@heytings.org> writes:

> I just pushed a change to the feature branch which should improve
> isearch in that case.

Yup; `C-s' works fine now in dictionary.json.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-07  5:53                                             ` Eli Zaretskii
@ 2022-07-07  8:23                                               ` Gregory Heytings
  2022-07-07 10:10                                                 ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-07  8:23 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: larsi, 56393


>
> C-p takes an inordinate amount of time in those cases because it calls 
> functions of the display engine (see vertical-motion).  Limiting the 
> display code to some small enough region of the buffer will speed that 
> up as well, since it's the same code in both cases.  The somewhat tricky 
> part with the likes of C-p is where and how to compute the restriction.
>

Okay.  Can I try to do this myself, or are you already working on it, if 
not already polishing your code?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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
  0 siblings, 2 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-07 10:10 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: larsi, 56393

> Date: Thu, 07 Jul 2022 08:23:11 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > C-p takes an inordinate amount of time in those cases because it calls 
> > functions of the display engine (see vertical-motion).  Limiting the 
> > display code to some small enough region of the buffer will speed that 
> > up as well, since it's the same code in both cases.  The somewhat tricky 
> > part with the likes of C-p is where and how to compute the restriction.
> >
> 
> Okay.  Can I try to do this myself, or are you already working on it, if 
> not already polishing your code?

I'm not working on this (unless you call this discussion and trying
the branch "work" ;-).

If you want to try this, here are some thoughts which may or may not
prove useful:

  . for actual redisplay, the natural place for checking whether we
    need to "narrow" is at the beginning of redisplay_window, where
    you can check the window's buffer; this might need to be rechecked
    in the few places (maybe just one) where redisplay moves point
  . to compute a good value for "narrowing", multiply the number of
    rows of the window's glyph matrix by the number of glyphs in each
    row, then by some small factor (like 2 or 3)
  . the way to "narrow" for display code only is to replace BEGV and
    ZV with new macros, say DBEGV and DZV, which look at separate
    variables, possibly new members in 'struct window', if those are
    set; when the above-mentioned check determines that "narrowing" is
    needed, set them accordingly
  . a good place to reset these new members of 'struct window' is in
    mark_window_display_accurate_1, when the window's display is
    marked as "accurate"
  . various calls to the likes of Fnext_single_property_change in the
    display code will need to specify explicit limits for the search,
    using DBEGV and DZV, instead of falling back on BEGV and ZV that
    are already set

I don't yet have a good idea about where to check whether "narrowing"
is necessary for commands like C-n and C-v, but maybe look where I set
the display_working_on_window_p flag as guideline.  Another idea would
be to use those new members in 'struct window', but then (a) it is
less clear when to reset them, and (b) some commands might go far
away, thus making those values no longer pertinent.

Let me know if you need help with display code internals.

Thanks.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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 18:38               ` Gregory Heytings
  0 siblings, 2 replies; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-07 11:29 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: Lars Ingebrigtsen, 56393

Looking at the changes in 0463368a7b..7b19ce51fc, I don't have much to
bicker, i.e. except about Magit, lldb, gcc-11, dap-mode, ... :-).

From my POV it's ready to go to master.  The sooner more people get to
use this the better.

Thanks again, Gregory!

P.S.

I currently can't compile Emacs because of reasons, so I can't try it
myself:

What happens when evaluating an expression in *scratch* that returns a
really large result?  Or maybe in a Shell buffer some large output?
Does Auto Narrow kick in?  I'm not sure it does.  Should it?



modified   src/buffer.c
@@ -6363,6 +6366,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-state",
+		     &BVAR (current_buffer, auto_narrow__narrowing_state), Qnil,
+		     doc: /* Internal variable used by `auto-narrow-mode'.  */);
+

Don't know about the "--" in the name.  AFAICS, no other per-buffer
variable has that. Likewise the "__" in the name.

Not that it is important.  I just noticed it.  And, maybe it's some
convention that I don't know.


@@ -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;
+}

If someone feels like it, could you tell me what the '[bw]set_.*'
business is for?  A serializer?  Or for setting breakpoints?


@@ -6557,6 +6557,11 @@ DEFUN ("recenter", Frecenter, Srecenter, 0, 2, "P\np",
   if (buf != current_buffer)
     error ("`recenter'ing a window that does not display current-buffer.");

+  /* Refuse to recenter auto-narrowed buffers that are not actually narrowed,
+     as this can be very slow.  */
+  if (BUFFER_AUTO_NARROWED_NON_NARROWED_P (buf))
+    return Qnil;
+

Hm, I don't know.  Is it always the right thing that recenter does
nothing in this case?  I'm not saying it isn't.


modified   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 (buf))
+	{
+	  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);

I can almost guarantee that it's not guaranteed that window_end_pos is
always right.  But I don't have an alternative, ATM.  Could you please
add a TODO or what's customary today in the comment, so it's easier to
find?

+	}
+      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);
+	}

I'd find it easier to read if the if/else were reversed to that the !
isn't needed.


@@ -19133,6 +19142,14 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
      variables.  */
   set_buffer_internal_1 (XBUFFER (w->contents));

+  if (BUFFER_NEEDS_AUTO_NARROWING_P (current_buffer))
+    {
+      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");
+    }

Could you please tell in what circumstances the call would not set the
variable?  And wouldn't the minot mode print something, also?  In
other words, can we remove it more or less safely?  (If the user
screws up, all bets are off anyway.)


@@ -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;

This if/else I'd also reverse because of the !.


@@ -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);
+	  }

Reverse if/else?







^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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:47                 ` Gerd Möllmann
  2022-07-07 18:38               ` Gregory Heytings
  1 sibling, 2 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-07 13:36 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: gregory, larsi, 56393

> Cc: Lars Ingebrigtsen <larsi@gnus.org>, 56393@debbugs.gnu.org
> From: Gerd Möllmann <gerd.moellmann@gmail.com>
> Date: Thu, 07 Jul 2022 13:29:10 +0200
> 
> +  DEFVAR_PER_BUFFER ("auto-narrow--narrowing-state",
> +		     &BVAR (current_buffer, auto_narrow__narrowing_state), Qnil,
> +		     doc: /* Internal variable used by `auto-narrow-mode'.  */);
> +
> 
> Don't know about the "--" in the name.  AFAICS, no other per-buffer
> variable has that. Likewise the "__" in the name.
> 
> Not that it is important.  I just noticed it.  And, maybe it's some
> convention that I don't know.

It's our current convention for "internal" variables and functions,
similar to the "internal-" prefix you know about.

> @@ -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;
> +}
> 
> If someone feels like it, could you tell me what the '[bw]set_.*'
> business is for?  A serializer?  Or for setting breakpoints?

It was originally supposed to make it easier to move to a more
sophisticated GC, where it is important to have one place where a
struct member is set, so that you could do whatever GC needs to do
with variables that got written to.  Unfortunately, the GC
modernization is still not here.

> modified   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 (buf))
> +	{
> +	  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);
> 
> I can almost guarantee that it's not guaranteed that window_end_pos is
> always right.  But I don't have an alternative, ATM.  Could you please
> add a TODO or what's customary today in the comment, so it's easier to
> find?

Yes, this should test window_end_valid before using window_end_pos.
An alternative could be window-start point plus some estimation of the
window's text, perhaps?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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  5:47                 ` Gerd Möllmann
  1 sibling, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-07 14:10 UTC (permalink / raw)
  To: gerd.moellmann, gregory; +Cc: larsi, 56393

> Cc: gregory@heytings.org, larsi@gnus.org, 56393@debbugs.gnu.org
> Date: Thu, 07 Jul 2022 16:36:38 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> 
> > modified   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 (buf))
> > +	{
> > +	  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);
> > 
> > I can almost guarantee that it's not guaranteed that window_end_pos is
> > always right.  But I don't have an alternative, ATM.  Could you please
> > add a TODO or what's customary today in the comment, so it's easier to
> > find?
> 
> Yes, this should test window_end_valid before using window_end_pos.
> An alternative could be window-start point plus some estimation of the
> window's text, perhaps?

Actually, we could be more accurate: we could use move_it_to,
similarly to what pos_visible_p does when passed -1 as the position.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-07  0:38                                           ` Gregory Heytings
  2022-07-07  5:53                                             ` Eli Zaretskii
@ 2022-07-07 14:25                                             ` Drew Adams
  2022-07-07 15:58                                               ` Eli Zaretskii
  2022-07-07 18:49                                               ` Gregory Heytings
  1 sibling, 2 replies; 205+ messages in thread
From: Drew Adams @ 2022-07-07 14:25 UTC (permalink / raw)
  To: Gregory Heytings, Eli Zaretskii; +Cc: larsi@gnus.org, 56393@debbugs.gnu.org

(Caveat: I'm not following this thread.  Ignore
if not helpful.)

> narrow-mode (ab)uses a feature in a way that...

If this is really about long-lines display, could
you please consider not using a name such as
`auto-narrow-mode' or `narrow-mode' for this?

Functions and variables with `narrow' in the name
should generally, when possible, be reserved for
the usual feature of narrowing a buffer.  (And in
particular for users doing that.)

If the reason for narrowing is only to carry out
or enable some other action/behavior/feature (e.g.
something to do with long-lines display?) then
maybe put that in the name, without `narrow'?

Will users look for this mode when they want to
narrow a buffer for some reason?  Or is this just
something that has to be done in order to effect
something else - a precondition/dependency?

IOW, is this the best name, for users?  What will
a user looking for functions for narrowing think
when coming across `narrow-mode'?  If this isn't
something users will generally use for narrowing
a buffer then at least please make that clear in
the doc string.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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:49                                               ` Gregory Heytings
  1 sibling, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-07 15:58 UTC (permalink / raw)
  To: Drew Adams; +Cc: gregory, larsi, 56393

> From: Drew Adams <drew.adams@oracle.com>
> CC: "larsi@gnus.org" <larsi@gnus.org>,
>         "56393@debbugs.gnu.org"
> 	<56393@debbugs.gnu.org>
> Date: Thu, 7 Jul 2022 14:25:12 +0000
> 
> > narrow-mode (ab)uses a feature in a way that...
> 
> If this is really about long-lines display, could
> you please consider not using a name such as
> `auto-narrow-mode' or `narrow-mode' for this?

auto-narrow-mode actually narrows the buffer.

> If the reason for narrowing is only to carry out
> or enable some other action/behavior/feature (e.g.
> something to do with long-lines display?) then
> maybe put that in the name, without `narrow'?
> 
> Will users look for this mode when they want to
> narrow a buffer for some reason?  Or is this just
> something that has to be done in order to effect
> something else - a precondition/dependency?
> 
> IOW, is this the best name, for users?  What will
> a user looking for functions for narrowing think
> when coming across `narrow-mode'?  If this isn't
> something users will generally use for narrowing
> a buffer then at least please make that clear in
> the doc string.

These questions are IMO premature, since the feature is under
development and is not even on master yet.  Hold your horses.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-07 15:58                                               ` Eli Zaretskii
@ 2022-07-07 17:50                                                 ` Eli Zaretskii
  2022-07-07 18:46                                                   ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-07 17:50 UTC (permalink / raw)
  To: gregory; +Cc: larsi, 56393

One problem with the current implementation that uses narrowing is
that if you have the same buffer buffer shown in more than one window,
the non-selected windows sometimes scroll "by themselves".  To
reproduce, visit, e.g., long-line.xml, say "C-x 2", then scroll with
C-v: at some point the other window will also scroll, to reflect the
narrowing.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-07 10:10                                                 ` Eli Zaretskii
@ 2022-07-07 18:08                                                   ` Gregory Heytings
  2022-07-09  6:20                                                   ` Eli Zaretskii
  1 sibling, 0 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-07 18:08 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: larsi, 56393


>
> If you want to try this, here are some thoughts which may or may not 
> prove useful:
>

Thanks.

>
> Let me know if you need help with display code internals.
>

I'll do that, thanks.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-07 11:29             ` Gerd Möllmann
  2022-07-07 13:36               ` Eli Zaretskii
@ 2022-07-07 18:38               ` Gregory Heytings
  2022-07-08  5:59                 ` Gerd Möllmann
  1 sibling, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-07 18:38 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: Lars Ingebrigtsen, 56393


Thanks for your detailed feedback, Gerd!

>
> From my POV it's ready to go to master.  The sooner more people get to 
> use this the better.
>

Eli (almost) convinced me that there might be a way to do even better.  I 
don't yet see how it can be done, but I think it's worth trying to see if 
it is indeed possible to do better before going to master.

>
> What happens when evaluating an expression in *scratch* that returns a 
> really large result?  Or maybe in a Shell buffer some large output? Does 
> Auto Narrow kick in?  I'm not sure it does.  Should it?
>

It doesn't, indeed.  I'm not sure it should, but ideally it would.

> +      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);
> +     }
>
> I'd find it easier to read if the if/else were reversed to that the ! 
> isn't needed.
>

I'm not sure what the convention is here (or even if there is a 
convention).  But my feeling is that it's better to place the "normal" 
case first, and the exceptional case in the else part.

> +  if (BUFFER_NEEDS_AUTO_NARROWING_P (current_buffer))
> +    {
> +      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");
> +    }
>
> Could you please tell in what circumstances the call would not set the 
> variable?  And wouldn't the minot mode print something, also?  In other 
> words, can we remove it more or less safely?  (If the user screws up, 
> all bets are off anyway.)
>

It should always set the variable indeed, but who knows what a user could 
do if they decide for some reason to override the definition of 
auto-narrow-mode in their init file?  Setting the narrowing state again 
here is a cheap safety measure that avoids calling that function again 
during each redisplay cycle.

I don't know why the minor mode doesn't print something when it's called 
from C, but it doesn't.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-07 17:50                                                 ` Eli Zaretskii
@ 2022-07-07 18:46                                                   ` Gregory Heytings
  2022-07-07 19:05                                                     ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-07 18:46 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: larsi, 56393


>
> One problem with the current implementation that uses narrowing is that 
> if you have the same buffer buffer shown in more than one window, the 
> non-selected windows sometimes scroll "by themselves".  To reproduce, 
> visit, e.g., long-line.xml, say "C-x 2", then scroll with C-v: at some 
> point the other window will also scroll, to reflect the narrowing.
>

Indeed.  Another similar problem is that scroll-other-window does not work 
(or rather, it does, but the narrowing of the buffer is not updated).

By the way, that's a problem I see with the idea of computing the 
narrowing dynamically by multiplying window-body-width by 
window-total-height.  If a buffer is displayed in two windows, a small one 
and a larger one, and we navigate the buffer in the smaller one, the 
larger one will display only a part of what it could display.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-07 14:25                                             ` Drew Adams
  2022-07-07 15:58                                               ` Eli Zaretskii
@ 2022-07-07 18:49                                               ` Gregory Heytings
  1 sibling, 0 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-07 18:49 UTC (permalink / raw)
  To: Drew Adams; +Cc: Eli Zaretskii, larsi, 56393


>
> Ignore if not helpful.
>

It isn't, indeed.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-07 18:46                                                   ` Gregory Heytings
@ 2022-07-07 19:05                                                     ` Eli Zaretskii
  0 siblings, 0 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-07 19:05 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: larsi, 56393

> Date: Thu, 07 Jul 2022 18:46:53 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: larsi@gnus.org, 56393@debbugs.gnu.org
> 
> By the way, that's a problem I see with the idea of computing the 
> narrowing dynamically by multiplying window-body-width by 
> window-total-height.  If a buffer is displayed in two windows, a small one 
> and a larger one, and we navigate the buffer in the smaller one, the 
> larger one will display only a part of what it could display.

If you are saying the above in the context of my proposal to implement
the "narrowing" such that it's only visible to redisplay, then I see
no problem: redisplay_window is called separately for each window, and
so the "narrowing" will be computed separately and differently for
each one of them.  (Which might, btw, mean we will see each window
with slightly different fontifications, if we limit font-lock to the
same restriction.  Something to keep in mind for later, I suppose.)

If you are saying the above in the context of the current
auto-narrow-mode, then it shouldn't be hard to loop over all the
windows showing the same buffer and choose the widest narrowing of
them all.  Or am I missing something?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-07 13:36               ` Eli Zaretskii
  2022-07-07 14:10                 ` Eli Zaretskii
@ 2022-07-08  5:47                 ` Gerd Möllmann
  2022-07-08  5:56                   ` Eli Zaretskii
  1 sibling, 1 reply; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-08  5:47 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gregory, larsi, 56393

[-- Attachment #1: Type: text/plain, Size: 909 bytes --]



> On 2022-07-07,, at 15:36 , Eli Zaretskii <eliz@gnu.org> wrote:
> 
> It's our current convention for "internal" variables and functions,
> similar to the "internal-" prefix you know about.

Thanks.  Again what learned.

> 
> It was originally supposed to make it easier to move to a more
> sophisticated GC, where it is important to have one place where a
> struct member is set, so that you could do whatever GC needs to do
> with variables that got written to.  Unfortunately, the GC
> modernization is still not here.

Too bad.  It does not improve the "habitability" of the code, IMO.

> 
>> I can almost guarantee that it's not guaranteed that window_end_pos is
>> always right.  But I don't have an alternative, ATM.  Could you please
>> add a TODO or what's customary today in the comment, so it's easier to
>> find?
> 
> Yes, this should test window_end_valid before using window_end_pos.

Right.


[-- Attachment #2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 874 bytes --]

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-07 14:10                 ` Eli Zaretskii
@ 2022-07-08  5:49                   ` Gerd Möllmann
  2022-07-08  6:55                     ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-08  5:49 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gregory, larsi, 56393


[-- Attachment #1.1: Type: text/plain, Size: 411 bytes --]



> On 2022-07-07,, at 16:10 , Eli Zaretskii <eliz@gnu.org> wrote:
> 
>> Yes, this should test window_end_valid before using window_end_pos.
>> An alternative could be window-start point plus some estimation of the
>> window's text, perhaps?
> 
> Actually, we could be more accurate: we could use move_it_to,
> similarly to what pos_visible_p does when passed -1 as the position.

That's a possibility, indeed.

[-- Attachment #1.2: Type: text/html, Size: 2711 bytes --]

[-- Attachment #2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 874 bytes --]

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-08  5:47                 ` Gerd Möllmann
@ 2022-07-08  5:56                   ` Eli Zaretskii
  2022-07-08  6:25                     ` Gerd Möllmann
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-08  5:56 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: gregory, larsi, 56393

> From: Gerd Möllmann <gerd.moellmann@gmail.com>
> Date: Fri, 8 Jul 2022 07:47:57 +0200
> Cc: gregory@heytings.org,
>  larsi@gnus.org,
>  56393@debbugs.gnu.org
> 
> > It was originally supposed to make it easier to move to a more
> > sophisticated GC, where it is important to have one place where a
> > struct member is set, so that you could do whatever GC needs to do
> > with variables that got written to.  Unfortunately, the GC
> > modernization is still not here.
> 
> Too bad.  It does not improve the "habitability" of the code, IMO.

I'm not sure I understand: can you elaborate what you mean by that?

From my POV, the names are quite self-explanatory, and in a production
build these small functions are all inlined by the compiler, so I
don't think I see a significant downside.  (There _was_ a downside in
the past: the annoying job of converting all direct accesses to struct
members to function calls, but that's water under the bridge.)





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-07 18:38               ` Gregory Heytings
@ 2022-07-08  5:59                 ` Gerd Möllmann
  0 siblings, 0 replies; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-08  5:59 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: Lars Ingebrigtsen, 56393

[-- Attachment #1: Type: text/plain, Size: 1160 bytes --]



> On 2022-07-07,, at 20:38 , Gregory Heytings <gregory@heytings.org> wrote:
> 
>> I'd find it easier to read if the if/else were reversed to that the ! isn't needed.
>> 
> 
> I'm not sure what the convention is here (or even if there is a convention).  But my feeling is that it's better to place the "normal" case first, and the exceptional case in the else part.

Ok.  Tastes differ, I guess.

>> Could you please tell in what circumstances the call would not set the variable?  And wouldn't the minot mode print something, also?  In other words, can we remove it more or less safely?  (If the user screws up, all bets are off anyway.)
>> 
> 
> It should always set the variable indeed, but who knows what a user could do if they decide for some reason to override the definition of auto-narrow-mode in their init file?  Setting the narrowing state again here is a cheap safety measure that avoids calling that function again during each redisplay cycle.
> 
> I don't know why the minor mode doesn't print something when it's called from C, but it doesn't.

I think we could use Ffuncall_interactively here to get the message printed.


[-- Attachment #2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 874 bytes --]

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-08  5:56                   ` Eli Zaretskii
@ 2022-07-08  6:25                     ` Gerd Möllmann
  2022-07-08  7:19                       ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-08  6:25 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gregory, larsi, 56393


[-- Attachment #1.1: Type: text/plain, Size: 1504 bytes --]



> On 2022-07-08,, at 7:56 , Eli Zaretskii <eliz@gnu.org> wrote:
> 
>> From: Gerd Möllmann <gerd.moellmann@gmail.com>
>> 
>> Too bad.  It does not improve the "habitability" of the code, IMO.
> 
> I'm not sure I understand: can you elaborate what you mean by that?

I used the term habitability in the sense of Richard Gabriel in Patterns of Software.

https://www.dreamsongs.com/Files/PatternsOfSoftware.pdf <https://www.dreamsongs.com/Files/PatternsOfSoftware.pdf>

"Habitability is the characteristic of source code that enables programmers, coders, bug-fixers, and people coming to the code later in its life to understand its construction and intentions and to change it comfortably and confidently."

(There's of course more...)

> 
> From my POV, the names are quite self-explanatory, and in a production
> build these small functions are all inlined by the compiler, so I
> don't think I see a significant downside.

But now, as in this case with the new variable, one has to write a new bset function, for no other reason than to make matters worse by introducing inconsistency by having some variables that habe a bset and other that have not...  I'm sure you understand what I mean.

I think I wouldn't call it "significant" either, but I also don't think it's good in any sense.

>  (There _was_ a downside in
> the past: the annoying job of converting all direct accesses to struct
> members to function calls, but that's water under the bridge.)

Right.


[-- Attachment #1.2: Type: text/html, Size: 2855 bytes --]

[-- Attachment #2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 874 bytes --]

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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
  0 siblings, 2 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-08  6:55 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: gregory, larsi, 56393

> From: Gerd Möllmann <gerd.moellmann@gmail.com>
> Date: Fri, 8 Jul 2022 07:49:30 +0200
> Cc: gregory@heytings.org,
>  larsi@gnus.org,
>  56393@debbugs.gnu.org
> 
>  Yes, this should test window_end_valid before using window_end_pos.
>  An alternative could be window-start point plus some estimation of the
>  window's text, perhaps?
> 
>  Actually, we could be more accurate: we could use move_it_to,
>  similarly to what pos_visible_p does when passed -1 as the position.
> 
> That's a possibility, indeed.

I installed the below on the feature branch.  Testing it, I see that
window_end_valid is false quite a lot in this spot, and in those cases
using window_end_pos yields (a usually small, like 100 - 200 bytes,
but occasionally very large) inaccuracy.

This is very old code (I see it in Emacs 21), with a FIXME comment
since those days, which AFAIU was written with exactly this issue in
mind.  If there are no problems with the fix below, I think it should
be moved to master.


diff --git a/src/xdisp.c b/src/xdisp.c
index 7821c12..a583e10 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -18872,19 +18872,32 @@ set_vertical_scroll_bar (struct window *w)
 	  && NILP (echo_area_buffer[0])))
     {
       struct buffer *buf = XBUFFER (w->contents);
+      ptrdiff_t window_end_pos = w->window_end_pos;
+
+      /* If w->window_end_pos cannot be trusted, recompute it "the
+	 hard way".  */
+      if (!w->window_end_valid)
+	{
+	  struct it it;
+	  struct text_pos start_pos;
+
+	  SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
+	  start_display (&it, w, start_pos);
+	  move_it_to (&it, -1, it.last_visible_x, window_box_height (w), -1,
+		      MOVE_TO_X | MOVE_TO_Y);
+	  window_end_pos = BUF_Z (buf) - IT_CHARPOS (it);
+	}
       if (! BUFFER_AUTO_NARROWED_P (buf))
 	{
 	  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);
+	  end = BUF_Z (buf) - 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);
+	  end = BUF_Z (buf) - window_end_pos - BUF_BEG (buf);
 	}
 
       if (end < start)





^ permalink raw reply related	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-08  6:55                     ` Eli Zaretskii
@ 2022-07-08  7:01                       ` Gerd Möllmann
  2022-07-08 21:41                       ` Gregory Heytings
  1 sibling, 0 replies; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-08  7:01 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Gregory Heytings, Lars Ingebrigtsen, 56393

[-- Attachment #1: Type: text/plain, Size: 359 bytes --]



> On 2022-07-08,, at 8:55 , Eli Zaretskii <eliz@gnu.org> wrote:
> 
> This is very old code (I see it in Emacs 21),

Ugh.  Will not happen again :-).

> with a FIXME comment
> since those days, which AFAIU was written with exactly this issue in
> mind.  If there are no problems with the fix below, I think it should
> be moved to master.

Three thumbs up!


[-- Attachment #2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 874 bytes --]

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-08  6:25                     ` Gerd Möllmann
@ 2022-07-08  7:19                       ` Eli Zaretskii
  0 siblings, 0 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-08  7:19 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: gregory, larsi, 56393

> From: Gerd Möllmann <gerd.moellmann@gmail.com>
> Date: Fri, 8 Jul 2022 08:25:29 +0200
> Cc: gregory@heytings.org,
>  larsi@gnus.org,
>  56393@debbugs.gnu.org
> 
> I used the term habitability in the sense of Richard Gabriel in Patterns of Software. 
> 
> https://www.dreamsongs.com/Files/PatternsOfSoftware.pdf
> 
> "Habitability is the characteristic of source code that enables programmers, coders, bug-fixers, and people
> coming to the code later in its life to understand its construction and intentions and to change it comfortably
> and confidently."
> 
> (There's of course more...)
> 
>  From my POV, the names are quite self-explanatory, and in a production
>  build these small functions are all inlined by the compiler, so I
>  don't think I see a significant downside. 
> 
> But now, as in this case with the new variable, one has to write a new bset function, for no other reason than
> to make matters worse by introducing inconsistency by having some variables that habe a bset and other
> that have not...  I'm sure you understand what I mean.

Well, that's true, but we have a lot of similarly "un-habitable" stuff
in Emacs anyway.  Most of that is due to the aspects of the Emacs
architecture, which is somewhat unique for a C program: automatic GC,
proliferation non-local exits, differences between external and
internal representation of text, C structs that represent Lisp
objects, etc.  As a simple example, the rule to use ENCODE_FILE and
DECODE_FILE when calling any file-name-oriented C APIs is one such
convention that newcomers have difficulties with following.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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
  1 sibling, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-08 21:41 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Gerd Möllmann, larsi, 56393


I reverted all commits on the feature branch, and started anew.  The 
feature has now been moved into the bowels of the display engine, and it 
works even better.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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
  1 sibling, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09  6:20 UTC (permalink / raw)
  To: gregory; +Cc: larsi

> Cc: larsi@gnus.org, 56393@debbugs.gnu.org
> Date: Thu, 07 Jul 2022 13:10:49 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> 
> I don't yet have a good idea about where to check whether "narrowing"
> is necessary for commands like C-n and C-v, but maybe look where I set
> the display_working_on_window_p flag as guideline.  Another idea would
> be to use those new members in 'struct window', but then (a) it is
> less clear when to reset them, and (b) some commands might go far
> away, thus making those values no longer pertinent.

After some more thinking about this, I think I do now have an idea how
to tackle command that employ the display code.

I see that you decided to produce the "restriction" in init_iterator,
which would, of course, work, but IMO it has a disadvantage:
init_iterator is called a lot, so computing the "restriction" in it
should be very fast.  Your current implementation _is_ fast, but AFAIU
its result is that we _always_ restrict the display code from seeing
the entire buffer, even if there are no long lines in it, which I
think is unnecessary.  The original implementation only did that when
it detected a long line, and I think we should keep it that way,
because the "restriction" will inevitably have some negative effects,
however minor, on what we display.

My proposal is to calculate the "restriction" in start_display.  That
function is called by all the commands/functions that use the display
code outside of redisplay proper.  (I think one or two such places
call init_iterator directly, but we can either handle them specially
or change them to use start_display.)  In addition, to prevent even
start_display doing more than necessary, redisplay_window should
compute the restriction for the window that is about to be
redisplayed, and store the values in 'struct window'; then
init_iterator, if called inside redisplay, will then simply reuse
those values, and start_display will refrain from computing them anew.
(To know whether some code is invoked by redisplay, test the value of
the global variable redisplaying_p.)  This way, we could make the
"restriction" smarter, and only apply it when needed.  Another
advantage is that this way the "restriction" will be the same for all
the code that is called by redisplay_window, directly or indirectly,
which I think is safer than having different "restrictions" computed
by different functions.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-08 21:41                       ` Gregory Heytings
@ 2022-07-09  7:03                         ` Eli Zaretskii
  2022-07-09  8:56                           ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09  7:03 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Fri, 08 Jul 2022 21:41:49 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: Gerd Möllmann <gerd.moellmann@gmail.com>, larsi@gnus.org, 
>     56393@debbugs.gnu.org
> 
> I reverted all commits on the feature branch, and started anew.  The 
> feature has now been moved into the bowels of the display engine, and it 
> works even better.

Thanks.  A few comments to what I see on the branch (apologies if
these are premature because you are still working on the code):

  . init_iterator is also called to display strings, and I'm not sure
    I understand what you intended to do in that case, since BEGV/ZV
    are not relevant to strings.
  . The WITH_NARROWED_BEGV macro is IMO awkward and not very
    convenient to use in C.  For starters, it cannot accommodate
    multi-line code, except via the 'do { ... } while(0);' kludge,
    which I think will make the code less readable.  It also should
    set up an unwind-protect handler, so that any non-local exit from
    the code will restore BEGV/ZV.  So I think it will be better to
    have two separate functions (and a third one to unwind).
  . You currently only apply the "restriction" in a few places where
    the code calls functions like find_newline_no_quit.  What about
    the rest of display code -- are you saying that it doesn't need to
    be "restricted"? or do you intend to add that in the future?  And
    what about restricting the Lisp code invoked via
    Vfontification_functions (i.e. jit-lock.el)?
  . Don't we want to "restrict" ZV as well?
  . I'm not sure the "restriction" should be computed relative to
    point: that might be OK for redisplaying a window, but for
    commands that use the display code the position with which we call
    init_iterator and start_display might be a better/safer
    alternative, because that position could be very far from point.
    In any case, get_narrowed_begv receives a pointer to a window, so
    I think it should use the window-point, not PT, which is the value
    of point in the current buffer.
  . The 10000 number should at least be a C macro if not a variable
    exposed to Lisp.
  . The maximum number of characters in a window could be more than
    just its width multiplied by its height, because the window could
    use smaller fonts than the default.  I think it is safer to use
    the dimensions of the window's glyph matrix for this, because
    there couldn't possibly be more characters in the window than the
    glyph matrix allows, and we always resize the matrix when we need
    to display more characters.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09  6:20                                                   ` Eli Zaretskii
@ 2022-07-09  8:24                                                     ` Gregory Heytings
  2022-07-09  9:13                                                       ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-09  8:24 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Gerd Möllmann, larsi, 56393


>
> I see that you decided to produce the "restriction" in init_iterator, 
> which would, of course, work, but IMO it has a disadvantage: 
> init_iterator is called a lot, so computing the "restriction" in it 
> should be very fast.  Your current implementation _is_ fast, but AFAIU 
> its result is that we _always_ restrict the display code from seeing the 
> entire buffer, even if there are no long lines in it, which I think is 
> unnecessary.  The original implementation only did that when it detected 
> a long line, and I think we should keep it that way, because the 
> "restriction" will inevitably have some negative effects, however minor, 
> on what we display.
>

I don't think we can detect long lines reliably enough.  The problem of 
the original implementation is what Gerd mentioned: "What happens when 
evaluating an expression in *scratch* that returns a really large result? 
Or maybe in a Shell buffer some large output?" and similar cases, like 
inserting the result of a shell command in the buffer.  Detecting long 
lines in insert-file-contents is not enough to make sure that Emacs will 
always continue to behave normally when a long line is on display.

Note that we the current implementation does not always restrict display 
code from seeing the entire buffer, it does so in a few well-chosen 
places, everywhere else the display code sees the entire buffer.

>
> My proposal is to calculate the "restriction" in start_display.  That 
> function is called by all the commands/functions that use the display 
> code outside of redisplay proper.  (I think one or two such places call 
> init_iterator directly, but we can either handle them specially or 
> change them to use start_display.)  In addition, to prevent even 
> start_display doing more than necessary, redisplay_window should compute 
> the restriction for the window that is about to be redisplayed, and 
> store the values in 'struct window'; then init_iterator, if called 
> inside redisplay, will then simply reuse those values, and start_display 
> will refrain from computing them anew. (To know whether some code is 
> invoked by redisplay, test the value of the global variable 
> redisplaying_p.)  This way, we could make the "restriction" smarter, and 
> only apply it when needed.  Another advantage is that this way the 
> "restriction" will be the same for all the code that is called by 
> redisplay_window, directly or indirectly, which I think is safer than 
> having different "restrictions" computed by different functions.
>

Okay, thanks.  I'll try to do that.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09  7:03                         ` Eli Zaretskii
@ 2022-07-09  8:56                           ` Gregory Heytings
  2022-07-09  9:20                             ` Eli Zaretskii
  2022-07-09 10:54                             ` Eli Zaretskii
  0 siblings, 2 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-09  8:56 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>
> Thanks.  A few comments to what I see on the branch (apologies if these 
> are premature because you are still working on the code):
>

I am not, as far as I see the code is in a near-final state, except that I 
will of course try to take your (and other's) comments into account.

>
> . init_iterator is also called to display strings, and I'm not sure I 
> understand what you intended to do in that case, since BEGV/ZV are not 
> relevant to strings.
>

I guess moving the calculation of the restriction into start_display 
should fix that problem.  Then it->narrowed_begv will be 0 for strings.

>
> . The WITH_NARROWED_BEGV macro is IMO awkward and not very convenient to 
> use in C.  For starters, it cannot accommodate multi-line code, except 
> via the 'do { ... } while(0);' kludge, which I think will make the code 
> less readable.  It also should set up an unwind-protect handler, so that 
> any non-local exit from the code will restore BEGV/ZV.  So I think it 
> will be better to have two separate functions (and a third one to 
> unwind).
>

Hmmm...  I'll see what I can do.  (But I don't understand why you write 
that it cannot accomodate multi-line code: you can write 
"WITH_NARROWED_BEGV (frobnicate (foo); frobnicate (bar));".)

>
> . You currently only apply the "restriction" in a few places where the 
> code calls functions like find_newline_no_quit.  What about the rest of 
> display code -- are you saying that it doesn't need to be "restricted"? 
> or do you intend to add that in the future?
>

Yes, that's what I'm saying.  You asked me to make sure that the 
restriction would have the least possible impact, which I did.

>
> And what about restricting the Lisp code invoked via 
> Vfontification_functions (i.e. jit-lock.el)?
>

That would mean that some Lisp code would not have access to the entire 
buffer, which you wanted to avoid.

>
> . Don't we want to "restrict" ZV as well?
>

It's not necessary, no.  Doing so has no performance impact AFAICS.

>
> . I'm not sure the "restriction" should be computed relative to point: 
> that might be OK for redisplaying a window, but for commands that use 
> the display code the position with which we call init_iterator and 
> start_display might be a better/safer alternative, because that position 
> could be very far from point. In any case, get_narrowed_begv receives a 
> pointer to a window, so I think it should use the window-point, not PT, 
> which is the value of point in the current buffer.
>

Okay, I'll do that.

>
> . The 10000 number should at least be a C macro if not a variable 
> exposed to Lisp.
>

Okay.

>
> . The maximum number of characters in a window could be more than just 
> its width multiplied by its height, because the window could use smaller 
> fonts than the default.  I think it is safer to use the dimensions of 
> the window's glyph matrix for this, because there couldn't possibly be 
> more characters in the window than the glyph matrix allows, and we 
> always resize the matrix when we need to display more characters.
>

Okay.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09  8:24                                                     ` Gregory Heytings
@ 2022-07-09  9:13                                                       ` Eli Zaretskii
  2022-07-09  9:39                                                         ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09  9:13 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Sat, 09 Jul 2022 08:24:38 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: larsi@gnus.org, Gerd Möllmann <gerd.moellmann@gmail.com>, 
>     56393@debbugs.gnu.org
> > I see that you decided to produce the "restriction" in init_iterator, 
> > which would, of course, work, but IMO it has a disadvantage: 
> > init_iterator is called a lot, so computing the "restriction" in it 
> > should be very fast.  Your current implementation _is_ fast, but AFAIU 
> > its result is that we _always_ restrict the display code from seeing the 
> > entire buffer, even if there are no long lines in it, which I think is 
> > unnecessary.  The original implementation only did that when it detected 
> > a long line, and I think we should keep it that way, because the 
> > "restriction" will inevitably have some negative effects, however minor, 
> > on what we display.
> 
> I don't think we can detect long lines reliably enough.  The problem of 
> the original implementation is what Gerd mentioned: "What happens when 
> evaluating an expression in *scratch* that returns a really large result? 

That problem doesn't exist when you run the detection code at the
beginning of redisplay (either in redisplay_window or in start_display
or in init_iterator), because by the time redisplay runs the buffer
text was already updated by the insertion that is the result of the
evaluation.

> Or maybe in a Shell buffer some large output?" and similar cases, like 
> inserting the result of a shell command in the buffer.  Detecting long 
> lines in insert-file-contents is not enough to make sure that Emacs will 
> always continue to behave normally when a long line is on display.

I agree, but doing this in insert-file-contents was not what I had in
mind.

> Note that we the current implementation does not always restrict display 
> code from seeing the entire buffer, it does so in a few well-chosen 
> places, everywhere else the display code sees the entire buffer.

And this is enough to make Emacs responsive?  If yes, that's great.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09  8:56                           ` Gregory Heytings
@ 2022-07-09  9:20                             ` Eli Zaretskii
  2022-07-09  9:23                               ` Eli Zaretskii
                                                 ` (2 more replies)
  2022-07-09 10:54                             ` Eli Zaretskii
  1 sibling, 3 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09  9:20 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Sat, 09 Jul 2022 08:56:16 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > . init_iterator is also called to display strings, and I'm not sure I 
> > understand what you intended to do in that case, since BEGV/ZV are not 
> > relevant to strings.
> 
> I guess moving the calculation of the restriction into start_display 
> should fix that problem.  Then it->narrowed_begv will be 0 for strings.

OK.  It wasn't celar to me what you intended to do, because
find_automatic_composition can be also invoked on strings.

> > . The WITH_NARROWED_BEGV macro is IMO awkward and not very convenient to 
> > use in C.  For starters, it cannot accommodate multi-line code, except 
> > via the 'do { ... } while(0);' kludge, which I think will make the code 
> > less readable.  It also should set up an unwind-protect handler, so that 
> > any non-local exit from the code will restore BEGV/ZV.  So I think it 
> > will be better to have two separate functions (and a third one to 
> > unwind).
> >
> 
> Hmmm...  I'll see what I can do.  (But I don't understand why you write 
> that it cannot accomodate multi-line code: you can write 
> "WITH_NARROWED_BEGV (frobnicate (foo); frobnicate (bar));".)

What if the multi-line code includes an if clause or a for loop with
just one line in their bodies?

> > . You currently only apply the "restriction" in a few places where the 
> > code calls functions like find_newline_no_quit.  What about the rest of 
> > display code -- are you saying that it doesn't need to be "restricted"? 
> > or do you intend to add that in the future?
> 
> Yes, that's what I'm saying.  You asked me to make sure that the 
> restriction would have the least possible impact, which I did.

If this is enough, then it's great.  I'm just asking myself how come
font-lock, for example, no longer slows things down as it did before?
Do you understand why?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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
  2 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09  9:23 UTC (permalink / raw)
  To: gregory; +Cc: gerd.moellmann, larsi, 56393

> Cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> Date: Sat, 09 Jul 2022 12:20:38 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> 
> > I guess moving the calculation of the restriction into start_display 
> > should fix that problem.  Then it->narrowed_begv will be 0 for strings.
> 
> OK.  It wasn't celar to me what you intended to do, because
                 ^^^^^
I meant "clear" here, sorry for the typo.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09  9:20                             ` Eli Zaretskii
  2022-07-09  9:23                               ` Eli Zaretskii
@ 2022-07-09  9:30                               ` Eli Zaretskii
  2022-07-09  9:49                               ` Gregory Heytings
  2 siblings, 0 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09  9:30 UTC (permalink / raw)
  To: gregory; +Cc: gerd.moellmann, larsi, 56393

> Cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> Date: Sat, 09 Jul 2022 12:20:38 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> 
> > > . The WITH_NARROWED_BEGV macro is IMO awkward and not very convenient to 
> > > use in C.  For starters, it cannot accommodate multi-line code, except 
> > > via the 'do { ... } while(0);' kludge, which I think will make the code 
> > > less readable.  It also should set up an unwind-protect handler, so that 
> > > any non-local exit from the code will restore BEGV/ZV.  So I think it 
> > > will be better to have two separate functions (and a third one to 
> > > unwind).
> > >
> > 
> > Hmmm...  I'll see what I can do.  (But I don't understand why you write 
> > that it cannot accomodate multi-line code: you can write 
> > "WITH_NARROWED_BEGV (frobnicate (foo); frobnicate (bar));".)
> 
> What if the multi-line code includes an if clause or a for loop with
> just one line in their bodies?

This also requires to remember NOT to use a semi-colon at the end of
the last line, which is problematic.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09  9:23                               ` Eli Zaretskii
@ 2022-07-09  9:32                                 ` Gregory Heytings
  0 siblings, 0 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-09  9:32 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393

[-- Attachment #1: Type: text/plain, Size: 179 bytes --]


>> OK.  It wasn't celar to me what you intended to do, because
>                 ^^^^^
> I meant "clear" here, sorry for the typo.
>

It was clear that it was "clear". 😉

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09  9:13                                                       ` Eli Zaretskii
@ 2022-07-09  9:39                                                         ` Gregory Heytings
  2022-07-09  9:59                                                           ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-09  9:39 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> I don't think we can detect long lines reliably enough.  The problem of 
>> the original implementation is what Gerd mentioned: "What happens when 
>> evaluating an expression in *scratch* that returns a really large 
>> result?
>
> That problem doesn't exist when you run the detection code at the 
> beginning of redisplay (either in redisplay_window or in start_display 
> or in init_iterator), because by the time redisplay runs the buffer text 
> was already updated by the insertion that is the result of the 
> evaluation.
>

Wouldn't running such detection code at the beginning of each redisplay be 
too expensive?

>> Note that we the current implementation does not always restrict 
>> display code from seeing the entire buffer, it does so in a few 
>> well-chosen places, everywhere else the display code sees the entire 
>> buffer.
>
> And this is enough to make Emacs responsive?  If yes, that's great.
>

It is.  On master C-p at the end of dictionary.json loaded "literally" 
takes 27 seconds.  Now the effect is immediate.  On master inserting a 
character there takes several (about 5) seconds, now the effect is 
immediate.  On master you cannot even move to the end of 
hugedictionary.json (the 1 GB file) for example with C-e (or perhaps you 
can, but I gave up after a few minutes).  Now you can move there 
instantly, and the effect of commands there is immediate, too.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09  9:20                             ` Eli Zaretskii
  2022-07-09  9:23                               ` Eli Zaretskii
  2022-07-09  9:30                               ` Eli Zaretskii
@ 2022-07-09  9:49                               ` Gregory Heytings
  2022-07-09 10:01                                 ` Eli Zaretskii
  2 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-09  9:49 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>>> . You currently only apply the "restriction" in a few places where the 
>>> code calls functions like find_newline_no_quit.  What about the rest 
>>> of display code -- are you saying that it doesn't need to be 
>>> "restricted"? or do you intend to add that in the future?
>>
>> Yes, that's what I'm saying.  You asked me to make sure that the 
>> restriction would have the least possible impact, which I did.
>
> If this is enough, then it's great.  I'm just asking myself how come 
> font-lock, for example, no longer slows things down as it did before? Do 
> you understand why?
>

Font lock does slow things down, see the NEWS entry.  But it also slows 
things down on much smaller files (see the long-line-excerpt.xml file I 
sent you).  As I said, to me the slowdown of font locking is a separate 
problem, as is shown by the fact that turning it off removes the remaining 
slowdowns in many/most cases.  There are in fact four separate problems 
here:

1. slowdowns caused by long lines,

2. slowdowns caused by multibyte characters in long lines (which are not 
solved by solving 1),

3. slowdowns caused by font locking,

4. slowdowns caused by major and minor modes (pre and post-command hooks 
and the like).

This bug "only" solves 1 and 2.  And as I said, I can try to look at 3 if 
you want, but not now.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09  9:39                                                         ` Gregory Heytings
@ 2022-07-09  9:59                                                           ` Eli Zaretskii
  2022-07-09 10:20                                                             ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09  9:59 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Sat, 09 Jul 2022 09:39:39 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> 
> >> I don't think we can detect long lines reliably enough.  The problem of 
> >> the original implementation is what Gerd mentioned: "What happens when 
> >> evaluating an expression in *scratch* that returns a really large 
> >> result?
> >
> > That problem doesn't exist when you run the detection code at the 
> > beginning of redisplay (either in redisplay_window or in start_display 
> > or in init_iterator), because by the time redisplay runs the buffer text 
> > was already updated by the insertion that is the result of the 
> > evaluation.
> >
> 
> Wouldn't running such detection code at the beginning of each redisplay be 
> too expensive?

I don't think so.  find_newline1 is very fast, and if we call it once
for every window, it shouldn't be a problem.  Of course, only actually
trying that will tell if I'm right or am missing something.

And maybe this is not needed at all if restricting
find_newline_no_quit is enough to solve the problem.

> >> Note that we the current implementation does not always restrict 
> >> display code from seeing the entire buffer, it does so in a few 
> >> well-chosen places, everywhere else the display code sees the entire 
> >> buffer.
> >
> > And this is enough to make Emacs responsive?  If yes, that's great.
> >
> 
> It is.  On master C-p at the end of dictionary.json loaded "literally" 
> takes 27 seconds.  Now the effect is immediate.  On master inserting a 
> character there takes several (about 5) seconds, now the effect is 
> immediate.  On master you cannot even move to the end of 
> hugedictionary.json (the 1 GB file) for example with C-e (or perhaps you 
> can, but I gave up after a few minutes).  Now you can move there 
> instantly, and the effect of commands there is immediate, too.

That's awesome, thanks.  I guess we will only need more measures if
some situations are reported where this is not fast enough, or causes
some other problems.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09  9:49                               ` Gregory Heytings
@ 2022-07-09 10:01                                 ` Eli Zaretskii
  2022-07-09 10:50                                   ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09 10:01 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Sat, 09 Jul 2022 09:49:36 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > If this is enough, then it's great.  I'm just asking myself how come 
> > font-lock, for example, no longer slows things down as it did before? Do 
> > you understand why?
> >
> 
> Font lock does slow things down, see the NEWS entry.  But it also slows 
> things down on much smaller files (see the long-line-excerpt.xml file I 
> sent you).  As I said, to me the slowdown of font locking is a separate 
> problem, as is shown by the fact that turning it off removes the remaining 
> slowdowns in many/most cases.  There are in fact four separate problems 
> here:
> 
> 1. slowdowns caused by long lines,
> 
> 2. slowdowns caused by multibyte characters in long lines (which are not 
> solved by solving 1),
> 
> 3. slowdowns caused by font locking,
> 
> 4. slowdowns caused by major and minor modes (pre and post-command hooks 
> and the like).
> 
> This bug "only" solves 1 and 2.  And as I said, I can try to look at 3 if 
> you want, but not now.

I'm asking whether applying the "restriction" where we call
Vfontification_functions from the display engine won't also solve 3.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09  9:59                                                           ` Eli Zaretskii
@ 2022-07-09 10:20                                                             ` Gregory Heytings
  2022-07-09 10:41                                                               ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-09 10:20 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>
> And maybe this is not needed at all if restricting find_newline_no_quit 
> is enough to solve the problem.
>

Indeed, that's what I think.

>
> That's awesome, thanks.  I guess we will only need more measures if some 
> situations are reported where this is not fast enough, or causes some 
> other problems.
>

I don't think it's possible to make it faster.  I forgot to mention that 
C-s works instantly, too.

To anticipate one possible criticism: this feature comes at a (IMO) very 
little price, namely that inside long lines (and only inside long lines) 
line-move-visual does always not work as expected, point sometimes moves 
to another column (but in most cases does not).  That's the only 
compromise I did, and it is unavoidable.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 10:20                                                             ` Gregory Heytings
@ 2022-07-09 10:41                                                               ` Eli Zaretskii
  2022-07-09 11:09                                                                 ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09 10:41 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Sat, 09 Jul 2022 10:20:51 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > That's awesome, thanks.  I guess we will only need more measures if some 
> > situations are reported where this is not fast enough, or causes some 
> > other problems.
> >
> 
> I don't think it's possible to make it faster.  I forgot to mention that 
> C-s works instantly, too.
> 
> To anticipate one possible criticism: this feature comes at a (IMO) very 
> little price, namely that inside long lines (and only inside long lines) 
> line-move-visual does always not work as expected, point sometimes moves 
> to another column (but in most cases does not).  That's the only 
> compromise I did, and it is unavoidable.

I'm playing with the branch, and I see some problems.  I fixed a
couple, but that's just a band-aid, I think.

Try this:

  emacs -Q
  C-x C-f src/xdisp.c RET
  M->
  C-u 37100 C-p

This signals an error "Beginning of buffer".  And if I use M-v instead
of C-p, I don't get an error message, but I don't get to the line I
wanted, either: it silently stops much earlier.

I think this is because find_newline_no_quit is not allowed to move
back far enough.  Actually detecting whether the buffer has long lines
will help to avoid this in "normal" files, but I'm not sure yet what
to do with buffers that really have long lines, or whether it matters.

Also, are you running with assertions enabled?  If not, please
configure --enable-checking='yes,glyphs', because some problems are
detected much earlier then (the ones I fixed were such problems).





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 10:01                                 ` Eli Zaretskii
@ 2022-07-09 10:50                                   ` Gregory Heytings
  2022-07-09 11:16                                     ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-09 10:50 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> Font lock does slow things down, see the NEWS entry.  But it also slows 
>> things down on much smaller files (see the long-line-excerpt.xml file I 
>> sent you).  As I said, to me the slowdown of font locking is a separate 
>> problem, as is shown by the fact that turning it off removes the 
>> remaining slowdowns in many/most cases.  There are in fact four 
>> separate problems here:
>>
>> 1. slowdowns caused by long lines,
>>
>> 2. slowdowns caused by multibyte characters in long lines (which are 
>> not solved by solving 1),
>>
>> 3. slowdowns caused by font locking,
>>
>> 4. slowdowns caused by major and minor modes (pre and post-command 
>> hooks and the like).
>>
>> This bug "only" solves 1 and 2.  And as I said, I can try to look at 3 
>> if you want, but not now.
>
> I'm asking whether applying the "restriction" where we call 
> Vfontification_functions from the display engine won't also solve 3.
>

It doesn't, see again the long-line-excerpt.xml file I sent you.  It is 
only 30K long, which would be a typical size for a restriction, and 
editing that file is slow when font locking is on and fast when font 
locking is off.

What I would do (but I'm pretty sure you wouln't agree with that) is to 
measure the time taken by fontification-functions in 
handle_fontified_prop, and whenever that time is above a certain threshold 
(say 0.25 or 0.5 seconds), to set fontification-functions to nil in that 
buffer.  For example, if you load dictionary.json (with "y") and type C-e, 
fontification-functions take about 2 seconds to complete.

But fontification-functions are not the only problem here.  What I also 
observe is that, for example, moving in a fontified buffer takes (much) 
longer than moving in a non-fontified buffer.  For example, in 
long-line.xml, vertical-motion takes about 40 ms backward and 10 ms 
forward in a non-fontified buffer, and about 180 ms backward and 40 ms 
forward in a fontified buffer.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09  8:56                           ` Gregory Heytings
  2022-07-09  9:20                             ` Eli Zaretskii
@ 2022-07-09 10:54                             ` Eli Zaretskii
  2022-07-09 11:09                               ` Eli Zaretskii
  2022-07-09 11:12                               ` Gregory Heytings
  1 sibling, 2 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09 10:54 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Sat, 09 Jul 2022 08:56:16 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > . I'm not sure the "restriction" should be computed relative to point: 
> > that might be OK for redisplaying a window, but for commands that use 
> > the display code the position with which we call init_iterator and 
> > start_display might be a better/safer alternative, because that position 
> > could be very far from point. In any case, get_narrowed_begv receives a 
> > pointer to a window, so I think it should use the window-point, not PT, 
> > which is the value of point in the current buffer.
> 
> Okay, I'll do that.

Here's one problem caused by using PT in get_narrowed_begv:

  emacs -Q
  C-x C-f src/xdisp.c RET
  C-x 2
  M->

Now move the mouse pointer over the "other" window, the one which
still shows xdisp.c at BOB, and turn the mouse wheel to scroll the
window towards the end of the buffer.  This segfaults:

  Thread 1 received signal SIGSEGV, Segmentation fault.
  0x01054f5c in get_visually_first_element (it=0x82d960) at xdisp.c:8667
  8667                   && (FETCH_BYTE (it->bidi_it.bytepos - 1) == '\n'
  (gdb) bt
  #0  0x01054f5c in get_visually_first_element (it=0x82d960) at xdisp.c:8667
  #1  0x010562b8 in next_element_from_buffer (it=0x82d960) at xdisp.c:9125
  #2  0x01052b35 in get_next_display_element (it=0x82d960) at xdisp.c:7762
  #3  0x0105704a in move_it_in_display_line_to (it=0x82d960, to_charpos=-1,
      to_x=0, op=MOVE_TO_X) at xdisp.c:9550
  #4  0x01059bcb in move_it_to (it=0x82d960, to_charpos=-1, to_x=0, to_y=119,
      to_vpos=-1, op=3) at xdisp.c:10221
  #5  0x01010aac in buffer_posn_from_coords (w=0x7c4ade8, x=0x82e90c,
      y=0x82e908, pos=0x82e920, object=0x82e938, dx=0x82e91c, dy=0x82e918,
      width=0x82e914, height=0x82e910) at dispnew.c:5539
  #6  0x0117d5a6 in make_lispy_position (f=0x75fd018, x=make_fixnum(492),
      y=make_fixnum(427), t=1403593421) at keyboard.c:5532
  #7  0x0117fae8 in make_lispy_event (event=0x1841100 <kbd_buffer+4096>)
      at keyboard.c:6157
  #8  0x01179e8d in kbd_buffer_get_event (kbp=0x82ee74,
      used_mouse_menu=0x82f43f, end_time=0x0) at keyboard.c:4241
  #9  0x011721b4 in read_event_from_main_queue (end_time=0x0,
      local_getcjmp=0x82f190, used_mouse_menu=0x82f43f) at keyboard.c:2238
  #10 0x011726d3 in read_decoded_event_from_main_queue (end_time=0x0,
      local_getcjmp=0x82f190, prev_event=XIL(0), used_mouse_menu=0x82f43f)
      at keyboard.c:2302
  #11 0x01174d50 in read_char (commandflag=1, map=XIL(0xc000000007c46380),
      prev_event=XIL(0), used_mouse_menu=0x82f43f, end_time=0x0)
      at keyboard.c:2932
  #12 0x0118d435 in read_key_sequence (keybuf=0x82f728, prompt=XIL(0),
      dont_downcase_last=false, can_return_switch_frame=true,
      fix_current_buffer=true, prevent_redisplay=false) at keyboard.c:9947
  #13 0x0116eeaf in command_loop_1 () at keyboard.c:1391
  #14 0x01270266 in internal_condition_case (bfun=0x116e774 <command_loop_1>,
      handlers=XIL(0x90), hfun=0x116d742 <cmd_error>) at eval.c:1485
  #15 0x0116e1e1 in command_loop_2 (handlers=XIL(0x90)) at keyboard.c:1132
  #16 0x0126f0ed in internal_catch (tag=XIL(0xfe70),
      func=0x116e1aa <command_loop_2>, arg=XIL(0x90)) at eval.c:1208
  #17 0x0116e14c in command_loop () at keyboard.c:1110
  #18 0x0116d1a2 in recursive_edit_1 () at keyboard.c:719
  #19 0x0116d440 in Frecursive_edit () at keyboard.c:802
  #20 0x011683aa in main (argc=2, argv=0xa42a10) at emacs.c:2517
  (gdb) p it.bidi_it.bytepos
  $1 = 1
  (gdb) p it.bidi_it.charpos
  $2 = 1
  (gdb) p bob
  $3 = 1160000
  (gdb) p it.narrowed_begv
  $4 = 1160000

The problem is that narrowed_begv was computed using PT, which doesn't
correspond to the window's point, and so the logic in
get_visually_first_element backfires.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 10:41                                                               ` Eli Zaretskii
@ 2022-07-09 11:09                                                                 ` Gregory Heytings
  2022-07-09 11:18                                                                   ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-09 11:09 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393

[-- Attachment #1: Type: text/plain, Size: 1009 bytes --]


>
> I'm playing with the branch, and I see some problems.  I fixed a
> couple,
>

Thanks.  I don't know why I forgot to check for a non-zero narrowed_begv 
in find_automatic_composition.

>
> Try this:
>
>  emacs -Q
>  C-x C-f src/xdisp.c RET
>  M->
>  C-u 37100 C-p
>
> This signals an error "Beginning of buffer".
>

Nice.  That's a recipe you concocted knowing the implementation details, 
didn't you?  😉

>
> And if I use M-v instead of C-p, I don't get an error message, but I 
> don't get to the line I wanted, either: it silently stops much earlier.
>

This I cannot reproduce, I can scroll through the whole buffer with M-v 
without any visible problems.  I tried to set the auto repeat rate to 50, 
and still do not see any problems.

>
> Also, are you running with assertions enabled?  If not, please configure 
> --enable-checking='yes,glyphs', because some problems are detected much 
> earlier then (the ones I fixed were such problems).
>

I'll do that.

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 10:54                             ` Eli Zaretskii
@ 2022-07-09 11:09                               ` Eli Zaretskii
  2022-07-09 11:12                               ` Gregory Heytings
  1 sibling, 0 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09 11:09 UTC (permalink / raw)
  To: gregory; +Cc: gerd.moellmann, larsi, 56393

> Cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> Date: Sat, 09 Jul 2022 13:54:24 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> 
> Here's one problem caused by using PT in get_narrowed_begv:
> 
>   emacs -Q
>   C-x C-f src/xdisp.c RET
>   C-x 2
>   M->

Here's another:

  emacs -Q
  C-x C-f src/xdisp.c
  C-x *of

After I type 'f' of "*of", Emacs segfaults:

  Thread 1 received signal SIGSEGV, Segmentation fault.
  0x01054f5c in get_visually_first_element (it=0x82d210) at xdisp.c:8667
  8667                   && (FETCH_BYTE (it->bidi_it.bytepos - 1) == '\n'
  (gdb) bt
  #0  0x01054f5c in get_visually_first_element (it=0x82d210) at xdisp.c:8667
  #1  0x010562b8 in next_element_from_buffer (it=0x82d210) at xdisp.c:9125
  #2  0x01052b35 in get_next_display_element (it=0x82d210) at xdisp.c:7762
  #3  0x0105704a in move_it_in_display_line_to (it=0x82d210, to_charpos=48949,
      to_x=0, op=(MOVE_TO_X | MOVE_TO_POS)) at xdisp.c:9550
  #4  0x01059bcb in move_it_to (it=0x82d210, to_charpos=48949, to_x=-1,
      to_y=543, to_vpos=-1, op=10) at xdisp.c:10221
  #5  0x01038364 in pos_visible_p (w=0x75fd230, charpos=48949, x=0x82e1fc,
      y=0x82e1f8, rtop=0x82e20c, rbot=0x82e208, rowh=0x82e204, vpos=0x82e200)
      at xdisp.c:1730
  #6  0x010c9fcc in Fpos_visible_in_window_p (pos=XIL(0), window=XIL(0),
      partially=XIL(0x30)) at window.c:2000
  #7  0x0127608d in funcall_subr (subr=0x173c8c0 <Spos_visible_in_window_p>,
      numargs=3, args=0x68b0240) at eval.c:3000
  #8  0x012e9238 in exec_byte_code (fun=XIL(0xa000000005db8a1c),
      args_template=768, nargs=3, args=0x68b0200) at bytecode.c:809
  #9  0x012765d1 in fetch_and_exec_byte_code (fun=XIL(0xa000000005e00f1c),
      args_template=512, nargs=2, args=0x82eb60) at eval.c:3045
  #10 0x01276b30 in funcall_lambda (fun=XIL(0xa000000005e00f1c), nargs=2,
      arg_vector=0x82eb60) at eval.c:3117
  #11 0x01275ae6 in funcall_general (fun=XIL(0xa000000005e00f1c), numargs=2,
      args=0x82eb60) at eval.c:2908
  #12 0x01275e42 in Ffuncall (nargs=3, args=0x82eb58) at eval.c:2958
  #13 0x0126526a in Ffuncall_interactively (nargs=3, args=0x82eb58)
      at callint.c:291
  #14 0x01276482 in funcall_subr (subr=0x1747440 <Sfuncall_interactively>,
      numargs=3, args=0x82eb58) at eval.c:3023
  #15 0x01275a7f in funcall_general (fun=XIL(0xa000000001747440), numargs=3,
      args=0x82eb58) at eval.c:2904
  #16 0x01275e42 in Ffuncall (nargs=4, args=0x82eb50) at eval.c:2958
  #17 0x01274d39 in Fapply (nargs=3, args=0x82ecc8) at eval.c:2629
  #18 0x0126599c in Fcall_interactively (function=XIL(0x4570a8c),
      record_flag=XIL(0), keys=XIL(0xa000000007a59e70)) at callint.c:384
  #19 0x0127608d in funcall_subr (subr=0x1747480 <Scall_interactively>,
      numargs=3, args=0x68b0078) at eval.c:3000
  #20 0x012e9238 in exec_byte_code (fun=XIL(0xa000000005dff734),
      args_template=1025, nargs=1, args=0x82f5b0) at bytecode.c:809
  #21 0x012765d1 in fetch_and_exec_byte_code (fun=XIL(0xa000000005dff734),
      args_template=1025, nargs=1, args=0x82f5a8) at eval.c:3045
  #22 0x01276b30 in funcall_lambda (fun=XIL(0xa000000005dff734), nargs=1,
      arg_vector=0x82f5a8) at eval.c:3117
  #23 0x01275ae6 in funcall_general (fun=XIL(0xa000000005dff734), numargs=1,
      args=0x82f5a8) at eval.c:2908
  #24 0x01275e42 in Ffuncall (nargs=2, args=0x82f5a0) at eval.c:2958
  #25 0x0116b1ce in call1 (fn=XIL(0x4440), arg1=XIL(0x4570a8c)) at lisp.h:3239
  #26 0x0116f400 in command_loop_1 () at keyboard.c:1510
  #27 0x01270266 in internal_condition_case (bfun=0x116e774 <command_loop_1>,
      handlers=XIL(0x90), hfun=0x116d742 <cmd_error>) at eval.c:1485
  #28 0x0116e1e1 in command_loop_2 (handlers=XIL(0x90)) at keyboard.c:1132
  #29 0x0126f0ed in internal_catch (tag=XIL(0xfe70),
      func=0x116e1aa <command_loop_2>, arg=XIL(0x90)) at eval.c:1208
  #30 0x0116e14c in command_loop () at keyboard.c:1110
  #31 0x0116d1a2 in recursive_edit_1 () at keyboard.c:719
  #32 0x0116d440 in Frecursive_edit () at keyboard.c:802
  #33 0x011683aa in main (argc=2, argv=0xa42a10) at emacs.c:2517

  Lisp Backtrace:
  "pos-visible-in-window-p" (0x68b0240)
  "pos-visible-in-window-group-p" (0x68b01e8)
  "isearch-update" (0x68b0198)
  "isearch-search-and-update" (0x68b0170)
  "isearch-process-search-string" (0x68b0130)
  "isearch-process-search-char" (0x68b00e0)
  "isearch-printing-char" (0x82eb60)
  "funcall-interactively" (0x82eb58)
  "call-interactively" (0x68b0078)
  "command-execute" (0x82f5a8)
  (gdb) p it->current
  $1 = {
    pos = {
      charpos = 1,
      bytepos = 1
    },
    overlay_string_index = -1,
    string_pos = {
      charpos = -1,
      bytepos = -1
    },
    dpvec_index = -1
  }
  (gdb) p it->bidi_it.bytepos
  $2 = 1
  (gdb) p bob
  $3 = 20000
  (gdb) p it->narrowed_begv
  $4 = 20000

This is because start_display was called to start from the window's
start point:

  #5  0x01038364 in pos_visible_p (w=0x75fd230, charpos=48949, x=0x82e1fc,
      y=0x82e1f8, rtop=0x82e20c, rbot=0x82e208, rowh=0x82e204, vpos=0x82e200)
      at xdisp.c:1730
  1730      move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1,
  (gdb) p top
  $6 = {
    charpos = 1,
    bytepos = 1
  }
  (gdb) p PT
  $7 = 48949
  (gdb) p w->start
  $8 = XIL(0xa00000000760a9d0)
  (gdb) xmarker
  $9 = (struct Lisp_Marker *) 0x760a9d0
  (gdb) p *$
  $10 = {
    header = {
      size = 1124081664
    },
    buffer = 0x76be1b8,
    need_adjustment = 0,
    insertion_type = 0,
    next = 0x7621158,
    charpos = 1,
    bytepos = 1
  }

In the source code it looks like this:

  SET_TEXT_POS_FROM_MARKER (top, w->start);
  [...]
  start_display (&it, w, top);
  move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1,
	      (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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
  1 sibling, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-09 11:12 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>
> Here's one problem caused by using PT in get_narrowed_begv:
>
>  emacs -Q
>  C-x C-f src/xdisp.c RET
>  C-x 2
>  M->
>
> Now move the mouse pointer over the "other" window, the one which still 
> shows xdisp.c at BOB, and turn the mouse wheel to scroll the window 
> towards the end of the buffer.  This segfaults:
>
> The problem is that narrowed_begv was computed using PT, which doesn't 
> correspond to the window's point, and so the logic in 
> get_visually_first_element backfires.
>

Yes, I understand and noted that I should use window-point instead of PT.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 10:50                                   ` Gregory Heytings
@ 2022-07-09 11:16                                     ` Eli Zaretskii
  2022-07-09 11:48                                       ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09 11:16 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Sat, 09 Jul 2022 10:50:26 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > I'm asking whether applying the "restriction" where we call 
> > Vfontification_functions from the display engine won't also solve 3.
> >
> 
> It doesn't, see again the long-line-excerpt.xml file I sent you.  It is 
> only 30K long, which would be a typical size for a restriction, and 
> editing that file is slow when font locking is on and fast when font 
> locking is off.

I guess it's because we leave ZV at its original value, and font-lock
attempts to fontify the entire long line till the end?  Does it help
to make the value of syntax-wholeline-max smaller?

> What I would do (but I'm pretty sure you wouln't agree with that) is to 
> measure the time taken by fontification-functions in 
> handle_fontified_prop, and whenever that time is above a certain threshold 
> (say 0.25 or 0.5 seconds), to set fontification-functions to nil in that 
> buffer.

You could instead look at the value of the "redisplay tick count"
collected by update_redisplay_ticks.  (That is only called if
max-redisplay-ticks is non-zero, but you could set it to some large
value, so that it never actually signals an error.)

> But fontification-functions are not the only problem here.  What I also 
> observe is that, for example, moving in a fontified buffer takes (much) 
> longer than moving in a non-fontified buffer.  For example, in 
> long-line.xml, vertical-motion takes about 40 ms backward and 10 ms 
> forward in a non-fontified buffer, and about 180 ms backward and 40 ms 
> forward in a fontified buffer.

I guess that's because vertical-motion calls the display code, and
that calls fontification-functions.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 11:09                                                                 ` Gregory Heytings
@ 2022-07-09 11:18                                                                   ` Eli Zaretskii
  2022-07-09 11:38                                                                     ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09 11:18 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Sat, 09 Jul 2022 11:09:40 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> >  emacs -Q
> >  C-x C-f src/xdisp.c RET
> >  M->
> >  C-u 37100 C-p
> >
> > This signals an error "Beginning of buffer".
> >
> 
> Nice.  That's a recipe you concocted knowing the implementation details, 
> didn't you?  😉

Of course ;-)

> > And if I use M-v instead of C-p, I don't get an error message, but I 
> > don't get to the line I wanted, either: it silently stops much earlier.
> >
> 
> This I cannot reproduce, I can scroll through the whole buffer with M-v 
> without any visible problems.  I tried to set the auto repeat rate to 50, 
> and still do not see any problems.

No, I meant this:

  C-u 37100 M-v





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 11:12                               ` Gregory Heytings
@ 2022-07-09 11:20                                 ` Gregory Heytings
  2022-07-09 12:29                                   ` Lars Ingebrigtsen
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-09 11:20 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> Here's one problem caused by using PT in get_narrowed_begv:
>>
>>  emacs -Q
>>  C-x C-f src/xdisp.c RET
>>  C-x 2
>>  M->
>> 
>> Now move the mouse pointer over the "other" window, the one which still 
>> shows xdisp.c at BOB, and turn the mouse wheel to scroll the window 
>> towards the end of the buffer.  This segfaults:
>> 
>> The problem is that narrowed_begv was computed using PT, which doesn't 
>> correspond to the window's point, and so the logic in 
>> get_visually_first_element backfires.
>
> Yes, I understand and noted that I should use window-point instead of 
> PT.
>

(That being said, I cannot reproduce that here either.)





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 11:18                                                                   ` Eli Zaretskii
@ 2022-07-09 11:38                                                                     ` Gregory Heytings
  2022-07-09 11:48                                                                       ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-09 11:38 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393

[-- Attachment #1: Type: text/plain, Size: 423 bytes --]


>>>  emacs -Q
>>>  C-x C-f src/xdisp.c RET
>>>  M->
>>>  C-u 37100 C-p
>>>
>>> This signals an error "Beginning of buffer".
>>
>> Nice.  That's a recipe you concocted knowing the implementation 
>> details, didn't you?  😉
>
> Of course ;-)
>

Then here's another recipe with long lines detection enabled:

emacs -Q
C-x C-f src/xdisp.c RET
C-n
C-x i .../dictionary.json RET
M->
C-u 37100 C-p

😉

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 11:38                                                                     ` Gregory Heytings
@ 2022-07-09 11:48                                                                       ` Eli Zaretskii
  2022-07-09 12:01                                                                         ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09 11:48 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Sat, 09 Jul 2022 11:38:17 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> Then here's another recipe with long lines detection enabled:
> 
> emacs -Q
> C-x C-f src/xdisp.c RET
> C-n
> C-x i .../dictionary.json RET
> M->
> C-u 37100 C-p

Where can I get a one-line dictionary.json file?  I don't think I have
it here.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 11:16                                     ` Eli Zaretskii
@ 2022-07-09 11:48                                       ` Gregory Heytings
  2022-07-09 11:59                                         ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-09 11:48 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> It doesn't, see again the long-line-excerpt.xml file I sent you.  It is 
>> only 30K long, which would be a typical size for a restriction, and 
>> editing that file is slow when font locking is on and fast when font 
>> locking is off.
>
> I guess it's because we leave ZV at its original value, and font-lock 
> attempts to fontify the entire long line till the end?  Does it help to 
> make the value of syntax-wholeline-max smaller?
>

Sorry, I wasn't clear enough: I meant opening that file with Emacs from 
master.  Given that it's only 30K long, which would be a typical size for 
a temporarily narrowed buffer, and that editing it is slow, I don't see 
how applying a narrowing similar to the size of that file before calling 
fontification-functions could possibly help.

>> But fontification-functions are not the only problem here.  What I also 
>> observe is that, for example, moving in a fontified buffer takes (much) 
>> longer than moving in a non-fontified buffer.  For example, in 
>> long-line.xml, vertical-motion takes about 40 ms backward and 10 ms 
>> forward in a non-fontified buffer, and about 180 ms backward and 40 ms 
>> forward in a fontified buffer.
>
> I guess that's because vertical-motion calls the display code, and that 
> calls fontification-functions.
>

No, fontification-functions are not called when moving around in an 
already fontified portion of the buffer.  So the slowdown of C-n and C-p 
(and others) in that case is not caused by fontification-functions.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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:09                                           ` Ihor Radchenko
  0 siblings, 2 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09 11:59 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Sat, 09 Jul 2022 11:48:27 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> >> But fontification-functions are not the only problem here.  What I also 
> >> observe is that, for example, moving in a fontified buffer takes (much) 
> >> longer than moving in a non-fontified buffer.  For example, in 
> >> long-line.xml, vertical-motion takes about 40 ms backward and 10 ms 
> >> forward in a non-fontified buffer, and about 180 ms backward and 40 ms 
> >> forward in a fontified buffer.
> >
> > I guess that's because vertical-motion calls the display code, and that 
> > calls fontification-functions.
> >
> 
> No, fontification-functions are not called when moving around in an 
> already fontified portion of the buffer.  So the slowdown of C-n and C-p 
> (and others) in that case is not caused by fontification-functions.

That's very strange, since AFAIK moving in a non-fontified buffer
involves both fontifications and display of the fontified text,
whereas moving through a fontified buffer involves only the latter.
FWIW, I've _never_ seen movement through fontified buffer being slower
than in a non-fontified one.  I'd be very interested to know what
slows down the movement in a fontified buffer.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 11:48                                                                       ` Eli Zaretskii
@ 2022-07-09 12:01                                                                         ` Gregory Heytings
  2022-07-09 12:24                                                                           ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-09 12:01 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> Then here's another recipe with long lines detection enabled:
>>
>> emacs -Q
>> C-x C-f src/xdisp.c RET
>> C-n
>> C-x i .../dictionary.json RET
>> M->
>> C-u 37100 C-p
>
> Where can I get a one-line dictionary.json file?  I don't think I have 
> it here.
>

It's here: https://github.com/Wilfred/ReVo-utilities/blob/a4bdc40dd2656c496defc461fc19c403c8306d9f/revo-export/dictionary.json?raw=true

Then you can obtain the 1GB file with:

for I in $(seq 1 60); do cat dictionary.json; done > hugedictionary.json

(Note that I did not actually try the above recipe, it's just meant to 
show that there will always be corner cases that won't be handled, even 
with a dynamic detection of long lines.)





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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:09                                           ` Ihor Radchenko
  1 sibling, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-09 12:07 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>
> That's very strange, since AFAIK moving in a non-fontified buffer 
> involves both fontifications and display of the fontified text, whereas 
> moving through a fontified buffer involves only the latter. FWIW, I've 
> _never_ seen movement through fontified buffer being slower than in a 
> non-fontified one.
>

Try the dictionary.json or the long-line.xml file with and without 
font-lock-mode.  Also try

emacs -Q
C-x C-f dictionary.json RET
y
C-s aan zich RET

and

emacs -Q
C-x C-f dictionary.json RET
y
M-x font-lock-mode
C-s aan zich RET

The first takes several seconds, the second is almost instantaneous.

>
> I'd be very interested to know what slows down the movement in a 
> fontified buffer.
>

One problem at a time, okay?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 11:59                                         ` Eli Zaretskii
  2022-07-09 12:07                                           ` Gregory Heytings
@ 2022-07-09 12:09                                           ` Ihor Radchenko
  2022-07-09 12:37                                             ` Eli Zaretskii
  1 sibling, 1 reply; 205+ messages in thread
From: Ihor Radchenko @ 2022-07-09 12:09 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, Gregory Heytings, larsi, 56393

Eli Zaretskii <eliz@gnu.org> writes:

>> No, fontification-functions are not called when moving around in an 
>> already fontified portion of the buffer.  So the slowdown of C-n and C-p 
>> (and others) in that case is not caused by fontification-functions.
>
> That's very strange, since AFAIK moving in a non-fontified buffer
> involves both fontifications and display of the fontified text,
> whereas moving through a fontified buffer involves only the latter.
> FWIW, I've _never_ seen movement through fontified buffer being slower
> than in a non-fontified one.  I'd be very interested to know what
> slows down the movement in a fontified buffer.

I am not sure if it is related, but I do observe a slowdown when moving
across fontified buffer. This happens in really large buffers when
moving across invisible text. AFAIU, line-move-1 uses
next-single-property-change loop, which could be costly when the region
has a large number of discontinuous text properties.

In the scenario here, I doubt that invisible text is present. Still, it
might be worth checking for the code that loops over text property
regions.

Best,
Ihor





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 12:01                                                                         ` Gregory Heytings
@ 2022-07-09 12:24                                                                           ` Eli Zaretskii
  2022-07-09 12:31                                                                             ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09 12:24 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Sat, 09 Jul 2022 12:01:17 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > Where can I get a one-line dictionary.json file?  I don't think I have 
> > it here.
> >
> 
> It's here: https://github.com/Wilfred/ReVo-utilities/blob/a4bdc40dd2656c496defc461fc19c403c8306d9f/revo-export/dictionary.json?raw=true

Thanks.

> (Note that I did not actually try the above recipe, it's just meant to 
> show that there will always be corner cases that won't be handled, even 
> with a dynamic detection of long lines.)

I think arbitrarily limiting C-p in buffers that don't have long lines
will be deemed a regression.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 11:20                                 ` Gregory Heytings
@ 2022-07-09 12:29                                   ` Lars Ingebrigtsen
  2022-07-09 12:38                                     ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Lars Ingebrigtsen @ 2022-07-09 12:29 UTC (permalink / raw)
  To: Gregory Heytings, Eli Zaretskii; +Cc: 56393

[-- Attachment #1: Type: text/plain, Size: 350 bytes --]

Using a probalistic approach for turning the auto narrow mode on might work? I.e., check for long lines in insert-file, but also if the buffer has increased a lot in size, or many modtics, or many display ticks.

That way we'd avoid issues with the mode in normal buffers
-- 
Sent from my Android device with K-9 Mail since Emacs doesn't run here

[-- Attachment #2: Type: text/html, Size: 472 bytes --]

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 12:24                                                                           ` Eli Zaretskii
@ 2022-07-09 12:31                                                                             ` Gregory Heytings
  0 siblings, 0 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-09 12:31 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> (Note that I did not actually try the above recipe, it's just meant to 
>> show that there will always be corner cases that won't be handled, even 
>> with a dynamic detection of long lines.)
>
> I think arbitrarily limiting C-p in buffers that don't have long lines 
> will be deemed a regression.
>

I bet that we won't have a single bug report about this.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 12:07                                           ` Gregory Heytings
@ 2022-07-09 12:34                                             ` Eli Zaretskii
  2022-07-09 12:36                                               ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09 12:34 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Sat, 09 Jul 2022 12:07:55 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> 
> >
> > That's very strange, since AFAIK moving in a non-fontified buffer 
> > involves both fontifications and display of the fontified text, whereas 
> > moving through a fontified buffer involves only the latter. FWIW, I've 
> > _never_ seen movement through fontified buffer being slower than in a 
> > non-fontified one.
> >
> 
> Try the dictionary.json or the long-line.xml file with and without 
> font-lock-mode.  Also try
> 
> emacs -Q
> C-x C-f dictionary.json RET
> y
> C-s aan zich RET
> 
> and
> 
> emacs -Q
> C-x C-f dictionary.json RET
> y
> M-x font-lock-mode
> C-s aan zich RET
> 
> The first takes several seconds, the second is almost instantaneous.

Ah, I misunderstood what you were saying.

But you originally talked about C-n and vertical-motion, not about
C-s.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 12:34                                             ` Eli Zaretskii
@ 2022-07-09 12:36                                               ` Gregory Heytings
  0 siblings, 0 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-09 12:36 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> The first takes several seconds, the second is almost instantaneous.
>
> Ah, I misunderstood what you were saying.
>
> But you originally talked about C-n and vertical-motion, not about C-s.
>

Yes, what I meant is that the effect is visible both with C-n / C-p and 
with C-s.  And probably with other commands.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 12:09                                           ` Ihor Radchenko
@ 2022-07-09 12:37                                             ` Eli Zaretskii
  0 siblings, 0 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-09 12:37 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: gerd.moellmann, gregory, larsi, 56393

> From: Ihor Radchenko <yantar92@gmail.com>
> Cc: Gregory Heytings <gregory@heytings.org>,  gerd.moellmann@gmail.com,
>   larsi@gnus.org,  56393@debbugs.gnu.org
> Date: Sat, 09 Jul 2022 20:09:42 +0800
> 
> I am not sure if it is related, but I do observe a slowdown when moving
> across fontified buffer. This happens in really large buffers when
> moving across invisible text. AFAIU, line-move-1 uses
> next-single-property-change loop, which could be costly when the region
> has a large number of discontinuous text properties.

Invisible text is a different matter altogether.  The problem there is
that the amount of text on the screen is very different from what's
actually in the buffer, and moving through such a buffer needs to skip
the invisible text, which isn't free.

Face properties don't have such an effect.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 12:29                                   ` Lars Ingebrigtsen
@ 2022-07-09 12:38                                     ` Gregory Heytings
  2022-07-16 19:39                                       ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-09 12:38 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: Eli Zaretskii, 56393

[-- Attachment #1: Type: text/plain, Size: 459 bytes --]


>
> Using a probalistic approach for turning the auto narrow mode on might 
> work? I.e., check for long lines in insert-file, but also if the buffer 
> has increased a lot in size, or many modtics, or many display ticks.
>
> That way we'd avoid issues with the mode in normal buffers--
>

That's a neat idea, thanks.

>
> Sent from my Android device with K-9 Mail since Emacs doesn't run here
>

You could run Emacs inside an SSH session 😉

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-09 12:38                                     ` Gregory Heytings
@ 2022-07-16 19:39                                       ` Gregory Heytings
  2022-07-17 15:21                                         ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-16 19:39 UTC (permalink / raw)
  To: Eli Zaretskii, Lars Ingebrigtsen; +Cc: 56393


I just pushed several improvements to the feature branch.

A few comments:

It turns out that it is not possible to calculate the restriction in 
start_display and/or in redisplay_window, because the restriction must 
also be used outside of redisplay.  I tried various approaches, and my 
conclusion is that the best place to calculate the restriction is 
init_iterator.

Using the size of the glyph matrix also turned out to be impractical, 
because the glyph matrix grows when the default font size becomes smaller 
(for example with C-x C-M--) but does not shrink when it becomes larger 
(with C-x C-M-+).  So I've used another formula, still based on 
window_body_{width,height}.

The optimizations now only apply to buffers which contain long lines, so 
the C-u 37100 C-p recipe in xdisp.c works as expected.

I also replaced the WITH_NARROWED_BEGV macro with another one, 
SET_WITH_NARROWED_BEGV.  I'm not convinced that defining another function, 
for example find_newline_no_quit_with_narrowed_begv, would be optimal, 
especially given that there is (in get_visually_first_element) a simple 
assignment that must be evaluated with a narrowed BEGV.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-16 19:39                                       ` Gregory Heytings
@ 2022-07-17 15:21                                         ` Eli Zaretskii
  2022-07-17 15:37                                           ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-17 15:21 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: larsi, 56393

> Date: Sat, 16 Jul 2022 19:39:18 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: 56393@debbugs.gnu.org
> 
> 
> I just pushed several improvements to the feature branch.

Thanks.

I still see a segfault in get_visually_first_element.  To reproduce:

  emacs -Q
  C-x C-f long-line.xml
  C-u 12 M-g g
  C-s C-q C-j

IOW, go to line 12 and search for a newline.  I think this segfaults
because point is very far from window-start, so the narrowing doesn't
include the position where get_visually_first_element is called.

Similarly, this also segfaults:

  emacs -Q
  C-x C-f long-line.xml
  C-u 15000 M-g c
  C-x 2





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-17 15:21                                         ` Eli Zaretskii
@ 2022-07-17 15:37                                           ` Gregory Heytings
  2022-07-17 16:00                                             ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-17 15:37 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: larsi, 56393


>
> I still see a segfault in get_visually_first_element.  To reproduce:
>
> emacs -Q
> C-x C-f long-line.xml
> C-u 12 M-g g
> C-s C-q C-j
>
> IOW, go to line 12 and search for a newline.  I think this segfaults 
> because point is very far from window-start, so the narrowing doesn't 
> include the position where get_visually_first_element is called.
>
> Similarly, this also segfaults:
>
> emacs -Q
> C-x C-f long-line.xml
> C-u 15000 M-g c
> C-x 2
>

Thanks.  I can't reproduce either of these two bugs with a regular build, 
both of these recipes produce the expected result.  Are these segfaults 
due to --enable-checking?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-17 15:37                                           ` Gregory Heytings
@ 2022-07-17 16:00                                             ` Eli Zaretskii
  2022-07-18 10:19                                               ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-17 16:00 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: larsi, 56393

> Date: Sun, 17 Jul 2022 15:37:08 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: larsi@gnus.org, 56393@debbugs.gnu.org
> 
> 
> >
> > I still see a segfault in get_visually_first_element.  To reproduce:
> >
> > emacs -Q
> > C-x C-f long-line.xml
> > C-u 12 M-g g
> > C-s C-q C-j
> >
> > IOW, go to line 12 and search for a newline.  I think this segfaults 
> > because point is very far from window-start, so the narrowing doesn't 
> > include the position where get_visually_first_element is called.
> >
> > Similarly, this also segfaults:
> >
> > emacs -Q
> > C-x C-f long-line.xml
> > C-u 15000 M-g c
> > C-x 2
> >
> 
> Thanks.  I can't reproduce either of these two bugs with a regular build, 
> both of these recipes produce the expected result.  Are these segfaults 
> due to --enable-checking?

No, I don't think so.  --enable-checking produces SIGABRT, not
SIGSEGV.

The segfault happens because it->bidi_it.bytepos is 1, and FETCH_BYTE
cannot be called with a zero argument.  Here's a relevant portion of a
debugging session:

  Thread 1 received signal SIGSEGV, Segmentation fault.
  0x01055028 in get_visually_first_element (it=0x82d250) at xdisp.c:8691
  8691                   && (FETCH_BYTE (it->bidi_it.bytepos - 1) == '\n'
  (gdb) bt
  #0  0x01055028 in get_visually_first_element (it=0x82d250) at xdisp.c:8691
  #1  0x010563d4 in next_element_from_buffer (it=0x82d250) at xdisp.c:9149
  #2  0x01052bd3 in get_next_display_element (it=0x82d250) at xdisp.c:7786
  #3  0x01057166 in move_it_in_display_line_to (it=0x82d250, to_charpos=306655,
      to_x=0, op=(MOVE_TO_X | MOVE_TO_POS)) at xdisp.c:9574
  #4  0x01059ce7 in move_it_to (it=0x82d250, to_charpos=306655, to_x=-1,
      to_y=543, to_vpos=-1, op=10) at xdisp.c:10245
  #5  0x01038364 in pos_visible_p (w=0x75fd640, charpos=306655, x=0x82e23c,
      y=0x82e238, rtop=0x82e24c, rbot=0x82e248, rowh=0x82e244, vpos=0x82e240)
      at xdisp.c:1730
  #6  0x010ca308 in Fpos_visible_in_window_p (pos=XIL(0), window=XIL(0),
      partially=XIL(0x30)) at window.c:2000
  #7  0x01276489 in funcall_subr (subr=0x173c8c0 <Spos_visible_in_window_p>,
      numargs=3, args=0x68b0248) at eval.c:3000
  #8  0x012e9634 in exec_byte_code (fun=XIL(0xa000000005db8a1c),
      args_template=768, nargs=3, args=0x68b0208) at bytecode.c:809
  #9  0x012769cd in fetch_and_exec_byte_code (fun=XIL(0xa000000005db9bdc),
      args_template=256, nargs=1, args=0x82ebd0) at eval.c:3045
  #10 0x01276f2c in funcall_lambda (fun=XIL(0xa000000005db9bdc), nargs=1,
      arg_vector=0x82ebd0) at eval.c:3117
  #11 0x01275ee2 in funcall_general (fun=XIL(0xa000000005db9bdc), numargs=1,
      args=0x82ebd0) at eval.c:2908
  #12 0x0127623e in Ffuncall (nargs=2, args=0x82ebc8) at eval.c:2958
  #13 0x01265666 in Ffuncall_interactively (nargs=2, args=0x82ebc8)
      at callint.c:291
  #14 0x0127687e in funcall_subr (subr=0x1747440 <Sfuncall_interactively>,
      numargs=2, args=0x82ebc8) at eval.c:3023
  #15 0x01275e7b in funcall_general (fun=XIL(0xa000000001747440), numargs=2,
      args=0x82ebc8) at eval.c:2904
  #16 0x0127623e in Ffuncall (nargs=3, args=0x82ebc0) at eval.c:2958
  #17 0x01268869 in Fcall_interactively (function=XIL(0x452974c),
      record_flag=XIL(0), keys=XIL(0xa0000000076986d8)) at callint.c:829
  #18 0x01276489 in funcall_subr (subr=0x1747480 <Scall_interactively>,
      numargs=3, args=0x68b0078) at eval.c:3000
  #19 0x012e9634 in exec_byte_code (fun=XIL(0xa000000005dff734),
      args_template=1025, nargs=1, args=0x82f5b0) at bytecode.c:809
  #20 0x012769cd in fetch_and_exec_byte_code (fun=XIL(0xa000000005dff734),
      args_template=1025, nargs=1, args=0x82f5a8) at eval.c:3045
  #21 0x01276f2c in funcall_lambda (fun=XIL(0xa000000005dff734), nargs=1,
      arg_vector=0x82f5a8) at eval.c:3117
  #22 0x01275ee2 in funcall_general (fun=XIL(0xa000000005dff734), numargs=1,
      args=0x82f5a8) at eval.c:2908
  #23 0x0127623e in Ffuncall (nargs=2, args=0x82f5a0) at eval.c:2958
  #24 0x0116b50a in call1 (fn=XIL(0x4440), arg1=XIL(0x452974c)) at lisp.h:3239
  #25 0x0116f73c in command_loop_1 () at keyboard.c:1510
  #26 0x01270662 in internal_condition_case (bfun=0x116eab0 <command_loop_1>,
      handlers=XIL(0x90), hfun=0x116da7e <cmd_error>) at eval.c:1485
  #27 0x0116e51d in command_loop_2 (handlers=XIL(0x90)) at keyboard.c:1132
  #28 0x0126f4e9 in internal_catch (tag=XIL(0xfe70),
      func=0x116e4e6 <command_loop_2>, arg=XIL(0x90)) at eval.c:1208
  #29 0x0116e488 in command_loop () at keyboard.c:1110
  #30 0x0116d4de in recursive_edit_1 () at keyboard.c:719
  #31 0x0116d77c in Frecursive_edit () at keyboard.c:802
  #32 0x011686e6 in main (argc=2, argv=0xa42a10) at emacs.c:2517

  Lisp Backtrace:
  "pos-visible-in-window-p" (0x68b0248)
  "pos-visible-in-window-group-p" (0x68b01f0)
  "isearch-update" (0x68b01a0)
  "isearch-search-and-update" (0x68b0178)
  "isearch-process-search-string" (0x68b0138)
  "isearch-process-search-char" (0x68b00d8)
  "isearch-quote-char" (0x82ebd0)
  "funcall-interactively" (0x82ebc8)
  "call-interactively" (0x68b0078)
  "command-execute" (0x82f5a8)
  (gdb) p it.bidi_it.bytepos
  $1 = 1
  (gdb) p bob
  $2 = 293760
  (gdb) p it->current
  $3 = {
    pos = {
      charpos = 1,
      bytepos = 1
    },
    overlay_string_index = -1,
    string_pos = {
      charpos = -1,
      bytepos = -1
    },
    dpvec_index = -1
  }






^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Soon also looking at your branch
  2022-07-05  8:49 bug#56393: Actually fix the long lines display bug Gregory Heytings
  2022-07-05  9:28 ` Gregory Heytings
@ 2022-07-18  9:44 ` Gerd Möllmann
  2022-07-18 10:11   ` Michael Albinus
  2022-07-18 10:49   ` Gregory Heytings
  1 sibling, 2 replies; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-18  9:44 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: 56393


[-- Attachment #1.1.1.1: Type: text/plain, Size: 1943 bytes --]

In case it matters, I'll soon also take a look at this.

Soon because I'm currently a bit frustrated by all the things that don't 
work on my system here, or don't work as I would expect.  It started 
today by debbugs.el not displaying all messages under this bug report 
that I can see under the bug on the web, and me not finding any way to 
force it to load all messages.  And it continued that way the whole 
morning...

Ca-tas-tro-phy.

Whatever.

Is it correct that the differences in your branch are that small?  I 
see, in the summary of Magit's equivalent to "git diff master..." only

13 files changed, 114 insertions(+), 79 deletions(-)
doc/emacs/emacs.texi             |  1 -
doc/emacs/trouble.texi           | 59 -------------------------------
etc/NEWS                         | 24 +++++++------
lisp/{ => obsolete}/longlines.el |  1 +
src/buffer.c                     | 10 ++++++
src/buffer.h                     |  4 +++
src/composite.c                  |  6 ++++
src/dispextern.h                 |  5 +++
src/lisp.h                       |  2 ++
src/search.c                     |  2 +-
src/window.c                     |  2 +-
src/window.h                     |  1 +
src/xdisp.c                      | 76 
++++++++++++++++++++++++++++++++++++----

I'm on

*Head:     66704fbbcf Fix typo in e7b5912b23.
*

That's only ~100 lines of code?  Can that be?  I'm suspecting that I 
don't use Magit right, again.  Or something.

Also, would it be a good idea to rebase the branch on master?  That 
would make it possible for me to run the branch OOTB with ASAN.  I did 
that locally here, because I don't want to interfere with your work, so...


[-- Attachment #1.1.1.2: Type: text/html, Size: 2819 bytes --]

[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3211 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Soon also looking at your branch
  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 10:49   ` Gregory Heytings
  1 sibling, 1 reply; 205+ messages in thread
From: Michael Albinus @ 2022-07-18 10:11 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: Gregory Heytings, 56393

Gerd Möllmann <gerd.moellmann@gmail.com> writes:

Hi Gerd,

> It started today by debbugs.el not displaying all messages under this
> bug report that I can see under the bug on the web, and me not finding
> any way to force it to load all messages.

It's a long thread. Could you pls tell the message numbers (from the
web) which are not displayed in debbugs.el? I'd like to debug it.

Best regards, Michael.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-17 16:00                                             ` Eli Zaretskii
@ 2022-07-18 10:19                                               ` Gregory Heytings
  2022-07-18 12:20                                                 ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-18 10:19 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: larsi, 56393


>> I can't reproduce either of these two bugs with a regular build, both 
>> of these recipes produce the expected result.  Are these segfaults due 
>> to --enable-checking?
>
> No, I don't think so.  --enable-checking produces SIGABRT, not SIGSEGV.
>

Yes, I know, but it's possible that some checking causes a segfault.

>
> The segfault happens because it->bidi_it.bytepos is 1, and FETCH_BYTE 
> cannot be called with a zero argument.  Here's a relevant portion of a 
> debugging session:
>

Thanks.  With that indication, and after adding assertions in the code, I 
could make Emacs abort when that problem occurred.  I pushed a fix a few 
minutes ago.

But I'm still unable to reproduce your second recipe.  I tried again and 
again, both with a regular and a checking-enable build, with and without 
the fix for the first recipe, and with various frame sizes... but without 
success.  If you can still reproduce it with the fix, could you perhaps 
send me a backtrace?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Soon also looking at your branch
  2022-07-18 10:11   ` Michael Albinus
@ 2022-07-18 10:26     ` Gerd Möllmann
  2022-07-18 11:43       ` Michael Albinus
  0 siblings, 1 reply; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-18 10:26 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Gregory Heytings, 56393


[-- Attachment #1.1.1: Type: text/plain, Size: 1158 bytes --]


On 22-07-18 12:11 , Michael Albinus wrote:
> It's a long thread. Could you pls tell the message numbers (from the
> web) which are not displayed in debbugs.el? I'd like to debug it.
>
This one doesn't show up:https://debbugs.gnu.org/cgi/bugreport.cgi?bug=56393#365

The last lines of the article list I see it:

  .  2022-07-06 16:13  Eli Zaretskii           │   │   ╰►  (-1)
  .  2022-07-06 16:27  Gregory Heyting         │   │    ╰►  (-1)
  .  2022-07-06 18:53  Eli Zaretskii           │   │     ╰►  (-1)
  .  2022-07-06 19:17  Gregory Heyting         │   │      ╰►  (-1)
  .  2022-07-06 19:30  Eli Zaretskii           │   │       ╰►  (-1)
  .  2022-07-06 23:53  Gregory Heyting         │   │        ╰► (-1)
  .  2022-07-06 11:49  -> Gregory Heyt         │   ╰►  (-1)
  .  2022-07-06 12:21  Gregory Heyting         │    ╰►  (-1)
  .  2022-07-05 17:21  Robert Pluim            ╰►  (-1)

The -1 is strange, too


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3211 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Soon also looking at your branch
  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:49   ` Gregory Heytings
  2022-07-19  8:21     ` bug#56393: Actually fix the long lines display bug Gerd Möllmann
  1 sibling, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-18 10:49 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: 56393

[-- Attachment #1: Type: text/plain, Size: 235 bytes --]


> 
> That's only ~100 lines of code?  Can that be?  I'm suspecting that I 
> don't use Magit right, again.  Or something.
>

You're using Magit right: it's indeed a small fix.

Your comments would be most welcome, of course.

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Soon also looking at your branch
  2022-07-18 10:26     ` Gerd Möllmann
@ 2022-07-18 11:43       ` Michael Albinus
  2022-07-18 12:15         ` Gerd Möllmann
  0 siblings, 1 reply; 205+ messages in thread
From: Michael Albinus @ 2022-07-18 11:43 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: Gregory Heytings, 56393

[-- Attachment #1: Type: text/plain, Size: 1675 bytes --]

Gerd Möllmann <gerd.moellmann@gmail.com> writes:

Hi Gerd,

> On 22-07-18 12:11 , Michael Albinus wrote:
>> It's a long thread. Could you pls tell the message numbers (from the
>> web) which are not displayed in debbugs.el? I'd like to debug it.
>>
> This one doesn't show up:https://debbugs.gnu.org/cgi/bugreport.cgi?bug=56393#365

This is Message-Id <83v8rvpxx7.fsf@gnu.org>, I see it in the debbugs
mail buffer. See attached screenshot.

Which mail backend do you use (debbugs-gnu-mail-backend)? I'm on
gnus. But also with the rmail backend, that message is there (see second
attachment).

Do you have aspecial gnus or rmail config, which suppresses some
messages to be shown?

> The last lines of the article list I see it:
>
>  .  2022-07-06 16:13  Eli Zaretskii           │   │   ╰►  (-1)
>  .  2022-07-06 16:27  Gregory Heyting         │   │    ╰►  (-1)
>  .  2022-07-06 18:53  Eli Zaretskii           │   │     ╰►  (-1)
>  .  2022-07-06 19:17  Gregory Heyting         │   │      ╰►  (-1)
>  .  2022-07-06 19:30  Eli Zaretskii           │   │       ╰►  (-1)
>  .  2022-07-06 23:53  Gregory Heyting         │   │        ╰► (-1)
>  .  2022-07-06 11:49  -> Gregory Heyt         │   ╰►  (-1)
>  .  2022-07-06 12:21  Gregory Heyting         │    ╰►  (-1)
>  .  2022-07-05 17:21  Robert Pluim            ╰►  (-1)
>
> The -1 is strange, too

Indeed. Is this gnus or rmail? Which config?

Best regards, Michael.


[-- Attachment #2: Screenshot from 2022-07-18 13-29-36.png --]
[-- Type: image/png, Size: 209888 bytes --]

[-- Attachment #3: Screenshot from 2022-07-18 13-37-41.png --]
[-- Type: image/png, Size: 214512 bytes --]

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Soon also looking at your branch
  2022-07-18 11:43       ` Michael Albinus
@ 2022-07-18 12:15         ` Gerd Möllmann
  2022-07-18 12:19           ` Michael Albinus
  0 siblings, 1 reply; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-18 12:15 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Gregory Heytings, 56393


[-- Attachment #1.1.1: Type: text/plain, Size: 1317 bytes --]


On 22-07-18 13:43 , Michael Albinus wrote:
> This is Message-Id <83v8rvpxx7.fsf@gnu.org>, I see it in the debbugs
> mail buffer. See attached screenshot.
>
> Which mail backend do you use (debbugs-gnu-mail-backend)? I'm on
> gnus. But also with the rmail backend, that message is there (see second
> attachment).
>
> Do you have aspecial gnus or rmail config, which suppresses some
> messages to be shown?

Now it get's interesting...

I'm trying out Spacemacs with the help of chemacs2.  I have one 
non-spacemacs profile, which uses the Gnus that Emacs comes with, and I 
have a spacemacs profile in which I use the spacemacs "layer" for Gnus.  
I can start both profiles, also at the same time with "emacs 
--with-profile default", and "emacs --with-profile spacemacs".

Now, guess what:

Debbugs works fine with the non-spacemacs profile, and shows the -1 and 
whatnot with spacemacs profile, running side by side.

F*** me backw***!

Something in that spacemacs "gnus" layer must have something to do with 
this.

Thanks for helping me with this!  I think this is clearly a user error, 
the user being me.

(I guess I'll no longer use spacemacs. It's very discoverable, and good 
for one's hands, no doubt, but also not very transparent when something 
goes wrong...)



[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3211 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Soon also looking at your branch
  2022-07-18 12:15         ` Gerd Möllmann
@ 2022-07-18 12:19           ` Michael Albinus
  0 siblings, 0 replies; 205+ messages in thread
From: Michael Albinus @ 2022-07-18 12:19 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: Gregory Heytings, 56393

Gerd Möllmann <gerd.moellmann@gmail.com> writes:

Hi Gerd,

> Thanks for helping me with this! I think this is clearly a user
> error, the user being me.

Thanks for the feedback. I was a little bit nervous about a hidden
debbugs.el error.

Best regards, Michael.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 10:19                                               ` Gregory Heytings
@ 2022-07-18 12:20                                                 ` Eli Zaretskii
  2022-07-18 12:58                                                   ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-18 12:20 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: Gerd Möllmann, larsi, 56393

> Date: Mon, 18 Jul 2022 10:19:28 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: larsi@gnus.org, 56393@debbugs.gnu.org
> 
> >> I can't reproduce either of these two bugs with a regular build, both 
> >> of these recipes produce the expected result.  Are these segfaults due 
> >> to --enable-checking?
> >
> > No, I don't think so.  --enable-checking produces SIGABRT, not SIGSEGV.
> 
> Yes, I know, but it's possible that some checking causes a segfault.

Not in this case.  I guess your OS/architecture don't (always)
segfault upon dereferencing a pointer that points one byte before
an allocated chunk of memory -- whether this is or isn't detected
depends on details of memory allocation and run-time diagnostics.

> > The segfault happens because it->bidi_it.bytepos is 1, and FETCH_BYTE 
> > cannot be called with a zero argument.  Here's a relevant portion of a 
> > debugging session:
> >
> 
> Thanks.  With that indication, and after adding assertions in the code, I 
> could make Emacs abort when that problem occurred.  I pushed a fix a few 
> minutes ago.

Thanks.  The crash is gone, of course, but I'm not sure this is the
correct fix.  See below.

> But I'm still unable to reproduce your second recipe.  I tried again and 
> again, both with a regular and a checking-enable build, with and without 
> the fix for the first recipe, and with various frame sizes... but without 
> success.  If you can still reproduce it with the fix, could you perhaps 
> send me a backtrace?

I can send you a backtrace from yesterday:

  Thread 1 received signal SIGSEGV, Segmentation fault.
  0x01055028 in get_visually_first_element (it=0x82af68) at xdisp.c:8691
  8691                   && (FETCH_BYTE (it->bidi_it.bytepos - 1) == '\n'
  (gdb) bt
  #0  0x01055028 in get_visually_first_element (it=0x82af68) at xdisp.c:8691
  #1  0x010563d4 in next_element_from_buffer (it=0x82af68) at xdisp.c:9149
  #2  0x01052bd3 in get_next_display_element (it=0x82af68) at xdisp.c:7786
  #3  0x0108a318 in display_line (it=0x82af68, cursor_vpos=0) at xdisp.c:24377
  #4  0x0107c178 in try_window (window=XIL(0xa000000007a89d98), pos=...,
      flags=1) at xdisp.c:20268
  #5  0x01078db7 in redisplay_window (window=XIL(0xa000000007a89d98),
      just_this_one_p=false) at xdisp.c:19675
  #6  0x010701d7 in redisplay_window_0 (window=XIL(0xa000000007a89d98))
      at xdisp.c:17236
  #7  0x0127074c in internal_condition_case_1 (
      bfun=0x107017f <redisplay_window_0>, arg=XIL(0xa000000007a89d98),
      handlers=XIL(0xc00000000612fdac), hfun=0x106fe41 <redisplay_window_error>)
      at eval.c:1509
  #8  0x0106fe03 in redisplay_windows (window=XIL(0xa000000007a89d98))
      at xdisp.c:17206
  #9  0x0106fd99 in redisplay_windows (window=XIL(0xa000000007a89bb8))
      at xdisp.c:17200
  #10 0x0106e5ca in redisplay_internal () at xdisp.c:16656
  #11 0x0106bd8c in redisplay () at xdisp.c:15860
  #12 0x01173882 in read_char (commandflag=1, map=XIL(0xc000000007b8e0d0),
      prev_event=XIL(0), used_mouse_menu=0x82f43f, end_time=0x0)
      at keyboard.c:2595
  #13 0x0118d771 in read_key_sequence (keybuf=0x82f728, prompt=XIL(0),
      dont_downcase_last=false, can_return_switch_frame=true,
      fix_current_buffer=true, prevent_redisplay=false) at keyboard.c:9947
  #14 0x0116f1eb in command_loop_1 () at keyboard.c:1391
  #15 0x01270662 in internal_condition_case (bfun=0x116eab0 <command_loop_1>,
      handlers=XIL(0x90), hfun=0x116da7e <cmd_error>) at eval.c:1485
  #16 0x0116e51d in command_loop_2 (handlers=XIL(0x90)) at keyboard.c:1132
  #17 0x0126f4e9 in internal_catch (tag=XIL(0xfe70),
      func=0x116e4e6 <command_loop_2>, arg=XIL(0x90)) at eval.c:1208
  #18 0x0116e488 in command_loop () at keyboard.c:1110
  #19 0x0116d4de in recursive_edit_1 () at keyboard.c:719
  #20 0x0116d77c in Frecursive_edit () at keyboard.c:802
  #21 0x011686e6 in main (argc=2, argv=0xa42a10) at emacs.c:2517

  Lisp Backtrace:
  "redisplay_internal (C function)" (0x0)
  (gdb) fr 4
  #4  0x0107c178 in try_window (window=XIL(0xa000000007a89d98), pos=...,
      flags=1) at xdisp.c:20268
  20268         if (display_line (&it, cursor_vpos))
  (gdb) p pos
  $1 = {
    charpos = 1,
    bytepos = 1
  }
  (gdb) fr 5
  #5  0x01078db7 in redisplay_window (window=XIL(0xa000000007a89d98),
      just_this_one_p=false) at xdisp.c:19675
  19675             if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)

  (gdb) p startp
  $2 = {
    charpos = 1,
    bytepos = 1
  }
  (gdb) p w->start
  $3 = XIL(0xa000000007a89f78)
  (gdb) xtype
  Lisp_Vectorlike
  PVEC_MARKER
  (gdb) xmarker
  $4 = (struct Lisp_Marker *) 0x7a89f78
  (gdb) p *$
  $5 = {
    header = {
      size = 1124081664
    },
    buffer = 0x7665a48,
    need_adjustment = 0,
    insertion_type = 0,
    next = 0x7a89fa8,
    charpos = 1,
    bytepos = 1
  }
  (gdb) p w->pointm
  $8 = XIL(0xa000000007a89f90)
  (gdb) xtype
  Lisp_Vectorlike
  PVEC_MARKER
  (gdb) xmarker
  $9 = (struct Lisp_Marker *) 0x7a89f90
  (gdb) p *$
  $10 = {
    header = {
      size = 1124081664
    },
    buffer = 0x7665a48,
    need_adjustment = 0,
    insertion_type = 0,
    next = 0x7a9c530,
    charpos = 15000,
    bytepos = 15000
  }

As you see, the cause of problem was the same one: try_window was
called to attempt displaying a window whose window-start position is
1, which is outside of the "narrowing".  This is because, when we
split the window with "C-x 2", the new window is given window-start of
its buffer's BEGV, in this case 1 -- because split-window runs outside
of redisplay, and so doesn't know about the "narrowing".  Then
redisplay is invoked, and it attempts to reuse the existing
window-start point.

Since you have now moved the iteration to begin at the "narrowed"
BEGV, this crash is also gone.

To tell the truth, I'm not sure this kind of fix is the correct
solution, because basically its success is a matter of luck (or lack
thereof).  For example, recall the higher-level context of the first
segfault:

  Thread 1 received signal SIGSEGV, Segmentation fault.
  0x01055028 in get_visually_first_element (it=0x82d250) at xdisp.c:8691
  8691                   && (FETCH_BYTE (it->bidi_it.bytepos - 1) == '\n'
  (gdb) bt
  #0  0x01055028 in get_visually_first_element (it=0x82d250) at xdisp.c:8691
  #1  0x010563d4 in next_element_from_buffer (it=0x82d250) at xdisp.c:9149
  #2  0x01052bd3 in get_next_display_element (it=0x82d250) at xdisp.c:7786
  #3  0x01057166 in move_it_in_display_line_to (it=0x82d250, to_charpos=306655,
      to_x=0, op=(MOVE_TO_X | MOVE_TO_POS)) at xdisp.c:9574
  #4  0x01059ce7 in move_it_to (it=0x82d250, to_charpos=306655, to_x=-1,
      to_y=543, to_vpos=-1, op=10) at xdisp.c:10245
  #5  0x01038364 in pos_visible_p (w=0x75fd640, charpos=306655, x=0x82e23c,
      y=0x82e238, rtop=0x82e24c, rbot=0x82e248, rowh=0x82e244, vpos=0x82e240)
      at xdisp.c:1730
  #6  0x010ca308 in Fpos_visible_in_window_p (pos=XIL(0), window=XIL(0),

  Lisp Backtrace:
  "pos-visible-in-window-p" (0x68b0248)
  "pos-visible-in-window-group-p" (0x68b01f0)
  "isearch-update" (0x68b01a0)
  "isearch-search-and-update" (0x68b0178)
  "isearch-process-search-string" (0x68b0138)
  "isearch-process-search-char" (0x68b00d8)
  "isearch-quote-char" (0x82ebd0)
  "funcall-interactively" (0x82ebc8)
  "call-interactively" (0x68b0078)
  "command-execute" (0x82f5a8)

This is isearch.el trying to establish whether the position of the
match is visible in the window.  To do that, it starts from the
current window-start position (which happens to be 1), and simulates
display of the buffer text portion up until point or until the end of
window, whichever comes first, to determine whether point is beyond
the end of the window.  Your change makes the search start from some
much later position instead, which could very well produce incorrect
results: pos-visible-in-window-p could decide that point _is_ visible,
when it really isn't.  (It doesn't happen in this particular case
because the newline is far away -- at the very end of the buffer -- so
it isn't visible in both cases.  But that's sheer luck.)

More generally, if you look at redisplay_window, you will see that
about 2/3 of its code tries very hard to reuse the previous
window-start position, before it gives up and looks for a new starting
position.  So in any situation where the previous window-start is far
enough before point, all that code will basically work with a buffer
position that is at risk of being before the "narrowed" BEGV.  Thus,
any code there which tries stuff like start_display+move_it_to will
risk hitting this kind of problems -- either FETCH_BYTE will crash, or
we risk producing the wrong result because we force the code to jump
to the "narrowed" BEGV before doing anything, while its caller expects
results relative to a different position.

I think this is because the display engine assumes that BEGV stays put
during the entire redisplay_window lifetime, i.e. that all of the
subroutines it calls see the same value of BEGV.  This is no longer so
on the branch, and I wonder whether and how we should handle this new
situation to keep the display code stable and reliable.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 12:20                                                 ` Eli Zaretskii
@ 2022-07-18 12:58                                                   ` Gregory Heytings
  2022-07-18 13:33                                                     ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-18 12:58 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Gerd Möllmann, larsi, 56393


>
> Thanks.  The crash is gone, of course,
>

That's good news.

>
> I can send you a backtrace from yesterday:
>
> [...]
>
> As you see, the cause of problem was the same one:
>
> [...]
>
> Since you have now moved the iteration to begin at the "narrowed" BEGV, 
> this crash is also gone.
>

That's good news, too.  Thanks for the other backtrace.

>
> To tell the truth, I'm not sure this kind of fix is the correct 
> solution, because basically its success is a matter of luck (or lack 
> thereof).  For example, recall the higher-level context of the first 
> segfault:
>
> [...]
>
> This is isearch.el trying to establish whether the position of the match 
> is visible in the window.  To do that, it starts from the current 
> window-start position (which happens to be 1), and simulates display of 
> the buffer text portion up until point or until the end of window, 
> whichever comes first, to determine whether point is beyond the end of 
> the window.  Your change makes the search start from some much later 
> position instead, which could very well produce incorrect results: 
> pos-visible-in-window-p could decide that point _is_ visible, when it 
> really isn't.  (It doesn't happen in this particular case because the 
> newline is far away -- at the very end of the buffer -- so it isn't 
> visible in both cases.  But that's sheer luck.)
>

Well, this happens only in buffers with long lines, and only when we are 
inside a long line, so from my point of view it works as expected, and 
moreover the risk is small.  Would the following be better from your point 
of view?

diff --git a/src/xdisp.c b/src/xdisp.c
index d69d7440bc..572ad2b854 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -8668,18 +8668,11 @@ get_visually_first_element (struct it *it)
    bool string_p = STRINGP (it->string) || it->s;
    ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
    ptrdiff_t bob;
+  ptrdiff_t obegv = BEGV;

-  SET_WITH_NARROWED_BEGV (it, bob, string_p ? 0 : BEGV);
-
-  /* Reseat again when, as a consequence of the SET_WITH_NARROWED_BEGV
-     above, the iterator is before bob.  */
-  if (!string_p && IT_CHARPOS (*it) < bob)
-    {
-      struct text_pos pos;
-      pos.charpos = bob;
-      pos.bytepos = CHAR_TO_BYTE (bob);
-      reseat (it, pos, true);
-    }
+  SET_WITH_NARROWED_BEGV (it, bob,
+                         string_p ? 0 :
+                         IT_BYTEPOS (*it) < BEGV ? obegv : BEGV);

    if (STRINGP (it->string))
      {

>
> More generally, if you look at redisplay_window, you will see that about 
> 2/3 of its code tries very hard to reuse the previous window-start 
> position, before it gives up and looks for a new starting position.  So 
> in any situation where the previous window-start is far enough before 
> point, all that code will basically work with a buffer position that is 
> at risk of being before the "narrowed" BEGV.  Thus, any code there which 
> tries stuff like start_display+move_it_to will risk hitting this kind of 
> problems -- either FETCH_BYTE will crash, or we risk producing the wrong 
> result because we force the code to jump to the "narrowed" BEGV before 
> doing anything, while its caller expects results relative to a different 
> position.
>

I understand.  But note that temporarily narrowing the buffer happens only 
at a few well-chosen places, which are situated rather low in the 
abstraction layers, so the effect on other parts of the code is nil.

>
> I think this is because the display engine assumes that BEGV stays put 
> during the entire redisplay_window lifetime, i.e. that all of the 
> subroutines it calls see the same value of BEGV.  This is no longer so 
> on the branch, and I wonder whether and how we should handle this new 
> situation to keep the display code stable and reliable.
>

I don't know.





^ permalink raw reply related	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 12:58                                                   ` Gregory Heytings
@ 2022-07-18 13:33                                                     ` Eli Zaretskii
  2022-07-18 14:00                                                       ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-18 13:33 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Mon, 18 Jul 2022 12:58:59 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: Gerd Möllmann <gerd.moellmann@gmail.com>, larsi@gnus.org, 
>     56393@debbugs.gnu.org
> 
> > This is isearch.el trying to establish whether the position of the match 
> > is visible in the window.  To do that, it starts from the current 
> > window-start position (which happens to be 1), and simulates display of 
> > the buffer text portion up until point or until the end of window, 
> > whichever comes first, to determine whether point is beyond the end of 
> > the window.  Your change makes the search start from some much later 
> > position instead, which could very well produce incorrect results: 
> > pos-visible-in-window-p could decide that point _is_ visible, when it 
> > really isn't.  (It doesn't happen in this particular case because the 
> > newline is far away -- at the very end of the buffer -- so it isn't 
> > visible in both cases.  But that's sheer luck.)
> 
> Well, this happens only in buffers with long lines, and only when we are 
> inside a long line

Is the last part really guaranteed?  AFAIU, the detection of long
lines scans the entire buffer, so if there's a long line _anywhere_ in
the buffer, the narrowing is applied, even if point is in no-so-long
lines.  Or am I missing something?

> so from my point of view it works as expected

"As expected" in what sense?  Suppose we really are in a long line,
the Isearch match is really outside the window, but if we use
point-10000 as BEGV point seems to be _inside_ the window -- in this
case the feature implemented in isearch-update for slow terminals will
not do its thing, right?

> and moreover the risk is small.

Not sure this should pacify the fears.

> Would the following be better from your point of view?
> 
> diff --git a/src/xdisp.c b/src/xdisp.c
> index d69d7440bc..572ad2b854 100644
> --- a/src/xdisp.c
> +++ b/src/xdisp.c
> @@ -8668,18 +8668,11 @@ get_visually_first_element (struct it *it)
>     bool string_p = STRINGP (it->string) || it->s;
>     ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
>     ptrdiff_t bob;
> +  ptrdiff_t obegv = BEGV;
> 
> -  SET_WITH_NARROWED_BEGV (it, bob, string_p ? 0 : BEGV);
> -
> -  /* Reseat again when, as a consequence of the SET_WITH_NARROWED_BEGV
> -     above, the iterator is before bob.  */
> -  if (!string_p && IT_CHARPOS (*it) < bob)
> -    {
> -      struct text_pos pos;
> -      pos.charpos = bob;
> -      pos.bytepos = CHAR_TO_BYTE (bob);
> -      reseat (it, pos, true);
> -    }
> +  SET_WITH_NARROWED_BEGV (it, bob,
> +                         string_p ? 0 :
> +                         IT_BYTEPOS (*it) < BEGV ? obegv : BEGV);

I guess it's better, as it reduces the number of cases where the
problem could happen, at the price of making those cases slower.

> > More generally, if you look at redisplay_window, you will see that about 
> > 2/3 of its code tries very hard to reuse the previous window-start 
> > position, before it gives up and looks for a new starting position.  So 
> > in any situation where the previous window-start is far enough before 
> > point, all that code will basically work with a buffer position that is 
> > at risk of being before the "narrowed" BEGV.  Thus, any code there which 
> > tries stuff like start_display+move_it_to will risk hitting this kind of 
> > problems -- either FETCH_BYTE will crash, or we risk producing the wrong 
> > result because we force the code to jump to the "narrowed" BEGV before 
> > doing anything, while its caller expects results relative to a different 
> > position.
> 
> I understand.  But note that temporarily narrowing the buffer happens only 
> at a few well-chosen places, which are situated rather low in the 
> abstraction layers, so the effect on other parts of the code is nil.

I think I agree with everything except the "nil" part ;-)

> > I think this is because the display engine assumes that BEGV stays put 
> > during the entire redisplay_window lifetime, i.e. that all of the 
> > subroutines it calls see the same value of BEGV.  This is no longer so 
> > on the branch, and I wonder whether and how we should handle this new 
> > situation to keep the display code stable and reliable.
> >
> 
> I don't know.

Neither do I.  Still thinking about it.  I'd be interested to hear
Gerd's thoughts on this.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 13:33                                                     ` Eli Zaretskii
@ 2022-07-18 14:00                                                       ` Gregory Heytings
  2022-07-18 14:10                                                         ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-18 14:00 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393

[-- Attachment #1: Type: text/plain, Size: 1761 bytes --]


>> Well, this happens only in buffers with long lines, and only when we 
>> are inside a long line
>
> Is the last part really guaranteed?  AFAIU, the detection of long lines 
> scans the entire buffer, so if there's a long line _anywhere_ in the 
> buffer, the narrowing is applied, even if point is in no-so-long lines.
>

That's correct, but the narrowing starts well before the visually first 
element.  So when point is inside a not-so-long line, 
get_visually_first_element will work as usual: it will not stop at a 
narrowed BOB while searching for the visually first element, or IOW it 
will never need to search until the narrowed BOB to do its job.

>
> "As expected" in what sense?  Suppose we really are in a long line, the 
> Isearch match is really outside the window, but if we use point-10000 as 
> BEGV point seems to be _inside_ the window -- in this case the feature 
> implemented in isearch-update for slow terminals will not do its thing, 
> right?
>

I just tried

emacs -Q
(setq search-slow-speed most-positive-fixnum)
C-x C-f dictionary.json
C-s aan zich

and everything worked as expected.

>> Would the following be better from your point of view?
>>
>> [...]
>
> I guess it's better, as it reduces the number of cases where the problem 
> could happen, at the price of making those cases slower.
>

Okay, I'll push that.  It seems to work as well.

>> I understand.  But note that temporarily narrowing the buffer happens 
>> only at a few well-chosen places, which are situated rather low in the 
>> abstraction layers, so the effect on other parts of the code is nil.
>
> I think I agree with everything except the "nil" part ;-)
>

There is alas no "near-nil" value in Elisp. 😉

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 14:00                                                       ` Gregory Heytings
@ 2022-07-18 14:10                                                         ` Gregory Heytings
  2022-07-18 14:22                                                           ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-18 14:10 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> I guess it's better, as it reduces the number of cases where the 
>> problem could happen, at the price of making those cases slower.
>
> Okay, I'll push that.  It seems to work as well.
>

Done.  Can you please check that the earlier segfaults are still gone?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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
  0 siblings, 2 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-18 14:22 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Mon, 18 Jul 2022 14:10:10 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> >> I guess it's better, as it reduces the number of cases where the 
> >> problem could happen, at the price of making those cases slower.
> >
> > Okay, I'll push that.  It seems to work as well.
> >
> 
> Done.  Can you please check that the earlier segfaults are still gone?

Still gone.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 14:22                                                           ` Eli Zaretskii
@ 2022-07-18 14:34                                                             ` Gregory Heytings
  2022-07-18 16:06                                                             ` Gregory Heytings
  1 sibling, 0 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-18 14:34 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> Done.  Can you please check that the earlier segfaults are still gone?
>
> Still gone.
>

Great.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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 16:48                                                               ` Eli Zaretskii
  1 sibling, 2 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-18 16:06 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


And I just pushed an improved heuristic to detect long lines.  The code to 
detect whether the buffer contains long lines will only be executed when 
two or more characters have been added in the buffer since last redisplay, 
which means that normal typing (that is, one character at a time) is now 
entirely unaffected by that detection code.  On my laptop that code takes 
only 1 ms in a 20 MiB large buffer, but that's still too much for my 
taste.

Of course in theory one could add a very long line, one character at a 
time, in a buffer, but doing so without sometimes adding two characters 
between two redisplays is near to impossible.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 16:06                                                             ` Gregory Heytings
@ 2022-07-18 16:21                                                               ` Gregory Heytings
  2022-07-18 17:04                                                                 ` Eli Zaretskii
  2022-07-18 16:48                                                               ` Eli Zaretskii
  1 sibling, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-18 16:21 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


By the way, one last optimization would be possible in get_narrowed_begv. 
Is there a way to check (efficiently) whether the buffer is displayed with 
a single font in a single size?  Or IOW, whether the buffer is displayed 
in a "character-only terminal" way?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 16:06                                                             ` Gregory Heytings
  2022-07-18 16:21                                                               ` Gregory Heytings
@ 2022-07-18 16:48                                                               ` Eli Zaretskii
  2022-07-18 17:11                                                                 ` Gregory Heytings
  1 sibling, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-18 16:48 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Mon, 18 Jul 2022 16:06:51 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> 
> And I just pushed an improved heuristic to detect long lines.  The code to 
> detect whether the buffer contains long lines will only be executed when 
> two or more characters have been added in the buffer since last redisplay, 
> which means that normal typing (that is, one character at a time) is now 
> entirely unaffected by that detection code.  On my laptop that code takes 
> only 1 ms in a 20 MiB large buffer, but that's still too much for my 
> taste.

Thanks, but couldn't we use the existing BUF_CHARS_MODIFF for that?

And I found a scenario in which redisplay is still very slow, as slow
as the master branch.  Here, try this:

  emacs -Q
  C-x C-f long-line.xml RET

Now, do NOT disable font-lock, and wait for Emacs to say "Valid" in
the mode line (to get nXML mode out of the way).  Then:

  M-x toggle-truncate-lines RET

Now simple cursor motion commands that use redisplay optimizations are
fast, but commands that cause more thorough redisplay are as slow as
on master.  As a simple example, try just "M-x" and wait until the
"M-x" prompt appears in the minibuffer -- here it takes much longer,
basically as long as the version on master.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 16:21                                                               ` Gregory Heytings
@ 2022-07-18 17:04                                                                 ` Eli Zaretskii
  2022-07-18 17:07                                                                   ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-18 17:04 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Mon, 18 Jul 2022 16:21:27 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> 
> By the way, one last optimization would be possible in get_narrowed_begv. 
> Is there a way to check (efficiently) whether the buffer is displayed with 
> a single font in a single size?

Not that I know of, no.  At least we don't keep this information
anywhere, even after we compute it for display.  In particular, if we
never displayed some part of the buffer since the beginning of the
session, we don't even know what fonts that could require.  And
computing that takes the same effort as displaying the text in the
first place.

But maybe I misunderstand the question: what do you mean by "buffer is
displayed"?  We never display the entire buffer, only as much as fits
in the window.  So do you really mean "the buffer" or "the portion of
the buffer visible in the window" (or something else)?

> Or IOW, whether the buffer is displayed in a "character-only
> terminal" way?

That translates into a lot of potential issues.  First, you need a
fixed-pitch default face, right?  Then you need to ensure we don't
have any characters that are displayed by fonts other than the default
face's font, either because these characters aren't supported by the
font, or required by some non-default face, or even because some face
requires the default font, but with a different weight or size or
slant.  You also need to make sure there are no overlays in the
buffer, and no 'display' or invisible properties.  Maybe also that
tab-width is at its default value?  Maybe there's more.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 17:04                                                                 ` Eli Zaretskii
@ 2022-07-18 17:07                                                                   ` Gregory Heytings
  2022-07-18 17:09                                                                     ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-18 17:07 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>
> Not that I know of, no.  At least we don't keep this information 
> anywhere, even after we compute it for display.  In particular, if we 
> never displayed some part of the buffer since the beginning of the 
> session, we don't even know what fonts that could require.  And 
> computing that takes the same effort as displaying the text in the first 
> place.
>
> [...]
>
> That translates into a lot of potential issues.  First, you need a 
> fixed-pitch default face, right?  Then you need to ensure we don't have 
> any characters that are displayed by fonts other than the default face's 
> font, either because these characters aren't supported by the font, or 
> required by some non-default face, or even because some face requires 
> the default font, but with a different weight or size or slant.  You 
> also need to make sure there are no overlays in the buffer, and no 
> 'display' or invisible properties.  Maybe also that tab-width is at its 
> default value?  Maybe there's more.
>

Thanks for the detailed explanation.  It's clear that computing that 
information would largely outweigh its potential benefit, so I'll have to 
live without that potential optimization.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 17:07                                                                   ` Gregory Heytings
@ 2022-07-18 17:09                                                                     ` Eli Zaretskii
  2022-07-18 18:33                                                                       ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-18 17:09 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Mon, 18 Jul 2022 17:07:26 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> Thanks for the detailed explanation.  It's clear that computing that 
> information would largely outweigh its potential benefit, so I'll have to 
> live without that potential optimization.

If you had a way to do this, for how many characters would you need to
have this info?  (I presume you want it for characters before point,
but how many?)





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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:26                                                                   ` Gregory Heytings
  0 siblings, 2 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-18 17:11 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>
> Thanks, but couldn't we use the existing BUF_CHARS_MODIFF for that?
>

I'll have a look, thanks.

>
> And I found a scenario in which redisplay is still very slow, as slow as 
> the master branch.  Here, try this:
>
> emacs -Q
> C-x C-f long-line.xml RET
>
> Now, do NOT disable font-lock, and wait for Emacs to say "Valid" in the 
> mode line (to get nXML mode out of the way).  Then:
>
> M-x toggle-truncate-lines RET
>

BTW, there is now a C-x x t binding for that.

>
> Now simple cursor motion commands that use redisplay optimizations are 
> fast, but commands that cause more thorough redisplay are as slow as on 
> master.  As a simple example, try just "M-x" and wait until the "M-x" 
> prompt appears in the minibuffer -- here it takes much longer, basically 
> as long as the version on master.
>

Yes, it's a font locking issue.  Turn font-lock-mode off and the problem 
is gone.  As I said, I'll look at that later.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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
  1 sibling, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-18 17:19 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Mon, 18 Jul 2022 17:11:23 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > M-x toggle-truncate-lines RET
> 
> BTW, there is now a C-x x t binding for that.

Old habits die hard ;-)  Besides, what I really type is

  M-x tog TAB tr TAB RET

> > Now simple cursor motion commands that use redisplay optimizations are 
> > fast, but commands that cause more thorough redisplay are as slow as on 
> > master.  As a simple example, try just "M-x" and wait until the "M-x" 
> > prompt appears in the minibuffer -- here it takes much longer, basically 
> > as long as the version on master.
> >
> 
> Yes, it's a font locking issue.  Turn font-lock-mode off and the problem 
> is gone.  As I said, I'll look at that later.

So you are saying that font-lock becomes much more expensive when
lines are truncated?  Because the comparison is with the same file and
font-lock turned ON, but without line truncation.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 17:19                                                                   ` Eli Zaretskii
@ 2022-07-18 18:17                                                                     ` Gregory Heytings
  0 siblings, 0 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-18 18:17 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393

[-- Attachment #1: Type: text/plain, Size: 887 bytes --]


>> BTW, there is now a C-x x t binding for that.
>
> Old habits die hard ;-)  Besides, what I really type is
>
> M-x tog TAB tr TAB RET
>

10 keys instead of 4, a 250 % slowdown! 😉

>> Yes, it's a font locking issue.  Turn font-lock-mode off and the 
>> problem is gone.  As I said, I'll look at that later.
>
> So you are saying that font-lock becomes much more expensive when lines 
> are truncated?  Because the comparison is with the same file and 
> font-lock turned ON, but without line truncation.
>

I can't give a precise answer to your question.  All I can say is that I'm 
sure that font locking slows down things significantly.  After opening 
that file and typing C-u C-x x f C-x x t, editing is fast.  That being 
said, perhaps there are specific optimizations to add for 
toggle-truncate-lines.  Which would be yet another subsection of this bug.

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 17:11                                                                 ` Gregory Heytings
  2022-07-18 17:19                                                                   ` Eli Zaretskii
@ 2022-07-18 18:26                                                                   ` Gregory Heytings
  2022-07-18 18:56                                                                     ` Eli Zaretskii
  1 sibling, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-18 18:26 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> Thanks, but couldn't we use the existing BUF_CHARS_MODIFF for that?
>
> I'll have a look, thanks.
>

And the answer is no.  (I tried to use it, but did not remember the reason 
why it was not usable in this context while writing my previous reply.) 
I don't know what BUF_CHARS_MODIFF records, but it is for example == 2 
before and after C-x i dictionary.json RET.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 17:09                                                                     ` Eli Zaretskii
@ 2022-07-18 18:33                                                                       ` Gregory Heytings
  0 siblings, 0 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-18 18:33 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> Thanks for the detailed explanation.  It's clear that computing that 
>> information would largely outweigh its potential benefit, so I'll have 
>> to live without that potential optimization.
>
> If you had a way to do this, for how many characters would you need to 
> have this info?  (I presume you want it for characters before point, but 
> how many?)
>

For something like two screenful characters before window point.  But as I 
said, if the infrastructure does not already exist, it's not worth the 
price.  I asked just in case I missed something, because I did not want to 
omit an potential optimization, but (as you probably understood) I'm 
firmly against over-engineering.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 18:26                                                                   ` Gregory Heytings
@ 2022-07-18 18:56                                                                     ` Eli Zaretskii
  2022-07-18 20:14                                                                       ` Gregory Heytings
  2022-07-21  9:42                                                                       ` Eli Zaretskii
  0 siblings, 2 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-18 18:56 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Mon, 18 Jul 2022 18:26:22 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> 
> >> Thanks, but couldn't we use the existing BUF_CHARS_MODIFF for that?
> >
> > I'll have a look, thanks.
> >
> 
> And the answer is no.  (I tried to use it, but did not remember the reason 
> why it was not usable in this context while writing my previous reply.) 
> I don't know what BUF_CHARS_MODIFF records

What BUF_CHARS_MODIFF records is documented in the doc string of
buffer-chars-modified-tick.

> but it is for example == 2 before and after C-x i dictionary.json
> RET.

It's a bug, plain and simple.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 18:56                                                                     ` Eli Zaretskii
@ 2022-07-18 20:14                                                                       ` Gregory Heytings
  2022-07-19  2:34                                                                         ` Eli Zaretskii
  2022-07-21  9:42                                                                       ` Eli Zaretskii
  1 sibling, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-18 20:14 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> And the answer is no.  (I tried to use it, but did not remember the 
>> reason why it was not usable in this context while writing my previous 
>> reply.) I don't know what BUF_CHARS_MODIFF records
>
> What BUF_CHARS_MODIFF records is documented in the doc string of 
> buffer-chars-modified-tick.
>

Yes, I know.  But, even if it had no bugs, the doc string does not seem 
promising for the present task AFAICS:

Each buffer has a character-change tick counter, which is set to the value 
of the buffer's tick counter (see `buffer-modified-tick'), each time text 
in that buffer is inserted or deleted.  By comparing the values returned 
by two individual calls of `buffer-chars-modified-tick', you can tell 
whether a character change occurred in that buffer in between these calls.

What I'm interested in in this case is not simply "whether a character 
change occurred", but "how many characters were added in the buffer".  I 
want to calculate whether the long line optimizations should be enabled if 
and only if two or more characters were added in the buffer since last 
redisplay.  That is, neither if only one character was added in the buffer 
(which is what happens during normal typing), nor if characters were 
removed from the buffer.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 20:14                                                                       ` Gregory Heytings
@ 2022-07-19  2:34                                                                         ` Eli Zaretskii
  2022-07-19  5:39                                                                           ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-19  2:34 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Mon, 18 Jul 2022 20:14:21 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> Each buffer has a character-change tick counter, which is set to the value 
> of the buffer's tick counter (see `buffer-modified-tick'), each time text 
> in that buffer is inserted or deleted.  By comparing the values returned 
> by two individual calls of `buffer-chars-modified-tick', you can tell 
> whether a character change occurred in that buffer in between these calls.
> 
> What I'm interested in in this case is not simply "whether a character 
> change occurred", but "how many characters were added in the buffer".  I 
> want to calculate whether the long line optimizations should be enabled if 
> and only if two or more characters were added in the buffer since last 
> redisplay.  That is, neither if only one character was added in the buffer 
> (which is what happens during normal typing), nor if characters were 
> removed from the buffer.

Why just "added"?  Deletion of characters can also create long lines,
if the deleted characters are newlines.

Also, what if since last redisplay N characters were deleted and N
other characters were added?  Isn't there a good chance that the long
line optimizations could now be needed in that case?

BUF_CHARS_MODIFF will catch all of these, while just looking at the
buffer's size won't.

And that's on top of the main reason: BUF_CHARS_MODIFF exists for a
long time, so introducing yet another similar counter sounds like not
the best idea to me.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-19  2:34                                                                         ` Eli Zaretskii
@ 2022-07-19  5:39                                                                           ` Gregory Heytings
  2022-07-19 12:00                                                                             ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-19  5:39 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>
> Why just "added"?  Deletion of characters can also create long lines, if 
> the deleted characters are newlines.
>

Indeed, somehow I missed that possibility.  I think a better heuristic 
would be: if more than one character was added or removed from the buffer, 
check whether the buffer contains long lines.  I want to avoid affecting 
normal typing as much as possible, even if the effect is small.

>
> Also, what if since last redisplay N characters were deleted and N other 
> characters were added?
>

You mean for example M-% C-j RET SPC RET?  Indeed, that's yet another 
possibility.

>
> And that's on top of the main reason: BUF_CHARS_MODIFF exists for a long 
> time, so introducing yet another similar counter sounds like not the 
> best idea to me.
>

To be honest, I don't really understand the purpose of BUF_CHARS_MODIFF. 
As the comment in buffer.h explains: "It is set to modiff for each such 
event, and never otherwise changed."  So it doesn't contain new 
information.  And it's inconvenient that you have to keep a copy of its 
previous value around, using MODIFIED != UNCHANGED_MODIFIED as I did 
earlier is much easier.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 10:49   ` Gregory Heytings
@ 2022-07-19  8:21     ` Gerd Möllmann
  2022-07-19  8:53       ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-19  8:21 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: 56393

Gregory Heytings <gregory@heytings.org> writes:

>> That's only ~100 lines of code?  Can that be?  I'm suspecting that I
>> don't use Magit right, again.  Or something.
>>
>
> You're using Magit right: it's indeed a small fix.
>
> Your comments would be most welcome, of course.

First of all - I find your design idea really nice.  I think the
iterator layer, if you will, is the right place for this kind of
functionality.

Whatever.  Let me distinguish your code into the part that decides
whether to do something, and the part that then does it.  I'm currently
only thinking about the first part, the determination if to do
something.

What I see, please correct me if I'm wrong:

The determination is part of what I call Emacs' redisplay layer.
Rediplay_window sets buffer's long_lines_optimization_p flag to true,
under some condition.  (l_l_o_p flag is then used to let the iterator
layer do something, later.)

Mark_window_display_accurate computes unchanged_size as Z - BEG, which
is the buffer's size at that point.  m_w_d_a is called from
redisplay_internal, again under certain conditions, basically when a
thorough display has been completed successfully.

Questions I'm pondering are, and I'm not saying anything is wrong or
something, I'm just thinking about this, and I guess you have been
thinking about the subject longer than I have

- Since the determination is done in what I'd call redisplay, what if a
  buffer with long lines is never, or not yet, displayed?  Are there
  circumstances under which we are using an iterator then?  Background
  fontification?  Some hook? Other stuff I don't know about?  Could that
  cause us trouble?

- I did not see that l_l_o_p is set to false anywhere.  Should it be?
  What if a buffer is modified in such a way that there are no long
  lines anymore?

- I don't understand this in redisplay_window:

  /* Check whether the buffer to be displayed contains long lines.  */
  if (!NILP (Vlong_line_threshold)
      && !current_buffer->long_line_optimizations_p
      && Z - BEG - BUF_UNCHANGED_SIZE (current_buffer) <= 1)

  Does the last line mean "buffer got smaller"?  Sorry if I'm dense
  here, but  I don't get it.


















^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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
                           ` (3 more replies)
  0 siblings, 4 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-19  8:53 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: 56393


Thanks again for your detailed comments!

>
> - Since the determination is done in what I'd call redisplay, what if a 
> buffer with long lines is never, or not yet, displayed?  Are there 
> circumstances under which we are using an iterator then?  Background 
> fontification?  Some hook? Other stuff I don't know about?  Could that 
> cause us trouble?
>

If a buffer with long lines is never or not yet displayed, the specific 
optimizations do not take place.  That was a very important if not 
critical improvement, because Emacs may internally use buffers with long 
lines, and they should be entirely unaffected by that change.  (For 
example, the newsrc.eld file used internally by Gnus contains one such 
long line; if the same temporary restrictions were used in that buffer, it 
is possible that Gnus would not work correctly anymore.)

As far as I can tell, iterators are used in such buffers, too, but they 
are not fontified.  Fontification happens only when necessary, that is, 
when the buffer is actually displayed.

>
> - I did not see that l_l_o_p is set to false anywhere.  Should it be? 
> What if a buffer is modified in such a way that there are no long lines 
> anymore?
>

Gosh!  That was an error, thanks!

>
> - I don't understand this in redisplay_window:
>
>  /* Check whether the buffer to be displayed contains long lines.  */
>  if (!NILP (Vlong_line_threshold)
>      && !current_buffer->long_line_optimizations_p
>      && Z - BEG - BUF_UNCHANGED_SIZE (current_buffer) <= 1)
>
> Does the last line mean "buffer got smaller"?  Sorry if I'm dense here, 
> but I don't get it.
>

It is (- (point-max) (point-min) (buffer-size-after-last-redisplay)), so 
it means "the buffer got larger by more than one character".  (Note that 
(buffer-size-after-last-redisplay) is a fictional function.)  But after 
discussing this with Eli I'm not convinced that it's a good enough 
heuristic.  The previous heuristic was simply "the buffer contents have 
changed", and I wanted to refine it a bit.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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 12:21           ` Eli Zaretskii
  2022-07-19  9:17         ` bug#56393: Auto narrowing autside of redisplay Gerd Möllmann
                           ` (2 subsequent siblings)
  3 siblings, 2 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-19  8:58 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: 56393


>> - I did not see that l_l_o_p is set to false anywhere.  Should it be? 
>> What if a buffer is modified in such a way that there are no long lines 
>> anymore?
>
> Gosh!  That was an error, thanks!
>

In fact it wasn't, there is a "b->long_line_optimizations_p = 0;" in 
reset_buffer.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Auto narrowing autside of redisplay
  2022-07-19  8:53       ` Gregory Heytings
  2022-07-19  8:58         ` Gregory Heytings
@ 2022-07-19  9:17         ` Gerd Möllmann
  2022-07-19  9:51           ` Gregory Heytings
  2022-07-19  9:25         ` bug#56393: Turn on narrowing in redisplay_window Gerd Möllmann
  2022-07-19 12:48         ` Eli Zaretskii
  3 siblings, 1 reply; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-19  9:17 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: 56393

Gregory Heytings <gregory@heytings.org> writes:

> If a buffer with long lines is never or not yet displayed, the
> specific optimizations do not take place.  That was a very important
> if not critical improvement, because Emacs may internally use buffers
> with long lines, and they should be entirely unaffected by that
> change.  (For example, the newsrc.eld file used internally by Gnus
> contains one such long line; if the same temporary restrictions were
> used in that buffer, it is possible that Gnus would not work correctly
> anymore.)
>
> As far as I can tell, iterators are used in such buffers, too, but
> they are not fontified.  Fontification happens only when necessary,
> that is, when the buffer is actually displayed.

Okay, I understand the internal buffer argument.  But what if it is not
such a buffer?  Say a large XML or JS file with background
fontification.

WDYT about marking buffers that don't want auto narrowing?  Or
the opssite, mark buffers that want it?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Turn on narrowing in redisplay_window
  2022-07-19  8:53       ` Gregory Heytings
  2022-07-19  8:58         ` Gregory Heytings
  2022-07-19  9:17         ` bug#56393: Auto narrowing autside of redisplay Gerd Möllmann
@ 2022-07-19  9:25         ` Gerd Möllmann
  2022-07-19  9:52           ` Gregory Heytings
  2022-07-19 12:48         ` Eli Zaretskii
  3 siblings, 1 reply; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-19  9:25 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: 56393

Gregory Heytings <gregory@heytings.org> writes:

>> - I don't understand this in redisplay_window:
>>
>>  /* Check whether the buffer to be displayed contains long lines.  */
>>  if (!NILP (Vlong_line_threshold)
>>      && !current_buffer->long_line_optimizations_p
>>      && Z - BEG - BUF_UNCHANGED_SIZE (current_buffer) <= 1)
>>
>> Does the last line mean "buffer got smaller"?  Sorry if I'm dense
>> here, but I don't get it.
>>
>
> It is (- (point-max) (point-min) (buffer-size-after-last-redisplay)),

Sorry, maybe it's too hot here to think (36°C currently), I still don't
get it

     (- (point-max) (point-min))  = current buffer size

so

     current-buffer-size - last-buffer-size <= 1
     current-buffer-size <= 1 + last-buffer-size

which is "the buffer got smaller"?

> so it means "the buffer got larger by more than one character".  (Note
> that (buffer-size-after-last-redisplay) is a fictional function.)

Goes without saying.

> But after discussing this with Eli I'm not convinced that it's a good
> enough heuristic.  The previous heuristic was simply "the buffer
> contents have changed", and I wanted to refine it a bit.

Okay.  Hm.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Resetting long_line_optimization_p to 0
  2022-07-19  8:58         ` Gregory Heytings
@ 2022-07-19  9:31           ` Gerd Möllmann
  2022-07-19  9:51             ` Gregory Heytings
  2022-07-19 12:21           ` Eli Zaretskii
  1 sibling, 1 reply; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-19  9:31 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: 56393

Gregory Heytings <gregory@heytings.org> writes:

>>> - I did not see that l_l_o_p is set to false anywhere.  Should it
>>> be? What if a buffer is modified in such a way that there are no
>>> long lines anymore?
>>
>> Gosh!  That was an error, thanks!
>
> In fact it wasn't, there is a "b->long_line_optimizations_p = 0;" in
> reset_buffer.

Yes, I've seen that one, sorry for not being clear.

What I meant was resetting the flag without resetting the buffer.  For
example in redisplay_window when it finds that the condition for setting
it true is no longer met.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Resetting long_line_optimization_p to 0
  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
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-19  9:51 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: 56393


>
> What I meant was resetting the flag without resetting the buffer.  For 
> example in redisplay_window when it finds that the condition for setting 
> it true is no longer met.
>

It is indeed never reset.  It goes only in one direction: as soon as a 
buffer contains one "long enough" line, the specific optimizations are 
used, and the buffer continues to use them.  Such buffers are not common, 
I don't think it is necessary/useful to check after each iteration whether 
the buffer still contains long lines, especially given that these 
optimizations have a near-nil effect in buffers without long lines.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Auto narrowing autside of redisplay
  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
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-19  9:51 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: 56393


>
> Okay, I understand the internal buffer argument.  But what if it is not 
> such a buffer?  Say a large XML or JS file with background 
> fontification.
>
> WDYT about marking buffers that don't want auto narrowing?  Or the 
> opssite, mark buffers that want it?
>

One of the explicit aims when designing that feature was that it should be 
as transparent as possible.  And it is: only a few selected places in 
xdisp.c see its effect.

That being said, you can do what you want nonetheless: if you (setq-local 
long-line-threshold nil) the optimizations will never be used (in that 
buffer), if you (setq-local long-line-threshold 0) the optimizations will 
always be used (in that buffer).

Adding code to expose the feature further to Lisp would be (IMO) a 
mistake.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Turn on narrowing in redisplay_window
  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
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-19  9:52 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: 56393

[-- Attachment #1: Type: text/plain, Size: 362 bytes --]


>
> Sorry, maybe it's too hot here to think (36°C currently), I still don't 
> get it
>
> (- (point-max) (point-min))  = current buffer size
>
> so
>
> current-buffer-size - last-buffer-size <= 1
>
> current-buffer-size <= 1 + last-buffer-size
>
> which is "the buffer got smaller"?
>

You are correct.  It's too hot here too, apparently!  😉

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-19  9:51           ` Gregory Heytings
@ 2022-07-19 10:56             ` Gerd Möllmann
  0 siblings, 0 replies; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-19 10:56 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: 56393

Gregory Heytings <gregory@heytings.org> writes:

>> WDYT about marking buffers that don't want auto narrowing?  Or the
>> opssite, mark buffers that want it?
>>
>
> One of the explicit aims when designing that feature was that it
> should be as transparent as possible.  And it is: only a few selected
> places in xdisp.c see its effect.

Okay.

> That being said, you can do what you want nonetheless: if you
> (setq-local long-line-threshold nil) the optimizations will never be
> used (in that buffer), if you (setq-local long-line-threshold 0) the
> optimizations will always be used (in that buffer).
>
> Adding code to expose the feature further to Lisp would be (IMO) a
> mistake.

Understood.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Resetting long_line_optimization_p to 0
  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
  0 siblings, 1 reply; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-19 11:20 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: 56393

Gregory Heytings <gregory@heytings.org> writes:

>>
>> What I meant was resetting the flag without resetting the buffer.
>> For example in redisplay_window when it finds that the condition for
>> setting it true is no longer met.
>>
>
> It is indeed never reset.  It goes only in one direction: as soon as a
> buffer contains one "long enough" line, the specific optimizations are
> used, and the buffer continues to use them.

Okay.

>
> Such buffers are not common,

Right.

That's the reason I didn't want to tackle this problem in Emacs 21, BTW.
But I also did not have your idea at the time.

>
> I don't think it is necessary/useful to check after each iteration
> whether the buffer still contains long lines, especially given that
> these optimizations have a near-nil effect in buffers without long
> lines.

Correct.

Which leaves me with something to think about, of course: when redisplay
sets the flag in the buffer, then there's of course a time before that.
And the question is what can happen in that interval.  But not today.
I'll come back to you.


P.S. (for Michael Albinus, if he's still reading this thread >:-))

When replying to a message in Debbugs with 'F' (Gnus), the subject gets
changed to the original bug report subject.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Turn on narrowing in redisplay_window
  2022-07-19  9:52           ` Gregory Heytings
@ 2022-07-19 11:26             ` Gerd Möllmann
  2022-07-19 12:43               ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-19 11:26 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: 56393

Gregory Heytings <gregory@heytings.org> writes:

>>
>> which is "the buffer got smaller"?
>>
>
> You are correct.  It's too hot here too, apparently!  😉

Is finding newlines that expensive?  (I don't remember.)  I mean, if
someone turns that "mode" on, does he deserve to suffer a little bit
while that is switched on?

I think someone with such a long line deserves to suffer.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-19  5:39                                                                           ` Gregory Heytings
@ 2022-07-19 12:00                                                                             ` Eli Zaretskii
  2022-07-19 12:07                                                                               ` Gerd Möllmann
                                                                                                 ` (2 more replies)
  0 siblings, 3 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-19 12:00 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Tue, 19 Jul 2022 05:39:24 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> To be honest, I don't really understand the purpose of BUF_CHARS_MODIFF. 
> As the comment in buffer.h explains: "It is set to modiff for each such 
> event, and never otherwise changed."  So it doesn't contain new 
> information.

Yes, it does: it allows you to keep track of changes to the buffer
text only, ignoring any other changes (like faces, overlays, etc.)
which affect the buffer's modified status.  The number itself is not
interesting, the only thing that is interesting is when the number
goes up -- this means the buffer text was changed in some way.

> And it's inconvenient that you have to keep a copy of its previous
> value around, using MODIFIED != UNCHANGED_MODIFIED as I did earlier
> is much easier.

We could indeed keep using MODIFIED != UNCHANGED_MODIFIED (and I'm not
really sure why you decided it was not good enough: can you describe
the problems using it?).  Alternatively, we could add a new member of
'struct buffer_text' called, say, unchanged_chars_modiff, and use it
instead of MODIFIED != UNCHANGED_MODIFIED in the same way as we use
MODIFIED != UNCHANGED_MODIFIED.

My point is that if you want the member you added, unchanged_size, to
be as responsive to text changes as BUF_CHARS_MODIFF, you will need to
add code to increment it in all the places where we already do that
with BUF_CHARS_MODIFF, and that sounds like redundancy, since we don't
really care about how many characters were added/deleted/replaced.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-19 12:00                                                                             ` Eli Zaretskii
@ 2022-07-19 12:07                                                                               ` Gerd Möllmann
  2022-07-19 12:49                                                                               ` Gregory Heytings
       [not found]                                                                               ` <bce7aad8-6872-97ec-77ac-6a593ff66a27@heytings.org>
  2 siblings, 0 replies; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-19 12:07 UTC (permalink / raw)
  To: Eli Zaretskii, Gregory Heytings; +Cc: larsi, 56393


[-- Attachment #1.1.1: Type: text/plain, Size: 117 bytes --]


On 22-07-19 14:00 , Eli Zaretskii wrote:
> We could indeed keep using MODIFIED != UNCHANGED_MODIFIED

Agree.


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3211 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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 12:21           ` Eli Zaretskii
  1 sibling, 0 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-19 12:21 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, 56393

> Cc: 56393@debbugs.gnu.org
> Date: Tue, 19 Jul 2022 08:58:52 +0000
> From: Gregory Heytings <gregory@heytings.org>
> 
> 
> >> - I did not see that l_l_o_p is set to false anywhere.  Should it be? 
> >> What if a buffer is modified in such a way that there are no long lines 
> >> anymore?
> >
> > Gosh!  That was an error, thanks!
> >
> 
> In fact it wasn't, there is a "b->long_line_optimizations_p = 0;" in 
> reset_buffer.

But who calls reset_buffer when a buffer is being edited?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Turn on narrowing in redisplay_window
  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
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-19 12:43 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: gregory, 56393

> Cc: 56393@debbugs.gnu.org
> From: Gerd Möllmann <gerd.moellmann@gmail.com>
> Date: Tue, 19 Jul 2022 13:26:31 +0200
> 
> Gregory Heytings <gregory@heytings.org> writes:
> 
> >>
> >> which is "the buffer got smaller"?
> >>
> >
> > You are correct.  It's too hot here too, apparently!  😉
> 
> Is finding newlines that expensive?  (I don't remember.)

It isn't, but if you have a very large buffer, finding _all_ the
newlines in it could take time.

> I mean, if someone turns that "mode" on, does he deserve to suffer a
> little bit while that is switched on?

We want to have this "mode" turned on by default.

> I think someone with such a long line deserves to suffer.

That's a bootstrap problem: when you first visit a file, you usually
don't know whether it will have long lines.  By the time you know,
it's many times too late.  Thus such a feature should ideally be
active by default, unless it sometimes causes serious problems.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-19  8:53       ` Gregory Heytings
                           ` (2 preceding siblings ...)
  2022-07-19  9:25         ` bug#56393: Turn on narrowing in redisplay_window Gerd Möllmann
@ 2022-07-19 12:48         ` Eli Zaretskii
  2022-07-20  6:32           ` Gerd Möllmann
  3 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-19 12:48 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, 56393

> Cc: 56393@debbugs.gnu.org
> Date: Tue, 19 Jul 2022 08:53:12 +0000
> From: Gregory Heytings <gregory@heytings.org>
> 
> If a buffer with long lines is never or not yet displayed, the specific 
> optimizations do not take place.  That was a very important if not 
> critical improvement, because Emacs may internally use buffers with long 
> lines, and they should be entirely unaffected by that change.  (For 
> example, the newsrc.eld file used internally by Gnus contains one such 
> long line; if the same temporary restrictions were used in that buffer, it 
> is possible that Gnus would not work correctly anymore.)
> 
> As far as I can tell, iterators are used in such buffers, too, but they 
> are not fontified.  Fontification happens only when necessary, that is, 
> when the buffer is actually displayed.

Not sure what you mean by "fontification" here.  AFAIR, when iterators
are used in any buffer, Emacs always calls jit-lock, and then always
resolves the faces produced by jit-lock (via font-lock).  Those faces
are never displayed, of course, if the buffer has no window.

I agree that functions that use iterators should rarely be called in
buffers that aren't displayed, but that still can happen.  Stuff like
vertical-motion, window-text-pixel-size, etc.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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
       [not found]                                                                               ` <bce7aad8-6872-97ec-77ac-6a593ff66a27@heytings.org>
  2 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-19 12:49 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> And it's inconvenient that you have to keep a copy of its previous 
>> value around, using MODIFF != UNCHANGED_MODIFIED as I did earlier is 
>> much easier.
>
> We could indeed keep using MODIFF != UNCHANGED_MODIFIED (and I'm not 
> really sure why you decided it was not good enough: can you describe the 
> problems using it?).
>

The problem is that the loop under that condition is called whenever 
redisplay_window is called.  For a file like xdisp.c or dictionary.json, 
that loop takes about 1 ms (on my laptop).  For a file with 150K lines, it 
takes about 13 ms.  As I said earlier, I would prefer to avoid calling 
that loop for normal typing, namely when only one character has been added 
or removed from the buffer since the last redisplay.  IOW, I want to make 
the heuristic more precise.

>
> Alternatively, we could add a new member of 'struct buffer_text' called, 
> say, unchanged_chars_modiff, and use it instead of MODIFF != 
> UNCHANGED_MODIFIED in the same way as we use MODIFF != 
> UNCHANGED_MODIFIED.
>
> My point is that if you want the member you added, unchanged_size, to be 
> as responsive to text changes as BUF_CHARS_MODIFF, you will need to add 
> code to increment it in all the places where we already do that with 
> BUF_CHARS_MODIFF, and that sounds like redundancy, since we don't really 
> care about how many characters were added/deleted/replaced.
>

AFAIU that's not correct: like unchanged_modified, unchanged_size must be 
updated only when redisplay ends, namely in 
mark_window_display_accurate_1.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
       [not found]                                                                               ` <bce7aad8-6872-97ec-77ac-6a593ff66a27@heytings.org>
@ 2022-07-19 12:57                                                                                 ` Gregory Heytings
  0 siblings, 0 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-19 12:57 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>
> The problem is that the loop under that condition is called whenever 
> redisplay_window is called.  For a file like xdisp.c or dictionary.json, 
> that loop takes about 1 ms (on my laptop).  For a file with 150K lines, 
> it takes about 13 ms.  As I said earlier, I would prefer to avoid 
> calling that loop for normal typing, namely when only one character has 
> been added or removed from the buffer since the last redisplay.  IOW, I 
> want to make the heuristic more precise.
>

Sorry, that was not precise enough: the loop under that condition is 
called whenever redisplay_window is called AND the buffer has been 
modified.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-19 12:49                                                                               ` Gregory Heytings
@ 2022-07-19 13:16                                                                                 ` Eli Zaretskii
  2022-07-19 13:42                                                                                   ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-19 13:16 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Tue, 19 Jul 2022 12:49:33 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> >> And it's inconvenient that you have to keep a copy of its previous 
> >> value around, using MODIFF != UNCHANGED_MODIFIED as I did earlier is 
> >> much easier.
> >
> > We could indeed keep using MODIFF != UNCHANGED_MODIFIED (and I'm not 
> > really sure why you decided it was not good enough: can you describe the 
> > problems using it?).
> >
> 
> The problem is that the loop under that condition is called whenever 
> redisplay_window is called. For a file like xdisp.c or dictionary.json, 
> that loop takes about 1 ms (on my laptop).  For a file with 150K lines, it 
> takes about 13 ms.  As I said earlier, I would prefer to avoid calling 
> that loop for normal typing, namely when only one character has been added 
> or removed from the buffer since the last redisplay.  IOW, I want to make 
> the heuristic more precise.

So you want to call the loop only when the buffer changed by two or
more characters?  Did you try something like

  MODIFF > UNCHANGED_MODIFIED + 1

?  (This could be optimized further to use a margin larger that 1.)

> > Alternatively, we could add a new member of 'struct buffer_text' called, 
> > say, unchanged_chars_modiff, and use it instead of MODIFF != 
> > UNCHANGED_MODIFIED in the same way as we use MODIFF != 
> > UNCHANGED_MODIFIED.
> >
> > My point is that if you want the member you added, unchanged_size, to be 
> > as responsive to text changes as BUF_CHARS_MODIFF, you will need to add 
> > code to increment it in all the places where we already do that with 
> > BUF_CHARS_MODIFF, and that sounds like redundancy, since we don't really 
> > care about how many characters were added/deleted/replaced.
> >
> 
> AFAIU that's not correct: like unchanged_modified, unchanged_size must be 
> updated only when redisplay ends, namely in 
> mark_window_display_accurate_1.

That's true, but I meant chars_modiff, not unchanged_chars_modiff.
The former is updated all over insdel.c, to catch all the possible
primitive operations that modify buffer text, so if you want to catch
those modifications, you need to do the same, more or less.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-19 13:16                                                                                 ` Eli Zaretskii
@ 2022-07-19 13:42                                                                                   ` Gregory Heytings
  2022-07-19 13:56                                                                                     ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-19 13:42 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>
> So you want to call the loop only when the buffer changed by two or more 
> characters?  Did you try something like
>
>  MODIFF > UNCHANGED_MODIFIED + 1
>
> ?  (This could be optimized further to use a margin larger that 1.)
>

That doesn't work alas, otherwise I would have used that of course. 
After C-u 100000 a, MODIFF - UNCHANGED_MODIFIED == 1 in a buffer without 
fontification and == 2 in a buffer with fontification, which does what it 
promises: it tells you that the buffer has been changed, but not how much.

I pushed an improved version of the heuristic, which uses both MODIFF / 
UNCHANGED_MODIFIED (to catch editing operations like M-% C-q C-j RET SPC 
RET) and the buffer size to decide whether a new detection should be 
performed.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-19 13:42                                                                                   ` Gregory Heytings
@ 2022-07-19 13:56                                                                                     ` Eli Zaretskii
  2022-07-19 14:06                                                                                       ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-19 13:56 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Tue, 19 Jul 2022 13:42:26 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > So you want to call the loop only when the buffer changed by two or more 
> > characters?  Did you try something like
> >
> >  MODIFF > UNCHANGED_MODIFIED + 1
> >
> > ?  (This could be optimized further to use a margin larger that 1.)
> 
> That doesn't work alas, otherwise I would have used that of course. 
> After C-u 100000 a, MODIFF - UNCHANGED_MODIFIED == 1 in a buffer without 
> fontification and == 2 in a buffer with fontification, which does what it 
> promises: it tells you that the buffer has been changed, but not how much.

Why is that a problem?  For this feature, we don't need the exact
number of modifications in character units.

> I pushed an improved version of the heuristic, which uses both MODIFF / 
> UNCHANGED_MODIFIED (to catch editing operations like M-% C-q C-j RET SPC 
> RET) and the buffer size to decide whether a new detection should be 
> performed.

Fine by me, but I think this is over-engineered.

Also, please add a comment there explaining the heuristics, including
the cases we know about where the counters could behave "strangely" or
fail to catch changes.

Thanks.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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:19                                                                                         ` Eli Zaretskii
  0 siblings, 2 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-19 14:06 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>
> Why is that a problem?  For this feature, we don't need the exact number 
> of modifications in character units.
>

Again, because I want to skip the long line detection code/overhead for 
normal editing operation (typing one character at a time).  I do not think 
that a 13 ms overhead for each typed character in a file with 150K lines 
is okay.

>
> Fine by me, but I think this is over-engineered.
>

Fine, but then you'd have to tell me how to do that in another way (that 
is, how to not trigger the long line detection code when the buffer has 
only changed a little), or to convince me that the 13 ms overhead is okay.

Also note that the full changeset only has 152 insertions and 88 
deletions, that is, 64 added lines.

>
> Also, please add a comment there explaining the heuristics, including 
> the cases we know about where the counters could behave "strangely" or 
> fail to catch changes.
>

I'll do that.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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 14:19                                                                                         ` Eli Zaretskii
  1 sibling, 2 replies; 205+ messages in thread
From: Lars Ingebrigtsen @ 2022-07-19 14:15 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, Eli Zaretskii, 56393

Gregory Heytings <gregory@heytings.org> writes:

> Again, because I want to skip the long line detection code/overhead
> for normal editing operation (typing one character at a time).  I do
> not think that a 13 ms overhead for each typed character in a file
> with 150K lines is okay.

Do you need it to run as often as the current code does?  It's a
heuristic -- if it gets it wrong in some pathological situation (i.e.,
if the user replaces all newlines with spaces in a huge buffer with a
function that does just that), that's not a deal breaker.

That is, I don't think you have to run the detection as often as you do
now.  If the previous call said you had no lines longer than 80
characters, you don't have to run it again until the buffer has grown
more than 30K characters, or you have a modiff in the thousands region.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-19 14:06                                                                                       ` Gregory Heytings
  2022-07-19 14:15                                                                                         ` Lars Ingebrigtsen
@ 2022-07-19 14:19                                                                                         ` Eli Zaretskii
  2022-07-19 14:33                                                                                           ` Gregory Heytings
  1 sibling, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-19 14:19 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Tue, 19 Jul 2022 14:06:17 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > Why is that a problem?  For this feature, we don't need the exact number 
> > of modifications in character units.
> 
> Again, because I want to skip the long line detection code/overhead for 
> normal editing operation (typing one character at a time).

That's not the problem you presented.  You presented an opposite
problem: where inserting many characters bumps the tick by just 1.  I
asked why that is a problem.

> > Fine by me, but I think this is over-engineered.
> 
> Fine, but then you'd have to tell me how to do that in another way (that 
> is, how to not trigger the long line detection code when the buffer has 
> only changed a little), or to convince me that the 13 ms overhead is okay.

That's not what I'm saying.  I'm saying that not recomputing the long
lines when the user types "C-u 100000 a" is not a catastrophe.

> > Also, please add a comment there explaining the heuristics, including 
> > the cases we know about where the counters could behave "strangely" or 
> > fail to catch changes.
> >
> 
> I'll do that.

Thanks.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-19 14:15                                                                                         ` Lars Ingebrigtsen
@ 2022-07-19 14:24                                                                                           ` Gregory Heytings
       [not found]                                                                                           ` <364167b2-83e-c5af-1981-221d53e33ce6@heytings.org>
  1 sibling, 0 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-19 14:24 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: gerd.moellmann, Eli Zaretskii, 56393


>
> Do you need it to run as often as the current code does?  It's a 
> heuristic -- if it gets it wrong in some pathological situation (i.e., 
> if the user replaces all newlines with spaces in a huge buffer with a 
> function that does just that), that's not a deal breaker.
>

I think you need, yes.  And with the present heuristic it will not run 
that often, in fact.  The problem is that a single editing operation like 
C-u 100000 a creates a long line, and Emacs would start choking again. 
Or C-x i <a file with long lines>.  Or a shell process which produces a 
long line.  And so forth.

>
> That is, I don't think you have to run the detection as often as you do 
> now.  If the previous call said you had no lines longer than 80 
> characters, you don't have to run it again until the buffer has grown 
> more than 30K characters, or you have a modiff in the thousands region.
>

Hmmm...  Thanks, I'll see if I can do something with that idea.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-19 14:19                                                                                         ` Eli Zaretskii
@ 2022-07-19 14:33                                                                                           ` Gregory Heytings
  2022-07-19 16:14                                                                                             ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-19 14:33 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>
> That's not the problem you presented.  You presented an opposite 
> problem: where inserting many characters bumps the tick by just 1.  I 
> asked why that is a problem.
>

We are miscommunicating.  I was not telling you that the fact that 
inserting many characters bumps the tick by just 1 is in itself a problem. 
I was telling you that it makes that tick unusable for the present task.

>> Fine, but then you'd have to tell me how to do that in another way 
>> (that is, how to not trigger the long line detection code when the 
>> buffer has only changed a little), or to convince me that the 13 ms 
>> overhead is okay.
>
> That's not what I'm saying.  I'm saying that not recomputing the long 
> lines when the user types "C-u 100000 a" is not a catastrophe.
>

It is, at least if this is meant to be a full and complete solution to 
that problem, because the same happens for example with C-x i <a file with 
long lines>: the tick does not change "enough", long line optimizations 
would not be enabled, and Emacs would choke again.  Or if a user 
innocently types "cat <a file with long lines>" in a shell buffer without 
knowing what that file contains.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-19 14:33                                                                                           ` Gregory Heytings
@ 2022-07-19 16:14                                                                                             ` Eli Zaretskii
  2022-07-19 21:40                                                                                               ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-19 16:14 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Tue, 19 Jul 2022 14:33:35 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > That's not the problem you presented.  You presented an opposite 
> > problem: where inserting many characters bumps the tick by just 1.  I 
> > asked why that is a problem.
> 
> We are miscommunicating.  I was not telling you that the fact that 
> inserting many characters bumps the tick by just 1 is in itself a problem. 
> I was telling you that it makes that tick unusable for the present task.

Would it help if the tick were incremented by the number of inserted
(or deleted or replaced) characters (perhaps limited by some
reasonable value, like 1000)?  That would be an easy change, and I
don't think it would break anything, since no current code relies on
the exact value of the tick, and the value you get after some
non-trivial operation on a buffer is generally unpredictable anyway.
Would that make the tick usable for this task?

You see, adding one more struct member to an object that we use all
over the place makes Emacs slower, because the object is larger and
thus takes more CPU cycles to copy.  Granted, the slowdown is barely
noticeable, but these things add up over the years, so it is best to
avoid adding members if we can do without that.  Thus, I'd rather
extend/improve the existing members than add new ones to fix issues in
the old ones.

If you agree, I can make such a change (but feel free to do it
yourself).





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-19 16:14                                                                                             ` Eli Zaretskii
@ 2022-07-19 21:40                                                                                               ` Gregory Heytings
  2022-07-20 12:07                                                                                                 ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-19 21:40 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>
> Would it help if the tick were incremented by the number of inserted (or 
> deleted or replaced) characters (perhaps limited by some reasonable 
> value, like 1000)?  That would be an easy change, and I don't think it 
> would break anything, since no current code relies on the exact value of 
> the tick, and the value you get after some non-trivial operation on a 
> buffer is generally unpredictable anyway. Would that make the tick 
> usable for this task?
>

It would.  In fact it is not even necessary to record the exact number of 
inserted/deleted/replaced characters.

>
> If you agree, I can make such a change (but feel free to do it 
> yourself).
>

I just did it, is this what you had in mind?  The tick is incremented 
logarithmically.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
       [not found]                                                                                           ` <364167b2-83e-c5af-1981-221d53e33ce6@heytings.org>
@ 2022-07-19 21:55                                                                                             ` Gregory Heytings
  0 siblings, 0 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-19 21:55 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: gerd.moellmann, Eli Zaretskii, 56393


>> That is, I don't think you have to run the detection as often as you do 
>> now.  If the previous call said you had no lines longer than 80 
>> characters, you don't have to run it again until the buffer has grown 
>> more than 30K characters, or you have a modiff in the thousands region.
>
> Hmmm...  Thanks, I'll see if I can do something with that idea.
>

I considered that option, but so far I cannot see how it could work 
reliably, or to be more precise, I fear that there are too many cases that 
would escape such a heuristic, such as M-% C-q C-j RET SPC RET in a 
sufficiently long buffer.  One disadvantage is that it would be necessary 
to record, in struct buffer, the buffer size (and perhaps also the modiff) 
when the detection was last run, something Eli would prefer to avoid.  I 
will continue to think about it, however.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-19 12:43               ` Eli Zaretskii
@ 2022-07-20  6:30                 ` Gerd Möllmann
  2022-07-20  9:08                   ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-20  6:30 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gregory, 56393

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Gerd Möllmann <gerd.moellmann@gmail.com>
>> 
>> Is finding newlines that expensive?  (I don't remember.)
>
> It isn't, but if you have a very large buffer, finding _all_ the
> newlines in it could take time.
>
>> I mean, if someone turns that "mode" on, does he deserve to suffer a
>> little bit while that is switched on?
>
> We want to have this "mode" turned on by default.

Okay.

If that's already determined, I don't need to think about it.

>
>> I think someone with such a long line deserves to suffer.
>
> That's a bootstrap problem: when you first visit a file, you usually
> don't know whether it will have long lines.  By the time you know,
> it's many times too late.  Thus such a feature should ideally be
> active by default, unless it sometimes causes serious problems.

Ideally, right.

What I'm trying to hint at it is that there's another way to see this:

It was mentioned a number of times that only a small fraction of people
encounter that problem.  And I'd add that this small fraction encounters
the problem only in a small fraction of cases.  And I even think most of
these cases are known upfront.

So, with some kind of mode, one could turn the iterator-narrowing on
(and off!) in redisplay_window without affecting anyone who doesn't have
the problem in the first place.

Just wanted to explain that.  No need for discussions.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-19 12:48         ` Eli Zaretskii
@ 2022-07-20  6:32           ` Gerd Möllmann
  0 siblings, 0 replies; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-20  6:32 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Gregory Heytings, 56393

Eli Zaretskii <eliz@gnu.org> writes:

> Not sure what you mean by "fontification" here.  AFAIR, when iterators
> are used in any buffer, Emacs always calls jit-lock, and then always

True.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-19 11:20               ` Gerd Möllmann
@ 2022-07-20  6:58                 ` Gerd Möllmann
  2022-07-20  9:13                   ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Gerd Möllmann @ 2022-07-20  6:58 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: 56393

Gerd Möllmann <gerd.moellmann@gmail.com> writes:

> Which leaves me with something to think about, of course: when redisplay
> sets the flag in the buffer, then there's of course a time before that.
> And the question is what can happen in that interval.  But not today.
> I'll come back to you.

So far, I can't think of something specifically catastrophic happening
in the interval between a buffer being loaded, let's say, and it being
marked with the flag.

I think it's the same situation we talked about previously wrt a buffer
that is never or not yet displayed:

Pretty much anything could potentially happen as soon as an iterator is
used.  The reason for this is that iterators must know faces and other
stuff, let's simply say they must know text properties and overlays.
And that can call Lisp, and then all bets are off.

If that happens in practice, how often it happens, or what else, I don't
know.

What's the worst thing that can happen?  Slowness, I guess.  I can't
think of something going seriously down the drain ATM.


I guess that's about what I can continute to the whole matter.

Nice work.  THanks!





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-20  6:30                 ` bug#56393: Actually fix the long lines display bug Gerd Möllmann
@ 2022-07-20  9:08                   ` Gregory Heytings
  0 siblings, 0 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-20  9:08 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: Eli Zaretskii, 56393


>
> It was mentioned a number of times that only a small fraction of people 
> encounter that problem.  And I'd add that this small fraction encounters 
> the problem only in a small fraction of cases.  And I even think most of 
> these cases are known upfront.
>

I agree that it's a relatively rare problem, but when it happens it is 
very annoying, because Emacs becomes unusable.  I disagree, however, that 
most of theses cases are known upfront, in most cases a user simply opens 
a file that they can open in other editors without setting any specific 
option in these other editors, with the expectation that they will be able 
to edit it in Emacs.  Now the situation is reversed: you can open and edit 
files in Emacs that you cannot open and edit in other editors.

>
> So, with some kind of mode, one could turn the iterator-narrowing on 
> (and off!) in redisplay_window without affecting anyone who doesn't have 
> the problem in the first place.
>

What we have right now is a kind of (minimal) mode indeed, which is turned 
on automatically when necessary.  And from a user point of view it's also 
a kind of (minimal) mode, which they can turn off unconditionally by 
setting long-line-threshold to nil in their init file, or turn on 
unconditionally by setting long-line-threshold to 0 in their init file. 
I don't think turning it on unconditionally has any significant drawback, 
but there some extreme cases where commands would not do their job 
properly (for example, doing M-> C-u 37000 C-p in xdisp.c), which is why 
it is not turned on unconditionally by default.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-20  6:58                 ` bug#56393: Actually fix the long lines display bug Gerd Möllmann
@ 2022-07-20  9:13                   ` Gregory Heytings
  0 siblings, 0 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-20  9:13 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: 56393

[-- Attachment #1: Type: text/plain, Size: 1471 bytes --]


>> Which leaves me with something to think about, of course: when 
>> redisplay sets the flag in the buffer, then there's of course a time 
>> before that. And the question is what can happen in that interval. 
>> But not today. I'll come back to you.
>
> So far, I can't think of something specifically catastrophic happening 
> in the interval between a buffer being loaded, let's say, and it being 
> marked with the flag.
>
> I think it's the same situation we talked about previously wrt a buffer 
> that is never or not yet displayed:
>
> Pretty much anything could potentially happen as soon as an iterator is 
> used.  The reason for this is that iterators must know faces and other 
> stuff, let's simply say they must know text properties and overlays. And 
> that can call Lisp, and then all bets are off.
>
> If that happens in practice, how often it happens, or what else, I don't 
> know.
>
> What's the worst thing that can happen?  Slowness, I guess.  I can't 
> think of something going seriously down the drain ATM.
>

Okay, now I see what you mean.  As far as I can see (but I could be 
wrong), there are no significant slowdowns between the moment the file is 
opened and the moment it is displayed.  If such slowdowns exist, they are 
a separate problem, and will be dealt with when they will be reported.

>
> I guess that's about what I can continute to the whole matter.
>
> Nice work.  THanks!
>

Thanks! 😃

^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-19 21:40                                                                                               ` Gregory Heytings
@ 2022-07-20 12:07                                                                                                 ` Eli Zaretskii
  2022-07-20 13:06                                                                                                   ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-20 12:07 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Tue, 19 Jul 2022 21:40:36 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > Would it help if the tick were incremented by the number of inserted (or 
> > deleted or replaced) characters (perhaps limited by some reasonable 
> > value, like 1000)?  That would be an easy change, and I don't think it 
> > would break anything, since no current code relies on the exact value of 
> > the tick, and the value you get after some non-trivial operation on a 
> > buffer is generally unpredictable anyway. Would that make the tick 
> > usable for this task?
> 
> It would.  In fact it is not even necessary to record the exact number of 
> inserted/deleted/replaced characters.
> 
> > If you agree, I can make such a change (but feel free to do it 
> > yourself).
> >
> 
> I just did it, is this what you had in mind?  The tick is incremented 
> logarithmically.

Yes, thanks.  Perhaps add a comment inside modiff_incr explaining why
we do it logarithmically.  Otherwise, LGTM.

(Hmm... should we say something about this in NEWS?  Not that I expect
some code out there depend on the exact increments in MOFIFF...)





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-20 12:07                                                                                                 ` Eli Zaretskii
@ 2022-07-20 13:06                                                                                                   ` Gregory Heytings
  2022-07-20 13:23                                                                                                     ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-20 13:06 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>
> Yes, thanks.  Perhaps add a comment inside modiff_incr explaining why we 
> do it logarithmically.
>

You mean, something like: "Increase the counter more for a large 
modification and less for a small modification, but increase it 
logarithmically to avoid increasing it too much for a large 
modification."?

BTW, I think the threshold to trigger the long lines check in 
redisplay_window could be increased a bit.  That is, instead of using 
"MODIFF - UNCHANGED_MODIFIED > 4" I think we could use "> 8".  That would 
exclude a few more common editing operations, e.g. C-k in a buffer with 80 
columns.  WDYT?

>
> (Hmm... should we say something about this in NEWS?  Not that I expect 
> some code out there depend on the exact increments in MOFIFF...)
>

That would be very surprising, because they are in general unpredictable, 
and different depending on the context; e.g. MODIFF is incremented when 
font locking is enabled.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-20 13:06                                                                                                   ` Gregory Heytings
@ 2022-07-20 13:23                                                                                                     ` Eli Zaretskii
  2022-07-20 13:42                                                                                                       ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-20 13:23 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Wed, 20 Jul 2022 13:06:59 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> 
> >
> > Yes, thanks.  Perhaps add a comment inside modiff_incr explaining why we 
> > do it logarithmically.
> >
> 
> You mean, something like: "Increase the counter more for a large 
> modification and less for a small modification, but increase it 
> logarithmically to avoid increasing it too much for a large 
> modification."?

No, I mean explaining why we want to be more sensitive to small
modifications than to the large.  IOW, why we want to avoid linear
increments.

My original proposal to limit the increment was because I wanted to
avoid overflowing the counter when several very large insertions are
made.  If this is the only reason, I think we should say that in a
comment there.

> BTW, I think the threshold to trigger the long lines check in 
> redisplay_window could be increased a bit.  That is, instead of using 
> "MODIFF - UNCHANGED_MODIFIED > 4" I think we could use "> 8".  That would 
> exclude a few more common editing operations, e.g. C-k in a buffer with 80 
> columns.  WDYT?

I have no real experience on which to base my opinions, so feel free
to make the change.  Like I said, the threshold should be tuned, and
we may yet find the need to change it more than once.

> > (Hmm... should we say something about this in NEWS?  Not that I expect 
> > some code out there depend on the exact increments in MOFIFF...)
> >
> 
> That would be very surprising, because they are in general unpredictable, 
> and different depending on the context; e.g. MODIFF is incremented when 
> font locking is enabled.

OK, let's wait until someone hollers, if they do.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-20 13:23                                                                                                     ` Eli Zaretskii
@ 2022-07-20 13:42                                                                                                       ` Gregory Heytings
  2022-07-20 15:54                                                                                                         ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-20 13:42 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> You mean, something like: "Increase the counter more for a large 
>> modification and less for a small modification, but increase it 
>> logarithmically to avoid increasing it too much for a large 
>> modification."?
>
> No, I mean explaining why we want to be more sensitive to small 
> modifications than to the large.  IOW, why we want to avoid linear 
> increments.
>
> My original proposal to limit the increment was because I wanted to 
> avoid overflowing the counter when several very large insertions are 
> made.  If this is the only reason, I think we should say that in a 
> comment there.
>

That's what I understood.  I did not decide to go for a logarithmical 
increase instead of a truncated increase to be more sensitive to small 
modifications than to large ones, but both (1) because it increases the 
counter less, and (2) because currently it will be used to make a 
distinction between a "small" and a "not small" modification, but I can 
imagine that perhaps some day for some other reason there could be a need 
to make a distinction between "large" and "very large" modifications, 
which wouldn't be possible with a truncated increase.

Is this better/clearer: "Increase the counter more for a large 
modification and less for a small modification.  Increase it 
logarithmically to avoid increasing it too much."?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-20 13:42                                                                                                       ` Gregory Heytings
@ 2022-07-20 15:54                                                                                                         ` Eli Zaretskii
  2022-07-20 17:33                                                                                                           ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-20 15:54 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Wed, 20 Jul 2022 13:42:26 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> Is this better/clearer: "Increase the counter more for a large 
> modification and less for a small modification.  Increase it 
> logarithmically to avoid increasing it too much."?

Sounds good, thanks.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-20 15:54                                                                                                         ` Eli Zaretskii
@ 2022-07-20 17:33                                                                                                           ` Gregory Heytings
  2022-07-21  6:32                                                                                                             ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-20 17:33 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> Is this better/clearer: "Increase the counter more for a large 
>> modification and less for a small modification.  Increase it 
>> logarithmically to avoid increasing it too much."?
>
> Sounds good, thanks.

Now done.

I also made a few (final?) tweaks.  Please tell me if the feature is ready 
to land on master, or if further improvements are needed.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-20 17:33                                                                                                           ` Gregory Heytings
@ 2022-07-21  6:32                                                                                                             ` Eli Zaretskii
  2022-07-21  7:39                                                                                                               ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-21  6:32 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Wed, 20 Jul 2022 17:33:00 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> I also made a few (final?) tweaks.  Please tell me if the feature is ready 
> to land on master, or if further improvements are needed.

Thanks.

I think the code is ready to be merged, but what about the
documentation?  The branch currently removes all traces of the
facilities we previously documented as possible remedies for poor
performance in these cases.  However, we do know that in some
situations redisplay and related commands are still very slow.  The
NEWS entry on the branch does say that font-lock is one reason for the
slowdown.  So at least that part should be in the manual, perhaps in
the form of a shorter description of so-long mode (because one thing
it does is disable font-lock).  We can remove that later, if and when
these problems and any others we find are also resolved.

IOW, I think we still don't have enough data and experience to decide
that all those other measures will never be needed, so maybe it is too
early to delete their docs.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-21  6:32                                                                                                             ` Eli Zaretskii
@ 2022-07-21  7:39                                                                                                               ` Gregory Heytings
  2022-07-21  7:49                                                                                                                 ` Gregory Heytings
  2022-07-21  7:56                                                                                                                 ` Eli Zaretskii
  0 siblings, 2 replies; 205+ messages in thread
From: Gregory Heytings @ 2022-07-21  7:39 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>
> I think the code is ready to be merged, but what about the 
> documentation?  The branch currently removes all traces of the 
> facilities we previously documented as possible remedies for poor 
> performance in these cases.  However, we do know that in some situations 
> redisplay and related commands are still very slow.  The NEWS entry on 
> the branch does say that font-lock is one reason for the slowdown.
>

As far as I can see, font locking is the one and only remaining cause of 
slowdowns that is under control of Emacs.  Mode-specific slowdowns can of 
course not be solved in Emacs.  So what about simply turning font locking 
off unconditionally when long lines are detected in a buffer, until the 
font locking slowdowns are fixed?

>
> So at least that part should be in the manual, perhaps in the form of a 
> shorter description of so-long mode (because one thing it does is 
> disable font-lock).  We can remove that later, if and when these 
> problems and any others we find are also resolved.
>

As I told you, I'll start working on the font locking slowdowns as soon as 
this branch is merged into master.  It shouldn't take more than a couple 
of weeks to fix them.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  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
  1 sibling, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-21  7:49 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>
> As far as I can see, font locking is the one and only remaining cause of 
> slowdowns that is under control of Emacs.  Mode-specific slowdowns can 
> of course not be solved in Emacs.  So what about simply turning font 
> locking off unconditionally when long lines are detected in a buffer, 
> until the font locking slowdowns are fixed?
>

(Doing that would also make it easier to get feedback about other causes 
of slowdown, if any.)





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-21  7:39                                                                                                               ` Gregory Heytings
  2022-07-21  7:49                                                                                                                 ` Gregory Heytings
@ 2022-07-21  7:56                                                                                                                 ` Eli Zaretskii
  2022-07-21  8:20                                                                                                                   ` Gregory Heytings
  1 sibling, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-21  7:56 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Thu, 21 Jul 2022 07:39:28 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > I think the code is ready to be merged, but what about the 
> > documentation?  The branch currently removes all traces of the 
> > facilities we previously documented as possible remedies for poor 
> > performance in these cases.  However, we do know that in some situations 
> > redisplay and related commands are still very slow.  The NEWS entry on 
> > the branch does say that font-lock is one reason for the slowdown.
> 
> As far as I can see, font locking is the one and only remaining cause of 
> slowdowns that is under control of Emacs.  Mode-specific slowdowns can of 
> course not be solved in Emacs.  So what about simply turning font locking 
> off unconditionally when long lines are detected in a buffer, until the 
> font locking slowdowns are fixed?

If that's a temporary measure, I don't think we should do it: coding
it would be a throw-away effort.  I see no problem to have unfinished
code on master, we have that (for other features) all the time.  We
should delay such decisions until we either fix completely the
slowdown due to font-lock, or have a good understanding of the
reasons.

> > So at least that part should be in the manual, perhaps in the form of a 
> > shorter description of so-long mode (because one thing it does is 
> > disable font-lock).  We can remove that later, if and when these 
> > problems and any others we find are also resolved.
> 
> As I told you, I'll start working on the font locking slowdowns as soon as 
> this branch is merged into master.  It shouldn't take more than a couple 
> of weeks to fix them.

Then I guess this is not very important either way.  (Still, leaving
the text until we know exactly what, if anything, to say instead
sounds better to me than removing it and then possibly adding some of
it later.  But that's me.)





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-21  7:49                                                                                                                 ` Gregory Heytings
@ 2022-07-21  8:00                                                                                                                   ` Eli Zaretskii
  0 siblings, 0 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-21  8:00 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Thu, 21 Jul 2022 07:49:44 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> > As far as I can see, font locking is the one and only remaining cause of 
> > slowdowns that is under control of Emacs.  Mode-specific slowdowns can 
> > of course not be solved in Emacs.  So what about simply turning font 
> > locking off unconditionally when long lines are detected in a buffer, 
> > until the font locking slowdowns are fixed?
> >
> 
> (Doing that would also make it easier to get feedback about other causes 
> of slowdown, if any.)

That could be so, but I'd prefer first to remove the elephant in the
room.  It's not like people edit such problematic files all the time,
so feedback will probably come in quickly only from people who
deliberately do that because they want to test this feature.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-21  7:56                                                                                                                 ` Eli Zaretskii
@ 2022-07-21  8:20                                                                                                                   ` Gregory Heytings
  2022-07-21  8:58                                                                                                                     ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-21  8:20 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> As I told you, I'll start working on the font locking slowdowns as soon 
>> as this branch is merged into master.  It shouldn't take more than a 
>> couple of weeks to fix them.
>
> Then I guess this is not very important either way.  (Still, leaving the 
> text until we know exactly what, if anything, to say instead sounds 
> better to me than removing it and then possibly adding some of it later. 
> But that's me.)
>

So... what do I do?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-21  8:20                                                                                                                   ` Gregory Heytings
@ 2022-07-21  8:58                                                                                                                     ` Eli Zaretskii
  2022-07-21  9:00                                                                                                                       ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-21  8:58 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, larsi, 56393

> Date: Thu, 21 Jul 2022 08:20:43 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> 
> 
> >> As I told you, I'll start working on the font locking slowdowns as soon 
> >> as this branch is merged into master.  It shouldn't take more than a 
> >> couple of weeks to fix them.
> >
> > Then I guess this is not very important either way.  (Still, leaving the 
> > text until we know exactly what, if anything, to say instead sounds 
> > better to me than removing it and then possibly adding some of it later. 
> > But that's me.)
> >
> 
> So... what do I do?

It's your call.

Thanks.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-21  8:58                                                                                                                     ` Eli Zaretskii
@ 2022-07-21  9:00                                                                                                                       ` Gregory Heytings
  2022-07-21  9:18                                                                                                                         ` Lars Ingebrigtsen
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-21  9:00 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gerd.moellmann, larsi, 56393


>> So... what do I do?
>
> It's your call.
>

Okay.  Should I wait for Lars' feedback?





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-21  9:00                                                                                                                       ` Gregory Heytings
@ 2022-07-21  9:18                                                                                                                         ` Lars Ingebrigtsen
  2022-07-21 11:56                                                                                                                           ` Gregory Heytings
  0 siblings, 1 reply; 205+ messages in thread
From: Lars Ingebrigtsen @ 2022-07-21  9:18 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, Eli Zaretskii, 56393

Gregory Heytings <gregory@heytings.org> writes:

> Okay.  Should I wait for Lars' feedback?

Merging into master is fine by me.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-18 18:56                                                                     ` Eli Zaretskii
  2022-07-18 20:14                                                                       ` Gregory Heytings
@ 2022-07-21  9:42                                                                       ` Eli Zaretskii
  1 sibling, 0 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-21  9:42 UTC (permalink / raw)
  To: gregory; +Cc: gerd.moellmann, larsi, 56393

> Cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> Date: Mon, 18 Jul 2022 21:56:44 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> 
> > Date: Mon, 18 Jul 2022 18:26:22 +0000
> > From: Gregory Heytings <gregory@heytings.org>
> > cc: gerd.moellmann@gmail.com, larsi@gnus.org, 56393@debbugs.gnu.org
> > 
> > 
> > >> Thanks, but couldn't we use the existing BUF_CHARS_MODIFF for that?
> > >
> > > I'll have a look, thanks.
> > >
> > 
> > And the answer is no.  (I tried to use it, but did not remember the reason 
> > why it was not usable in this context while writing my previous reply.) 
> > I don't know what BUF_CHARS_MODIFF records
> 
> What BUF_CHARS_MODIFF records is documented in the doc string of
> buffer-chars-modified-tick.
> 
> > but it is for example == 2 before and after C-x i dictionary.json
> > RET.
> 
> It's a bug, plain and simple.

Should now be fixed on the master branch.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-21  9:18                                                                                                                         ` Lars Ingebrigtsen
@ 2022-07-21 11:56                                                                                                                           ` Gregory Heytings
  2022-07-21 12:22                                                                                                                             ` Eli Zaretskii
  0 siblings, 1 reply; 205+ messages in thread
From: Gregory Heytings @ 2022-07-21 11:56 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: gerd.moellmann, 56393-done, Eli Zaretskii


>> Okay.  Should I wait for Lars' feedback?
>
> Merging into master is fine by me.
>

Thanks, now done.

Should I delete the feature branch?  I don't remember what the policy is.





^ permalink raw reply	[flat|nested] 205+ messages in thread

* bug#56393: Actually fix the long lines display bug
  2022-07-21 11:56                                                                                                                           ` Gregory Heytings
@ 2022-07-21 12:22                                                                                                                             ` Eli Zaretskii
  0 siblings, 0 replies; 205+ messages in thread
From: Eli Zaretskii @ 2022-07-21 12:22 UTC (permalink / raw)
  To: Gregory Heytings; +Cc: gerd.moellmann, 56393-done, larsi

> Date: Thu, 21 Jul 2022 11:56:18 +0000
> From: Gregory Heytings <gregory@heytings.org>
> cc: gerd.moellmann@gmail.com, Eli Zaretskii <eliz@gnu.org>, 
>     56393-done@debbugs.gnu.org
> 
> 
> >> Okay.  Should I wait for Lars' feedback?
> >
> > Merging into master is fine by me.
> 
> Thanks, now done.

Thanks.

> Should I delete the feature branch?  I don't remember what the policy is.

The general policy is to delete them.  My suggestion is to wait for a
few days before actually deleting the branch, just so the dust
settles.





^ permalink raw reply	[flat|nested] 205+ messages in thread

end of thread, other threads:[~2022-07-21 12:22 UTC | newest]

Thread overview: 205+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-05  8:49 bug#56393: Actually fix the long lines display bug Gregory Heytings
2022-07-05  9:28 ` Gregory Heytings
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

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).