Subject: Re: bug#51176: eww switch buffer by title

From: Protesilaos Stavrou <[email-masked]>
Date: Fri, 15 Oct 2021 14:22:27 +0300

On 2021-10-15, 12:35 +0200, Lars Ingebrigtsen <[email-masked]> wrote:

> Protesilaos Stavrou <[email-masked]> writes:
>
>> Please find attached the patch which implements a renaming scheme for
>> EWW buffers.  I include Abhiseck, the co-author of this patch, in Cc.
>>
>> What do you think?
>>
>> We had entertained the notion of a single defcustom with more options,
>> but ultimately decided against it on the grounds that it was more
>> complex.
>
> Yeah, looks good to me, but:
>
> [email-masked] writes:
>
>> With your patch, the buffer isn't renamed if the user presses "l" or "r"
>> to go backward and forward in history. I suggest calling your rename
>> function from 'eww-update-header-line-format' instead.
>
> Yes, it has to be performed upon all updates.  But putting it in that
> function would be misleading, so what about creating a new function
> `eww--after-page-change' that would call 'eww-update-header-line-format'
> and
>
>             (when eww-auto-rename-buffer-flag
>               (funcall eww-auto-rename-buffer-function))
>
> and call that where 'eww-update-header-line-format' is called now.
>
> And we don't really call user options -flag, so rename it to just
> `eww-auto-rename-buffer'. 

Thanks for the feedback!  Please find attached the revised patch, based
on what you suggested:

    0001-Implement-auto-renaming-scheme-for-EWW-buffers-simple.patch

Because it may be useful for your consideration, there also exists the
more complex approach that I alluded to earlier ("complex" may be an
exaggeration, but still).  Attached as well and also based on your
feedback.

    0001-Implement-auto-renaming-scheme-for-EWW-buffers-complex.patch

-- 
Protesilaos Stavrou
https://protesilaos.com
>From 9b1c46c18c113952f2274fab9c334140d5c071e3 Mon Sep 17 00:00:00 2001
Message-Id: <[email-masked]>
From: Protesilaos Stavrou <[email-masked]>
Date: Fri, 15 Oct 2021 14:05:01 +0300
Subject: [PATCH] Implement auto-renaming scheme for EWW buffers

* etc/NEWS: Document the new user options.

* lisp/net/eww.el (eww-auto-rename-buffer, eww-buffer-name-length):
Add new user options.
(eww--rename-buffer): Introduce new function that performs the
renaming of buffers.
(eww--after-page-change): Add new wrapper function which calls
'eww-update-header-line-format' and 'eww--rename-buffer'.
(eww, eww-render, eww-tag-title, eww-readable, eww-restore-history):
Include eww--after-page-change.

Fix bug#51176.

Co-authored-by: Abhiseck Paira <[email-masked]>
Co-authored-by: Protesilaos Stavrou <[email-masked]>
---
 etc/NEWS        | 11 +++++++++
 lisp/net/eww.el | 65 +++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 71 insertions(+), 5 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 7dd4d14274..3300ac157d 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -89,6 +89,17 @@ Customize this option to limit the amount of entries in the menu
 
 * Changes in Specialized Modes and Packages in Emacs 29.1
 
