Subject: bug#72485: closed (Re: bug#72485: Support 'visual-wrap-prefix-mode' in SHR/EWW)

From: [email-masked] (GNU bug Tracking System)
Date: Sun, 18 Aug 2024 23:13:02 +0000

Your bug report

#72485: Support 'visual-wrap-prefix-mode' in SHR/EWW

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
72485: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=72485
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#72485: Support 'visual-wrap-prefix-mode' in SHR/EWW
From: Jim Porter <[email-masked]>
To: Eli Zaretskii <[email-masked]>
Cc: [email-masked]
Date: Sun, 18 Aug 2024 16:10:15 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

On 8/18/2024 11:53 AM, Eli Zaretskii wrote:
> LGTM, thanks.
> 
>> (If you think this makes the Emacs 31 NEWS entry partially redundant, I
>> can try to trim that one down to only discuss the new additions, but I
>> don't mind either way.)
> 
> I see no reason to trim it.

Thanks. Merged the NEWS update to the release branch as b54e8b3741b, and 
the main patch to the master branch as a876c4d7a17. Closing this bug now.

Subject: Support 'visual-wrap-prefix-mode' in SHR/EWW
From: Jim Porter <[email-masked]>
To: [email-masked]
Date: Mon, 5 Aug 2024 20:47:52 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

This patch is an extension of bug#71605, and the first place to 
explicitly use the new variable-pitch support for 
'visual-wrap-prefix-mode'. While implementing this, I found two small 
bugs in the new 'visual-wrap-prefix-mode' code:

1. When setting the min-width for the first line prefix, we should use 
'add-display-text-property' so as not to clobber other display properties.

2. My attempts to be "helpful" by special-casing wrap-prefixes of all 
spaces ended up just interfering with more complex cases (like SHR), so 
I removed it. The code is now simpler (one fewer condition) and just 
works more smoothly overall.

There's one limitation to this patch though: since SHR uses absolute 
pixel-widths for indenting internally, things can look mis-indented if 
you scale the text in the buffer. However, SHR has exactly the same 
issue when *not* using 'visual-wrap-prefix-mode', so it's really just a 
more-general bug in SHR. (It'd be nice to fix that, but I'd have to get 
a better understanding of how indentation and <table> elements interact.)

Attached is a test HTML page that shows off the indentation. You can see 
the results by running:

   emacs -Q --eval '(progn (setq shr-fill-text nil) (eww "test.html"))'

(And also compare to the default behavior where 'shr-fill-text' is non-nil.)

From 5e1de09af5398bd0a60683ebf53bef3f87440a91 Mon Sep 17 00:00:00 2001
From: Jim Porter <[email-masked]>
Date: Sun, 4 Aug 2024 19:37:00 -0700
Subject: [PATCH] Improve SHR/EWW support for 'visual-wrap-prefix-mode'

* lisp/visual-wrap.el (visual-wrap--apply-to-line): Use
'add-display-text-property' so we don't clobber other display
properties.
(visual-wrap--content-prefix): Remove special-case for spaces-only
indent prefix; this was an attempt to be helpful for variable-pitch
fonts, but in practice just interferes with matters.  This case now
falls back to the one immediately following it (return the string of
spaces).)

* lisp/net/shr.el (shr-indent): Set 'shr-prefix-length' here to help
keep track of the prefixes of nestedly-indented elements.
* lisp/net/shr.el (shr-adaptive-fill-function): Use 'shr-prefix-length'
as set above to return a fill prefix.