+** eww
+
+---
+*** New user option to automatically rename EWW buffers
+The 'eww-auto-rename-buffer' can be configured to rename rendered web
+pages by using their title, URL, or a user-defined function which
+returns a string.  For the first two cases, the length of the
+resulting name is controlled by 'eww-buffer-name-length'.  By default,
+no automatic renaming is performed.
+
+
 ** image-dired
 
 ---
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index 24c6335210..dc20c1745c 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -178,6 +178,33 @@ (defcustom eww-after-render-hook nil
   :group 'eww
   :type 'hook)
 
+(defcustom eww-auto-rename-buffer nil
+  "Automatically rename EWW buffers once the page is rendered.
+
+When nil, do not rename the buffer.  With a non-nil value
+determine the renaming scheme, as follows:
+
+- `title': Use the web page's title.
+- `url': Use the web page's URL.
+- a function's symbol: Run a user-defined function that returns a
+  string with which to rename the buffer.
+
+The string of `title' and `url' is always truncated to the value
+of `eww-buffer-name-length'."
+  :version "29.1"
+  :type '(choice
+          (const :tag "Do not rename buffers (default)" nil)
+          (const :tag "Rename buffer to web page title" title)
+          (const :tag "Rename buffer to web page URL" url)
+          (function :tag "A user-defined function to rename the buffer"))
+  :group 'eww)
+
+(defcustom eww-buffer-name-length 40
+  "Length of renamed buffer name, per `eww-auto-rename-buffer'."
+  :type 'natnum
+  :version "29.1"
+  :group 'eww)
+
 (defcustom eww-form-checkbox-selected-symbol "[X]"
   "Symbol used to represent a selected checkbox.
 See also `eww-form-checkbox-symbol'."
@@ -353,7 +380,7 @@ (defun eww (url &optional arg buffer)
     (setq url (url-recreate-url parsed)))
   (plist-put eww-data :url url)
   (plist-put eww-data :title "")
-  (eww-update-header-line-format)
+  (eww--after-page-change)
   (let ((inhibit-read-only t))
     (insert (format "Loading %s..." url))
     (goto-char (point-min)))
@@ -502,6 +529,30 @@ (defun eww-html-p (content-type)
   (member content-type '("text/html"
 			 "application/xhtml+xml")))
 
+(defun eww--rename-buffer ()
+  "Rename the current EWW buffer.
+The renaming scheme is performed in accordance with
+`eww-auto-rename-buffer'."
+  (let ((rename-string)
+        (formater
+         (lambda (string)
+           (format "*%s # eww*" (truncate-string-to-width
+                                 string eww-buffer-name-length))))
+        (site-title (plist-get eww-data :title))
+        (site-url (plist-get eww-data :url)))
+    (cond ((null eww-auto-rename-buffer))
+          ((eq eww-auto-rename-buffer 'url)
+           (setq rename-string (funcall formater site-url)))
+          ((functionp eww-auto-rename-buffer)
+           (setq rename-string (funcall eww-auto-rename-buffer)))
+          (t (setq rename-string
+                   (funcall formater (if (or (equal site-title "")
+                                             (null site-title))
+                                         "Untitled"
+                                       site-title)))))
+    (when rename-string
+      (rename-buffer rename-string t))))
+
 (defun eww-render (status url &optional point buffer encode)
   (let* ((headers (eww-parse-headers))
 	 (content-type
@@ -552,7 +603,7 @@ (defun eww-render (status url &optional point buffer encode)
 	    (eww-display-raw buffer (or encode charset 'utf-8))))
 	  (with-current-buffer buffer
 	    (plist-put eww-data :url url)
-	    (eww-update-header-line-format)
+	    (eww--after-page-change)
 	    (setq eww-history-position 0)
 	    (and last-coding-system-used
 		 (set-buffer-file-coding-system last-coding-system-used))
@@ -796,12 +847,16 @@ (defun eww-update-header-line-format ()
 		 `((?u . ,(or url ""))
 		   (?t . ,title))))))))
 
+(defun eww--after-page-change ()
+  (eww-update-header-line-format)
+  (eww--rename-buffer))
+
 (defun eww-tag-title (dom)
   (plist-put eww-data :title
 	     (replace-regexp-in-string
 	      "^ \\| $" ""
 	      (replace-regexp-in-string "[ \t\r\n]+" " " (dom-text dom))))
-  (eww-update-header-line-format))
+  (eww--after-page-change))
 
 (defun eww-display-raw (buffer &optional encode)
   (let ((data (buffer-substring (point) (point-max))))
@@ -929,7 +984,7 @@ (defun eww-readable ()
 		      nil (current-buffer))
     (dolist (elem '(:source :url :title :next :previous :up))
       (plist-put eww-data elem (plist-get old-data elem)))
-    (eww-update-header-line-format)))
+    (eww--after-page-change)))
 
 (defun eww-score-readability (node)
   (let ((score -1))
@@ -1161,7 +1216,7 @@ (defun eww-restore-history (elem)
       (goto-char (plist-get elem :point))
       ;; Make buffer listings more informative.
       (setq list-buffers-directory (plist-get elem :url))
-      (eww-update-header-line-format))))
+      (eww--after-page-change))))
 
 (defun eww-next-url ()
   "Go to the page marked `next'.
-- 
2.33.0

>From 6bd3f685b4602aa478b5e987899e7215af20f25e Mon Sep 17 00:00:00 2001
Message-Id: <[email-masked]>
From: Protesilaos Stavrou <[email-masked]>
Date: Fri, 15 Oct 2021 13:55:44 +0300
Subject: [PATCH] Implement auto-renaming scheme for EWW buffers

* etc/NEWS: Document the new user options.

* lisp/net/eww.el (eww-auto-rename-buffer-function)
(eww-auto-rename-buffer): Add user options.
(eww--rename-buffer): Introduce new function that performs the
renaming of buffers.
(eww--after-page-change): Add new wrapper function which calls
'eww-update-header-line-format' and 'eww-auto-rename-buffer-function'.
(eww, eww-render, eww-tag-title, eww-readable, eww-restore-history):
Include eww--after-page-change.

Fix bug#51176.

Co-authored-by: Abhiseck Paira <[email-masked]>
Co-authored-by: Protesilaos Stavrou <[email-masked]>
---
 etc/NEWS        |  8 ++++++++
 lisp/net/eww.el | 39 ++++++++++++++++++++++++++++++++++-----
 2 files changed, 42 insertions(+), 5 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 7dd4d14274..906ff4e6ae 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -89,6 +89,14 @@
 
 * Changes in Specialized Modes and Packages in Emacs 29.1
 
+** eww
+
+---
+*** New user option to automatically rename EWW buffers
+When 'eww-auto-rename-buffer' is set to a non-nil value, it will make
+all buffers use either the title or the URL of the rendered web page.
+The rendering scheme is handled by 'eww-auto-rename-buffer-function'.
+
 ** image-dired
 
 ---
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index 24c6335210..14cf207e59 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -178,6 +178,21 @@
   :group 'eww
   :type 'hook)
 
+(defcustom eww-auto-rename-buffer-function #'eww--rename-buffer
+  "Function to rename EWW buffer.
+The function is called just before the `eww-after-render-hook' if
+`eww-auto-rename-buffer' is non-nil."
+  :version "29.1"
+  :group 'eww
+  :type 'function)
+
+(defcustom eww-auto-rename-buffer nil
+  "When non-nil rename EWW buffers after they are rendered.
+Renaming is controlled by `eww-auto-rename-buffer-function'."
+  :version "29.1"
+  :group 'eww
+  :type 'boolean)
+
 (defcustom eww-form-checkbox-selected-symbol "[X]"
   "Symbol used to represent a selected checkbox.
 See also `eww-form-checkbox-symbol'."
@@ -353,7 +368,7 @@
     (setq url (url-recreate-url parsed)))
   (plist-put eww-data :url url)
   (plist-put eww-data :title "")
-  (eww-update-header-line-format)
+  (eww--after-page-change)
   (let ((inhibit-read-only t))
     (insert (format "Loading %s..." url))
     (goto-char (point-min)))
@@ -502,6 +517,15 @@
   (member content-type '("text/html"
 			 "application/xhtml+xml")))
 
+(defun eww--rename-buffer ()
+  "Rename the current EWW buffer.
+Use the page's title or URL as an identifier."
+  (when (eq major-mode 'eww-mode)
+    (when-let ((title (or (plist-get eww-data :title)
+                          (plist-get eww-data :url))))
+      (rename-buffer
+       (format "*%s # eww*" (truncate-string-to-width title 40)) t))))
+
 (defun eww-render (status url &optional point buffer encode)
   (let* ((headers (eww-parse-headers))
 	 (content-type
@@ -552,7 +576,7 @@
 	    (eww-display-raw buffer (or encode charset 'utf-8))))
 	  (with-current-buffer buffer
 	    (plist-put eww-data :url url)
-	    (eww-update-header-line-format)
+	    (eww--after-page-change)
 	    (setq eww-history-position 0)
 	    (and last-coding-system-used
 		 (set-buffer-file-coding-system last-coding-system-used))
@@ -796,12 +820,17 @@
 		 `((?u . ,(or url ""))
 		   (?t . ,title))))))))
 
+(defun eww--after-page-change ()
+  (eww-update-header-line-format)
+  (when eww-auto-rename-buffer
+    (funcall eww-auto-rename-buffer-function)))
+
 (defun eww-tag-title (dom)
   (plist-put eww-data :title
 	     (replace-regexp-in-string
 	      "^ \\| $" ""
 	      (replace-regexp-in-string "[ \t\r\n]+" " " (dom-text dom))))
-  (eww-update-header-line-format))
+  (eww--after-page-change))
 
 (defun eww-display-raw (buffer &optional encode)
   (let ((data (buffer-substring (point) (point-max))))
@@ -929,7 +958,7 @@
 		      nil (current-buffer))
     (dolist (elem '(:source :url :title :next :previous :up))
       (plist-put eww-data elem (plist-get old-data elem)))
-    (eww-update-header-line-format)))
+    (eww--after-page-change)))
 
 (defun eww-score-readability (node)
   (let ((score -1))
@@ -1161,7 +1190,7 @@
       (goto-char (plist-get elem :point))
       ;; Make buffer listings more informative.
       (setq list-buffers-directory (plist-get elem :url))
-      (eww-update-header-line-format))))
+      (eww--after-page-change))))
 
 (defun eww-next-url ()
   "Go to the page marked `next'.
-- 
2.33.0