* lisp/net/eww.el (eww-render): Enable 'visual-wrap-prefix-mode'
alongside of 'visual-line-mode'.
(eww-mode): Set 'adaptive-fill-function' to
'shr-adaptive-fill-function'.
---
 lisp/net/eww.el     |  5 ++++-
 lisp/net/shr.el     | 19 ++++++++++++++-----
 lisp/visual-wrap.el | 12 +++---------
 3 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index b2e1c5a72e5..b5d2f20781a 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -709,7 +709,8 @@ eww-render
 	      (and last-coding-system-used
 		   (set-buffer-file-coding-system last-coding-system-used))
               (unless shr-fill-text
-                (visual-line-mode))
+                (visual-line-mode)
+                (visual-wrap-prefix-mode))
 	      (run-hooks 'eww-after-render-hook)
               ;; Enable undo again so that undo works in text input
               ;; boxes.
@@ -1336,6 +1337,8 @@ eww-mode
   ;; desktop support
   (setq-local desktop-save-buffer #'eww-desktop-misc-data)
   (setq truncate-lines t)
+  ;; visual-wrap-prefix-mode support
+  (setq-local adaptive-fill-function #'shr-adaptive-fill-function)
   ;; thingatpt support
   (setq-local thing-at-point-provider-alist
               (cons '(url . eww--url-at-point)
diff --git a/lisp/net/shr.el b/lisp/net/shr.el
index d3c48b34428..a0f9cd252d2 100644
--- a/lisp/net/shr.el
+++ b/lisp/net/shr.el
@@ -938,6 +938,11 @@ shr-fill-line
         (when (looking-at " $")
 	  (delete-region (point) (line-end-position)))))))
 
+(defun shr-adaptive-fill-function ()
+  "Return a fill prefix for the paragraph at point."
+  (when-let ((prefix (get-text-property (point) 'shr-prefix-length)))
+    (buffer-substring (point) (+ (point) prefix))))
+
 (defun shr-parse-base (url)
   ;; Always chop off anchors.
   (when (string-match "#.*" url)
@@ -1041,11 +1046,15 @@ shr-ensure-paragraph
 
 (defun shr-indent ()
   (when (> shr-indentation 0)
-    (if (not shr-use-fonts)
-        (insert-char ?\s shr-indentation)
-      (insert ?\s)
-      (put-text-property (1- (point)) (point)
-                         'display `(space :width (,shr-indentation))))))
+    (let ((start (point))
+          (prefix (or (get-text-property (point) 'shr-prefix-length) 0)))
+      (if (not shr-use-fonts)
+          (insert-char ?\s shr-indentation)
+        (insert ?\s)
+        (put-text-property start (point)
+                           'display `(space :width (,shr-indentation))))
+      (put-text-property start (+ (point) prefix)
+                         'shr-prefix-length (+ prefix (- (point) start))))))
 
 (defun shr-fontize-dom (dom &rest types)
   (let ((start (point)))
diff --git a/lisp/visual-wrap.el b/lisp/visual-wrap.el
index cac3bc767b8..51c0213a037 100644
--- a/lisp/visual-wrap.el
+++ b/lisp/visual-wrap.el
@@ -121,9 +121,9 @@ visual-wrap--apply-to-line
                (next-line-prefix (visual-wrap--content-prefix
                                   first-line-prefix position)))
       (when (numberp next-line-prefix)
-        (put-text-property
-         position (+ position (length first-line-prefix)) 'display
-         `(min-width ((,next-line-prefix . width)))))
+        (add-display-text-property
+         position (+ position (length first-line-prefix)) 'min-width
+         `((,next-line-prefix . width))))
       (setq next-line-prefix (visual-wrap--adjust-prefix next-line-prefix))
       (put-text-property
        position (line-end-position) 'wrap-prefix
@@ -141,12 +141,6 @@ visual-wrap--content-prefix
   (cond
    ((string= prefix "")
     nil)
-   ((string-match (rx bos (+ blank) eos) prefix)
-    ;; If the first-line prefix is all spaces, return its width in
-    ;; characters.  This way, we can set the prefix for all lines to use
-    ;; the canonical-width of the font, which helps for variable-pitch
-    ;; fonts where space characters are usually quite narrow.
-    (string-width prefix))
    ((or (and adaptive-fill-first-line-regexp
              (string-match adaptive-fill-first-line-regexp prefix))
         (and comment-start-skip
-- 
2.25.1