unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#64126: [PATCH] New command 'eww-copy-alternate-url'
@ 2023-06-17 11:07 Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-06-17 13:07 ` Eli Zaretskii
  0 siblings, 1 reply; 10+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-06-17 11:07 UTC (permalink / raw)
  To: 64126

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

Tags: patch

This patch extends EWW with a command that grabs the URL of an alternate
link of the current page, such as an RSS or Atom feed.


In GNU Emacs 30.0.50 (build 5, x86_64-apple-darwin22.5.0, NS
 appkit-2299.60 Version 13.4 (Build 22F66)) of 2023-06-16 built on
 Dazzs-MBP
Repository revision: 8657afac774f36777d0fdd368e0bec64beca22ae
Repository branch: master
Windowing system distributor 'Apple', version 10.3.2299
System Description:  macOS 13.4

Configured using:
 'configure 'CFLAGS=-g0 -O3' --with-native-compilation --with-json
 --with-imagemagick --with-tree-sitter --enable-link-time-optimization'


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-New-command-eww-copy-alternate-url.patch --]
[-- Type: text/patch, Size: 5641 bytes --]

From 998f3048bd0a804b861140991e3c62cf3c42e9ed Mon Sep 17 00:00:00 2001
From: Eshel Yaron <me@eshelyaron.com>
Date: Sat, 17 Jun 2023 13:48:51 +0300
Subject: [PATCH] New command 'eww-copy-alternate-url'

This adds a new command to EWW that copies an alternate link to the
currently visited page into the kill ring.  This is useful for
subscribing to website feeds, etc..

* lisp/net/eww.el (eww--alternate-urls)
(eww-read-alternate-url): New functions.
(eww-copy-alternate-url): New command.
(eww-mode-map): Bind it to 'A'.

* doc/misc/eww.texi (Basics): Document it.

* etc/NEWS: Announce it.
---
 doc/misc/eww.texi |  7 +++++
 etc/NEWS          |  5 ++++
 lisp/net/eww.el   | 75 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 87 insertions(+)

diff --git a/doc/misc/eww.texi b/doc/misc/eww.texi
index c02e9db11c9..2f2a1d7d405 100644
--- a/doc/misc/eww.texi
+++ b/doc/misc/eww.texi
@@ -115,6 +115,13 @@ Basics
 @kbd{w} calls @code{eww-copy-page-url}, which will copy the current
 page's URL to the kill ring instead.
 
+@findex eww-copy-alternate-url
+@kindex A
+  The @kbd{A} command (@code{eww-copy-alternate-url}) copies the URL
+of an alternate link of the current page (such as an associated RSS
+feed) into the kill ring.  If the page specifies multiple alternate
+links, this command prompt for one of them in the minibuffer.
+
 @findex eww-open-in-new-buffer
 @kindex M-RET
   The @kbd{M-@key{RET}} command (@code{eww-open-in-new-buffer}) opens the
diff --git a/etc/NEWS b/etc/NEWS
index 61e6e161665..7c94c3efa89 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -253,6 +253,11 @@ The interactive minibuffer prompt when invoking 'eww' now provides
 completions from 'eww-suggest-uris'.  'eww-suggest-uris' now includes
 bookmark URIs.
 
++++
+*** New command 'eww-copy-alternate-url'.
+It copies an alternate link to the page currently visited in EWW into
+the kill ring.
+
 ** go-ts-mode
 
 +++
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index 61f0f47373d..3ce9061ea7d 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -1086,6 +1086,7 @@ eww-mode-map
   "&" #'eww-browse-with-external-browser
   "d" #'eww-download
   "w" #'eww-copy-page-url
+  "A" #'eww-copy-alternate-url
   "C" #'url-cookie-list
   "v" #'eww-view-source
   "R" #'eww-readable
@@ -2576,4 +2577,78 @@ eww-bookmark-jump
 
 (provide 'eww)
 
+;;; Alternate links (RSS and Atom feeds, etc.)
+
+(defun eww--alternate-urls (dom &optional base)
+  "Return an alist of alternate links in DOM.
+
+Each element is a list of the form (URL TYPE TITLE) where URL is
+the href attribute of the link expanded relative to BASE, TYPE is
+its type attribute, and TITLE is its title attribute.  If any of
+these attributes is absent, the corresponding element is nil."
+  (let ((alternates
+         (seq-filter
+          (lambda (attrs) (string= (alist-get 'rel attrs)
+                                   "alternate"))
+          (mapcar #'dom-attributes (dom-by-tag dom 'link)))))
+    (mapcar (lambda (alternate)
+              (list (url-expand-file-name (alist-get 'href alternate)
+                                          base)
+                    (alist-get 'type  alternate)
+                    (alist-get 'title alternate)))
+            alternates)))
+
+(defun eww-read-alternate-url ()
+  "Get the URL of an alternate link of this page.
+
+If there is just one alternate link, return it's URL.  If there
+are multiple alternate links, prompt for one in the minibuffer.
+If there are none, return nil."
+  (when-let ((alternates (eww--alternate-urls
+                          (plist-get eww-data :dom)
+                          (plist-get eww-data :url))))
+    (let ((max-length
+           (apply #'max
+                  (mapcar #'length
+                          (mapcar #'car alternates))))
+          (max-title
+           (apply #'max
+                  (mapcar #'length
+                          (mapcar #'caddr alternates)))))
+      (if (cdr alternates)
+          (let ((completion-extra-properties
+                 (list :annotation-function
+                       (lambda (feed)
+                         (let* ((attrs (alist-get feed
+                                                  alternates
+                                                  nil
+                                                  nil
+                                                  #'string=))
+                                (type (car attrs))
+                                (title (cadr attrs)))
+                           (concat (when title
+                                     (concat (make-string
+                                              (1+ (- max-length
+                                                     (length feed)))
+                                              ?\s)
+                                             title))
+                                   (when type
+                                     (concat
+                                      (make-string
+                                       (1+ (- max-title
+                                              (length title)))
+                                       ?\s)
+                                      "[" type "]"))))))))
+            (completing-read "Alternate URL: " alternates nil t))
+        (caar alternates)))))
+
+(defun eww-copy-alternate-url ()
+  "Copy an alternate URL of the current page into the kill ring."
+  (interactive nil eww-mode)
+  (if-let ((url (eww-read-alternate-url)))
+      (progn
+        (kill-new url)
+        (message "Copied %s to kill ring" url))
+    (user-error "No feeds found!")))
+
 ;;; eww.el ends here
-- 
2.41.0


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

* bug#64126: [PATCH] New command 'eww-copy-alternate-url'
  2023-06-17 11:07 bug#64126: [PATCH] New command 'eww-copy-alternate-url' Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-06-17 13:07 ` Eli Zaretskii
  2023-06-17 14:08   ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 10+ messages in thread
From: Eli Zaretskii @ 2023-06-17 13:07 UTC (permalink / raw)
  To: Eshel Yaron; +Cc: 64126

> Date: Sat, 17 Jun 2023 14:07:40 +0300
> From:  Eshel Yaron via "Bug reports for GNU Emacs,
>  the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
> 
> This patch extends EWW with a command that grabs the URL of an alternate
> link of the current page, such as an RSS or Atom feed.

Thanks.

> This adds a new command to EWW that copies an alternate link to the
> currently visited page into the kill ring.  This is useful for
> subscribing to website feeds, etc..
                                   ^^
Two periods, one of which is probably redunant.

> +@findex eww-copy-alternate-url
> +@kindex A
> +  The @kbd{A} command (@code{eww-copy-alternate-url}) copies the URL
> +of an alternate link of the current page (such as an associated RSS
> +feed) into the kill ring.  If the page specifies multiple alternate
> +links, this command prompt for one of them in the minibuffer.

This doesn't say anything about what an "alternate link" could be, it
just provides a single example.  Since this is for the manual (as
opposed to the doc string), there's no need to be so terse; we should
instead explain more about what these alternate links are or could be,
and give more than just a single example.  Perhaps also tell how the
alternate links are designated in HTML.

> +*** New command 'eww-copy-alternate-url'.
> +It copies an alternate link to the page currently visited in EWW into
> +the kill ring.

Searching the Internet for "alternate link" brings this:

  A type of hyperlink that gives alternate representations of the
  current document.

Is this what is meant here?  If so, why are you talking about RSS
feeds?

> +(defun eww-read-alternate-url ()
> +  "Get the URL of an alternate link of this page.
> +
> +If there is just one alternate link, return it's URL.  If there
                                               ^^^^
"its"

> +are multiple alternate links, prompt for one in the minibuffer.

I guess the prompt is with completion?  If so, please mention that.

> +(defun eww-copy-alternate-url ()
> +  "Copy an alternate URL of the current page into the kill ring."

This doc string says nothing at all about what an alternate link is.
It should say at least something.

> +  (interactive nil eww-mode)
> +  (if-let ((url (eww-read-alternate-url)))
> +      (progn
> +        (kill-new url)
> +        (message "Copied %s to kill ring" url))
> +    (user-error "No feeds found!")))

"No feeds"?  Can the alternate link be something other than a feed?
In any case, "No feeds found on this page!" is better, I think, as "No
feeds!" is too general.





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

* bug#64126: [PATCH] New command 'eww-copy-alternate-url'
  2023-06-17 13:07 ` Eli Zaretskii
@ 2023-06-17 14:08   ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-06-17 17:08     ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-06-21 14:04     ` Eli Zaretskii
  0 siblings, 2 replies; 10+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-06-17 14:08 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 64126

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

Thanks for your comments, Eli, I'm attaching an updated patch below.

Eli Zaretskii <eliz@gnu.org> writes:

>> This adds a new command to EWW that copies an alternate link to the
>> currently visited page into the kill ring.  This is useful for
>> subscribing to website feeds, etc..
>                                    ^^
> Two periods, one of which is probably redunant.
>

Fixed.

>> +@findex eww-copy-alternate-url
>> +@kindex A
>> +  The @kbd{A} command (@code{eww-copy-alternate-url}) copies the URL
>> +of an alternate link of the current page (such as an associated RSS
>> +feed) into the kill ring.  If the page specifies multiple alternate
>> +links, this command prompt for one of them in the minibuffer.
>
> This doesn't say anything about what an "alternate link" could be, it
> just provides a single example.  Since this is for the manual (as
> opposed to the doc string), there's no need to be so terse; we should
> instead explain more about what these alternate links are or could be,
> and give more than just a single example.  Perhaps also tell how the
> alternate links are designated in HTML.
>

Alright, I wasn't sure how much to elaborate here, I've added more
details in the updated patch.  I hope I got the formatting right for
referring to HTML elements, basically I tried to follow similar existing
cases in eww.texi.

>> +*** New command 'eww-copy-alternate-url'.
>> +It copies an alternate link to the page currently visited in EWW into
>> +the kill ring.
>
> Searching the Internet for "alternate link" brings this:
>
>   A type of hyperlink that gives alternate representations of the
>   current document.
>
> Is this what is meant here?  If so, why are you talking about RSS
> feeds?
>

Yes, websites very often use these alternate links to point to their
RSS/Atom feeds.  Should I add a couple of words about that in the NEWS
entry as well?

For instance, https://www.gnu.org/ lists
https://planet.gnu.org/rss20.xml as an alternate link (as well as
translations of that webpage to other languages).

There's more information about alternate links here
https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel#alternate


>> +(defun eww-read-alternate-url ()
>> +  "Get the URL of an alternate link of this page.
>> +
>> +If there is just one alternate link, return it's URL.  If there
>                                                ^^^^
> "its"
>

Thanks, fixed.

>> +are multiple alternate links, prompt for one in the minibuffer.
>
> I guess the prompt is with completion?  If so, please mention that.
>

Done.

>> +(defun eww-copy-alternate-url ()
>> +  "Copy an alternate URL of the current page into the kill ring."
>
> This doc string says nothing at all about what an alternate link is.
> It should say at least something.
>

Sure, I've added a couple of words here as well.

>> +  (interactive nil eww-mode)
>> +  (if-let ((url (eww-read-alternate-url)))
>> +      (progn
>> +        (kill-new url)
>> +        (message "Copied %s to kill ring" url))
>> +    (user-error "No feeds found!")))
>
> "No feeds"?  Can the alternate link be something other than a feed?
> In any case, "No feeds found on this page!" is better, I think, as "No
> feeds!" is too general.

You're right, thanks, I've changed this to "No alternate links found on
this page!".



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: v2-0001-New-command-eww-copy-alternate-url.patch --]
[-- Type: text/x-patch, Size: 6342 bytes --]

From 70e10c40cf2319b316611c56be53a27b6e67cad5 Mon Sep 17 00:00:00 2001
From: Eshel Yaron <me@eshelyaron.com>
Date: Sat, 17 Jun 2023 13:48:51 +0300
Subject: [PATCH v2] New command 'eww-copy-alternate-url'

This adds a new command to EWW that copies an alternate link to the
currently visited page into the kill ring.  This is useful for
subscribing to website feeds, etc.

* lisp/net/eww.el (eww--alternate-urls)
(eww-read-alternate-url): New functions.
(eww-copy-alternate-url): New command.
(eww-mode-map): Bind it to 'A'.

* doc/misc/eww.texi (Basics): Document it.

* etc/NEWS: Announce it.
---
 doc/misc/eww.texi | 15 +++++++++
 etc/NEWS          |  5 +++
 lisp/net/eww.el   | 79 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 99 insertions(+)

diff --git a/doc/misc/eww.texi b/doc/misc/eww.texi
index c02e9db11c9..cff48bd601e 100644
--- a/doc/misc/eww.texi
+++ b/doc/misc/eww.texi
@@ -115,6 +115,21 @@ Basics
 @kbd{w} calls @code{eww-copy-page-url}, which will copy the current
 page's URL to the kill ring instead.
 
+@findex eww-copy-alternate-url
+@kindex A
+  The @kbd{A} command (@code{eww-copy-alternate-url}) copies the URL
+of an alternate link of the current page into the kill ring.  If the
+page specifies multiple alternate links, this command prompts for one
+of them in the minibuffer, with completion.  Alternate links are
+references that an @acronym{HTML} page may include to point to other
+documents that act as its alternative representations.  Notably,
+@acronym{HTML} pages can use alternate links to point to their
+translated versions and to @acronym{RSS} feeds.  Alternate links
+appear in the @samp{<head>} section of @acronym{HTML} pages as
+@samp{<link>} elements with @samp{rel} attribute equal to
+@samp{``alternate''}, they are part of the page's metadata and are not
+visible in its rendered content.
+
 @findex eww-open-in-new-buffer
 @kindex M-RET
   The @kbd{M-@key{RET}} command (@code{eww-open-in-new-buffer}) opens the
diff --git a/etc/NEWS b/etc/NEWS
index 61e6e161665..7c94c3efa89 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -253,6 +253,11 @@ The interactive minibuffer prompt when invoking 'eww' now provides
 completions from 'eww-suggest-uris'.  'eww-suggest-uris' now includes
 bookmark URIs.
 
++++
+*** New command 'eww-copy-alternate-url'.
+It copies an alternate link to the page currently visited in EWW into
+the kill ring.
+
 ** go-ts-mode
 
 +++
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index 61f0f47373d..6e8bb5961a0 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -1086,6 +1086,7 @@ eww-mode-map
   "&" #'eww-browse-with-external-browser
   "d" #'eww-download
   "w" #'eww-copy-page-url
+  "A" #'eww-copy-alternate-url
   "C" #'url-cookie-list
   "v" #'eww-view-source
   "R" #'eww-readable
@@ -2576,4 +2577,82 @@ eww-bookmark-jump
 
 (provide 'eww)
 
+;;; Alternate links (RSS and Atom feeds, etc.)
+
+(defun eww--alternate-urls (dom &optional base)
+  "Return an alist of alternate links in DOM.
+
+Each element is a list of the form (URL TYPE TITLE) where URL is
+the href attribute of the link expanded relative to BASE, TYPE is
+its type attribute, and TITLE is its title attribute.  If any of
+these attributes is absent, the corresponding element is nil."
+  (let ((alternates
+         (seq-filter
+          (lambda (attrs) (string= (alist-get 'rel attrs)
+                                   "alternate"))
+          (mapcar #'dom-attributes (dom-by-tag dom 'link)))))
+    (mapcar (lambda (alternate)
+              (list (url-expand-file-name (alist-get 'href alternate)
+                                          base)
+                    (alist-get 'type  alternate)
+                    (alist-get 'title alternate)))
+            alternates)))
+
+(defun eww-read-alternate-url ()
+  "Get the URL of an alternate link of this page.
+
+If there is just one alternate link, return its URL.  If there
+are multiple alternate links, prompt for one in the minibuffer
+with completion.  If there are none, return nil."
+  (when-let ((alternates (eww--alternate-urls
+                          (plist-get eww-data :dom)
+                          (plist-get eww-data :url))))
+    (let ((max-length
+           (apply #'max
+                  (mapcar #'length
+                          (mapcar #'car alternates))))
+          (max-title
+           (apply #'max
+                  (mapcar #'length
+                          (mapcar #'caddr alternates)))))
+      (if (cdr alternates)
+          (let ((completion-extra-properties
+                 (list :annotation-function
+                       (lambda (feed)
+                         (let* ((attrs (alist-get feed
+                                                  alternates
+                                                  nil
+                                                  nil
+                                                  #'string=))
+                                (type (car attrs))
+                                (title (cadr attrs)))
+                           (concat (when title
+                                     (concat (make-string
+                                              (1+ (- max-length
+                                                     (length feed)))
+                                              ?\s)
+                                             title))
+                                   (when type
+                                     (concat
+                                      (make-string
+                                       (1+ (- max-title
+                                              (length title)))
+                                       ?\s)
+                                      "[" type "]"))))))))
+            (completing-read "Alternate URL: " alternates nil t))
+        (caar alternates)))))
+
+(defun eww-copy-alternate-url ()
+  "Copy an alternate URL of the current page into the kill ring.
+
+Alternate links are references that an HTML page may include to
+point to its alternative representations, such as a translated
+version or an RSS feed."
+  (interactive nil eww-mode)
+  (if-let ((url (eww-read-alternate-url)))
+      (progn
+        (kill-new url)
+        (message "Copied %s to kill ring" url))
+    (user-error "No alternate links found on this page!")))
+
 ;;; eww.el ends here
-- 
2.41.0


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

* bug#64126: [PATCH] New command 'eww-copy-alternate-url'
  2023-06-17 14:08   ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-06-17 17:08     ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-06-21  6:01       ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-06-21 14:04     ` Eli Zaretskii
  1 sibling, 1 reply; 10+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-06-17 17:08 UTC (permalink / raw)
  To: 64126; +Cc: Eli Zaretskii

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

I'm attaching yet another updated patch (v3), the difference compared to
the former patch is that now the alignment of completion candidate
annotations is based on `string-pixel-width` and `display` text
properties instead of padding with spaces.

This deals better with more exotic strings that may appear in the link's
title (again gnu.org is a good example here, as there are alternate link
titles in different languages).  Still I wonder if there's a more
principled way to align such annotations, any suggestions?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: v3-0001-New-command-eww-copy-alternate-url.patch --]
[-- Type: text/x-patch, Size: 6454 bytes --]

From 2337ba007e2d0512b2a4445e6749ef51df343417 Mon Sep 17 00:00:00 2001
From: Eshel Yaron <me@eshelyaron.com>
Date: Sat, 17 Jun 2023 13:48:51 +0300
Subject: [PATCH v3] New command 'eww-copy-alternate-url'

This adds a new command to EWW that copies an alternate link to the
currently visited page into the kill ring.  This is useful for
subscribing to website feeds, etc.

* lisp/net/eww.el (eww--alternate-urls)
(eww-read-alternate-url): New functions.
(eww-copy-alternate-url): New command.
(eww-mode-map): Bind it to 'A'.

* doc/misc/eww.texi (Basics): Document it.

* etc/NEWS: Announce it.
---
 doc/misc/eww.texi | 15 +++++++++
 etc/NEWS          |  5 +++
 lisp/net/eww.el   | 79 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 99 insertions(+)

diff --git a/doc/misc/eww.texi b/doc/misc/eww.texi
index c02e9db11c9..cff48bd601e 100644
--- a/doc/misc/eww.texi
+++ b/doc/misc/eww.texi
@@ -115,6 +115,21 @@ Basics
 @kbd{w} calls @code{eww-copy-page-url}, which will copy the current
 page's URL to the kill ring instead.
 
+@findex eww-copy-alternate-url
+@kindex A
+  The @kbd{A} command (@code{eww-copy-alternate-url}) copies the URL
+of an alternate link of the current page into the kill ring.  If the
+page specifies multiple alternate links, this command prompts for one
+of them in the minibuffer, with completion.  Alternate links are
+references that an @acronym{HTML} page may include to point to other
+documents that act as its alternative representations.  Notably,
+@acronym{HTML} pages can use alternate links to point to their
+translated versions and to @acronym{RSS} feeds.  Alternate links
+appear in the @samp{<head>} section of @acronym{HTML} pages as
+@samp{<link>} elements with @samp{rel} attribute equal to
+@samp{``alternate''}, they are part of the page's metadata and are not
+visible in its rendered content.
+
 @findex eww-open-in-new-buffer
 @kindex M-RET
   The @kbd{M-@key{RET}} command (@code{eww-open-in-new-buffer}) opens the
diff --git a/etc/NEWS b/etc/NEWS
index 61e6e161665..7c94c3efa89 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -253,6 +253,11 @@ The interactive minibuffer prompt when invoking 'eww' now provides
 completions from 'eww-suggest-uris'.  'eww-suggest-uris' now includes
 bookmark URIs.
 
++++
+*** New command 'eww-copy-alternate-url'.
+It copies an alternate link to the page currently visited in EWW into
+the kill ring.
+
 ** go-ts-mode
 
 +++
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index 61f0f47373d..89f7ba37cc1 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -1086,6 +1086,7 @@ eww-mode-map
   "&" #'eww-browse-with-external-browser
   "d" #'eww-download
   "w" #'eww-copy-page-url
+  "A" #'eww-copy-alternate-url
   "C" #'url-cookie-list
   "v" #'eww-view-source
   "R" #'eww-readable
@@ -2576,4 +2577,82 @@ eww-bookmark-jump
 
 (provide 'eww)
 
+;;; Alternate links (RSS and Atom feeds, etc.)
+
+(defun eww--alternate-urls (dom &optional base)
+  "Return an alist of alternate links in DOM.
+
+Each element is a list of the form (URL TYPE TITLE) where URL is
+the href attribute of the link expanded relative to BASE, TYPE is
+its type attribute, and TITLE is its title attribute.  If any of
+these attributes is absent, the corresponding element is nil."
+  (let ((alternates
+         (seq-filter
+          (lambda (attrs) (string= (alist-get 'rel attrs)
+                                   "alternate"))
+          (mapcar #'dom-attributes (dom-by-tag dom 'link)))))
+    (mapcar (lambda (alternate)
+              (list (url-expand-file-name (alist-get 'href alternate)
+                                          base)
+                    (alist-get 'type  alternate)
+                    (alist-get 'title alternate)))
+            alternates)))
+
+(defun eww-read-alternate-url ()
+  "Get the URL of an alternate link of this page.
+
+If there is just one alternate link, return its URL.  If there
+are multiple alternate links, prompt for one in the minibuffer
+with completion.  If there are none, return nil."
+  (when-let ((alternates (eww--alternate-urls
+                          (plist-get eww-data :dom)
+                          (plist-get eww-data :url))))
+    (let ((url-max-width
+           (seq-max (mapcar #'string-pixel-width
+                            (mapcar #'car alternates))))
+          (title-max-width
+           (seq-max (mapcar #'string-pixel-width
+                            (mapcar #'caddr alternates))))
+          (sep-width (string-pixel-width " ")))
+      (if (cdr alternates)
+          (let ((completion-extra-properties
+                 (list :annotation-function
+                       (lambda (feed)
+                         (let* ((attrs (alist-get feed
+                                                  alternates
+                                                  nil
+                                                  nil
+                                                  #'string=))
+                                (type (car attrs))
+                                (title (cadr attrs)))
+                           (concat
+                            (propertize " " 'display
+                                        `(space :align-to
+                                                (,(+ sep-width
+                                                     url-max-width))))
+                            title
+                            (when type
+                              (concat
+                               (propertize " " 'display
+                                           `(space :align-to
+                                                   (,(+ (* 2 sep-width)
+                                                        url-max-width
+                                                        title-max-width))))
+                               "[" type "]"))))))))
+            (completing-read "Alternate URL: " alternates nil t))
+        (caar alternates)))))
+
+(defun eww-copy-alternate-url ()
+  "Copy an alternate URL of the current page into the kill ring.
+
+Alternate links are references that an HTML page may include to
+point to its alternative representations, such as a translated
+version or an RSS feed."
+  (interactive nil eww-mode)
+  (if-let ((url (eww-read-alternate-url)))
+      (progn
+        (kill-new url)
+        (message "Copied %s to kill ring" url))
+    (user-error "No alternate links found on this page!")))
+
 ;;; eww.el ends here
-- 
2.41.0


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

* bug#64126: [PATCH] New command 'eww-copy-alternate-url'
  2023-06-17 17:08     ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-06-21  6:01       ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-06-21 11:00         ` Eli Zaretskii
  0 siblings, 1 reply; 10+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-06-21  6:01 UTC (permalink / raw)
  To: 64126; +Cc: eliz

Hi all,
Any further comments about this addition?

> I'm attaching yet another updated patch (v3), the difference compared to
> the former patch is that now the alignment of completion candidate
> annotations is based on `string-pixel-width` and `display` text
> properties instead of padding with spaces.
>
> This deals better with more exotic strings that may appear in the link's
> title (again gnu.org is a good example here, as there are alternate link
> titles in different languages).  Still I wonder if there's a more
> principled way to align such annotations, any suggestions?
>
> From 2337ba007e2d0512b2a4445e6749ef51df343417 Mon Sep 17 00:00:00 2001
> From: Eshel Yaron <me@eshelyaron.com>
> Date: Sat, 17 Jun 2023 13:48:51 +0300
> Subject: [PATCH v3] New command 'eww-copy-alternate-url'
>
> This adds a new command to EWW that copies an alternate link to the
> currently visited page into the kill ring.  This is useful for
> subscribing to website feeds, etc.
>
> * lisp/net/eww.el (eww--alternate-urls)
> (eww-read-alternate-url): New functions.
> (eww-copy-alternate-url): New command.
> (eww-mode-map): Bind it to 'A'.
>
> * doc/misc/eww.texi (Basics): Document it.
>
> * etc/NEWS: Announce it.
> ---
>  doc/misc/eww.texi | 15 +++++++++
>  etc/NEWS          |  5 +++
>  lisp/net/eww.el   | 79 +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 99 insertions(+)
>
> diff --git a/doc/misc/eww.texi b/doc/misc/eww.texi
> index c02e9db11c9..cff48bd601e 100644
> --- a/doc/misc/eww.texi
> +++ b/doc/misc/eww.texi
> @@ -115,6 +115,21 @@ Basics
>  @kbd{w} calls @code{eww-copy-page-url}, which will copy the current
>  page's URL to the kill ring instead.
>  
> +@findex eww-copy-alternate-url
> +@kindex A
> +  The @kbd{A} command (@code{eww-copy-alternate-url}) copies the URL
> +of an alternate link of the current page into the kill ring.  If the
> +page specifies multiple alternate links, this command prompts for one
> +of them in the minibuffer, with completion.  Alternate links are
> +references that an @acronym{HTML} page may include to point to other
> +documents that act as its alternative representations.  Notably,
> +@acronym{HTML} pages can use alternate links to point to their
> +translated versions and to @acronym{RSS} feeds.  Alternate links
> +appear in the @samp{<head>} section of @acronym{HTML} pages as
> +@samp{<link>} elements with @samp{rel} attribute equal to
> +@samp{``alternate''}, they are part of the page's metadata and are not
> +visible in its rendered content.
> +
>  @findex eww-open-in-new-buffer
>  @kindex M-RET
>    The @kbd{M-@key{RET}} command (@code{eww-open-in-new-buffer}) opens the
> diff --git a/etc/NEWS b/etc/NEWS
> index 61e6e161665..7c94c3efa89 100644
> --- a/etc/NEWS
> +++ b/etc/NEWS
> @@ -253,6 +253,11 @@ The interactive minibuffer prompt when invoking 'eww' now provides
>  completions from 'eww-suggest-uris'.  'eww-suggest-uris' now includes
>  bookmark URIs.
>  
> ++++
> +*** New command 'eww-copy-alternate-url'.
> +It copies an alternate link to the page currently visited in EWW into
> +the kill ring.
> +
>  ** go-ts-mode
>  
>  +++
> diff --git a/lisp/net/eww.el b/lisp/net/eww.el
> index 61f0f47373d..89f7ba37cc1 100644
> --- a/lisp/net/eww.el
> +++ b/lisp/net/eww.el
> @@ -1086,6 +1086,7 @@ eww-mode-map
>    "&" #'eww-browse-with-external-browser
>    "d" #'eww-download
>    "w" #'eww-copy-page-url
> +  "A" #'eww-copy-alternate-url
>    "C" #'url-cookie-list
>    "v" #'eww-view-source
>    "R" #'eww-readable
> @@ -2576,4 +2577,82 @@ eww-bookmark-jump
>  
>  (provide 'eww)
>  
> +;;; Alternate links (RSS and Atom feeds, etc.)
> +
> +(defun eww--alternate-urls (dom &optional base)
> +  "Return an alist of alternate links in DOM.
> +
> +Each element is a list of the form (URL TYPE TITLE) where URL is
> +the href attribute of the link expanded relative to BASE, TYPE is
> +its type attribute, and TITLE is its title attribute.  If any of
> +these attributes is absent, the corresponding element is nil."
> +  (let ((alternates
> +         (seq-filter
> +          (lambda (attrs) (string= (alist-get 'rel attrs)
> +                                   "alternate"))
> +          (mapcar #'dom-attributes (dom-by-tag dom 'link)))))
> +    (mapcar (lambda (alternate)
> +              (list (url-expand-file-name (alist-get 'href alternate)
> +                                          base)
> +                    (alist-get 'type  alternate)
> +                    (alist-get 'title alternate)))
> +            alternates)))
> +
> +(defun eww-read-alternate-url ()
> +  "Get the URL of an alternate link of this page.
> +
> +If there is just one alternate link, return its URL.  If there
> +are multiple alternate links, prompt for one in the minibuffer
> +with completion.  If there are none, return nil."
> +  (when-let ((alternates (eww--alternate-urls
> +                          (plist-get eww-data :dom)
> +                          (plist-get eww-data :url))))
> +    (let ((url-max-width
> +           (seq-max (mapcar #'string-pixel-width
> +                            (mapcar #'car alternates))))
> +          (title-max-width
> +           (seq-max (mapcar #'string-pixel-width
> +                            (mapcar #'caddr alternates))))
> +          (sep-width (string-pixel-width " ")))
> +      (if (cdr alternates)
> +          (let ((completion-extra-properties
> +                 (list :annotation-function
> +                       (lambda (feed)
> +                         (let* ((attrs (alist-get feed
> +                                                  alternates
> +                                                  nil
> +                                                  nil
> +                                                  #'string=))
> +                                (type (car attrs))
> +                                (title (cadr attrs)))
> +                           (concat
> +                            (propertize " " 'display
> +                                        `(space :align-to
> +                                                (,(+ sep-width
> +                                                     url-max-width))))
> +                            title
> +                            (when type
> +                              (concat
> +                               (propertize " " 'display
> +                                           `(space :align-to
> +                                                   (,(+ (* 2 sep-width)
> +                                                        url-max-width
> +                                                        title-max-width))))
> +                               "[" type "]"))))))))
> +            (completing-read "Alternate URL: " alternates nil t))
> +        (caar alternates)))))
> +
> +(defun eww-copy-alternate-url ()
> +  "Copy an alternate URL of the current page into the kill ring.
> +
> +Alternate links are references that an HTML page may include to
> +point to its alternative representations, such as a translated
> +version or an RSS feed."
> +  (interactive nil eww-mode)
> +  (if-let ((url (eww-read-alternate-url)))
> +      (progn
> +        (kill-new url)
> +        (message "Copied %s to kill ring" url))
> +    (user-error "No alternate links found on this page!")))
> +
>  ;;; eww.el ends here


-- 
Thanks,

Eshel





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

* bug#64126: [PATCH] New command 'eww-copy-alternate-url'
  2023-06-21  6:01       ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-06-21 11:00         ` Eli Zaretskii
  2023-06-21 12:02           ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 10+ messages in thread
From: Eli Zaretskii @ 2023-06-21 11:00 UTC (permalink / raw)
  To: Eshel Yaron; +Cc: 64126

> From: Eshel Yaron <me@eshelyaron.com>
> Cc: 64126@debbugs.gnu.org,  Eli Zaretskii <eliz@gnu.org>
> Date: Wed, 21 Jun 2023 09:01:03 +0300
> 
> Hi all,
> Any further comments about this addition?

Please allow more than just 3-4 days before pinging.  This changeset
is for master, not for the release branch, and it adds a new feature
(i.e. is not a bugfix).  Such changes are less urgent, and IME it is a
good idea to let them be posted for at least a week before installing,
to let enough people notice and comment if they want.  (And in this
case I didn't yet have time to review this final version myself.)

TIA





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

* bug#64126: [PATCH] New command 'eww-copy-alternate-url'
  2023-06-21 11:00         ` Eli Zaretskii
@ 2023-06-21 12:02           ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 0 replies; 10+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-06-21 12:02 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 64126

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Eshel Yaron <me@eshelyaron.com>
>> Cc: 64126@debbugs.gnu.org,  Eli Zaretskii <eliz@gnu.org>
>> Date: Wed, 21 Jun 2023 09:01:03 +0300
>> 
>> Hi all,
>> Any further comments about this addition?
>
> Please allow more than just 3-4 days before pinging.  This changeset
> is for master, not for the release branch, and it adds a new feature
> (i.e. is not a bugfix).  Such changes are less urgent, and IME it is a
> good idea to let them be posted for at least a week before installing,
> to let enough people notice and comment if they want.

No problem, I'll keep that in mind.

> (And in this case I didn't yet have time to review this final version
> myself.)
>
> TIA

Thanks,

Eshel





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

* bug#64126: [PATCH] New command 'eww-copy-alternate-url'
  2023-06-17 14:08   ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-06-17 17:08     ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-06-21 14:04     ` Eli Zaretskii
  2023-06-21 17:20       ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  1 sibling, 1 reply; 10+ messages in thread
From: Eli Zaretskii @ 2023-06-21 14:04 UTC (permalink / raw)
  To: Eshel Yaron; +Cc: 64126

> From: Eshel Yaron <me@eshelyaron.com>
> Cc: 64126@debbugs.gnu.org
> Date: Sat, 17 Jun 2023 17:08:24 +0300
> 
> >> +*** New command 'eww-copy-alternate-url'.
> >> +It copies an alternate link to the page currently visited in EWW into
> >> +the kill ring.
> >
> > Searching the Internet for "alternate link" brings this:
> >
> >   A type of hyperlink that gives alternate representations of the
> >   current document.
> >
> > Is this what is meant here?  If so, why are you talking about RSS
> > feeds?
> >
> 
> Yes, websites very often use these alternate links to point to their
> RSS/Atom feeds.  Should I add a couple of words about that in the NEWS
> entry as well?

Yes, a few more words of explanation would be good there.





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

* bug#64126: [PATCH] New command 'eww-copy-alternate-url'
  2023-06-21 14:04     ` Eli Zaretskii
@ 2023-06-21 17:20       ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-06-24 12:00         ` Eli Zaretskii
  0 siblings, 1 reply; 10+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-06-21 17:20 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 64126

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

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Eshel Yaron <me@eshelyaron.com>
>> 
>> >> +*** New command 'eww-copy-alternate-url'.
>> >> +It copies an alternate link to the page currently visited in EWW into
>> >> +the kill ring.
>> >
>> > Searching the Internet for "alternate link" brings this:
>> >
>> >   A type of hyperlink that gives alternate representations of the
>> >   current document.
>> >
>> > Is this what is meant here?  If so, why are you talking about RSS
>> > feeds?
>> >
>> 
>> Yes, websites very often use these alternate links to point to their
>> RSS/Atom feeds.  Should I add a couple of words about that in the NEWS
>> entry as well?
>
> Yes, a few more words of explanation would be good there.

Sure, I've added a few words about alternate links to the NEWS entry in
the following (updated) patch:


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: v4-0001-New-command-eww-copy-alternate-url.patch --]
[-- Type: text/x-patch, Size: 6621 bytes --]

From 6f2de147056000d2007d7715f1f616ff6a37a508 Mon Sep 17 00:00:00 2001
From: Eshel Yaron <me@eshelyaron.com>
Date: Sat, 17 Jun 2023 13:48:51 +0300
Subject: [PATCH v4] New command 'eww-copy-alternate-url'

This adds a new command to EWW that copies an alternate link to the
currently visited page into the kill ring.  This is useful for
subscribing to website feeds, etc.

* lisp/net/eww.el (eww--alternate-urls)
(eww-read-alternate-url): New functions.
(eww-copy-alternate-url): New command.
(eww-mode-map): Bind it to 'A'.

* doc/misc/eww.texi (Basics): Document it.

* etc/NEWS: Announce it.
---
 doc/misc/eww.texi | 15 +++++++++
 etc/NEWS          |  7 +++++
 lisp/net/eww.el   | 79 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 101 insertions(+)

diff --git a/doc/misc/eww.texi b/doc/misc/eww.texi
index c02e9db11c9..cff48bd601e 100644
--- a/doc/misc/eww.texi
+++ b/doc/misc/eww.texi
@@ -115,6 +115,21 @@ Basics
 @kbd{w} calls @code{eww-copy-page-url}, which will copy the current
 page's URL to the kill ring instead.
 
+@findex eww-copy-alternate-url
+@kindex A
+  The @kbd{A} command (@code{eww-copy-alternate-url}) copies the URL
+of an alternate link of the current page into the kill ring.  If the
+page specifies multiple alternate links, this command prompts for one
+of them in the minibuffer, with completion.  Alternate links are
+references that an @acronym{HTML} page may include to point to other
+documents that act as its alternative representations.  Notably,
+@acronym{HTML} pages can use alternate links to point to their
+translated versions and to @acronym{RSS} feeds.  Alternate links
+appear in the @samp{<head>} section of @acronym{HTML} pages as
+@samp{<link>} elements with @samp{rel} attribute equal to
+@samp{``alternate''}, they are part of the page's metadata and are not
+visible in its rendered content.
+
 @findex eww-open-in-new-buffer
 @kindex M-RET
   The @kbd{M-@key{RET}} command (@code{eww-open-in-new-buffer}) opens the
diff --git a/etc/NEWS b/etc/NEWS
index d703b7e77be..c2299c2998e 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -258,6 +258,13 @@ The interactive minibuffer prompt when invoking 'eww' now provides
 completions from 'eww-suggest-uris'.  'eww-suggest-uris' now includes
 bookmark URIs.
 
++++
+*** New command 'eww-copy-alternate-url'.
+It copies an alternate link to the page currently visited in EWW into
+the kill ring.  Alternate links are optional metadata that HTML pages
+use for linking to their alternative representations, such as
+translated versions or associated RSS feeds.
+
 ** go-ts-mode
 
 +++
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index 61f0f47373d..89f7ba37cc1 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -1086,6 +1086,7 @@ eww-mode-map
   "&" #'eww-browse-with-external-browser
   "d" #'eww-download
   "w" #'eww-copy-page-url
+  "A" #'eww-copy-alternate-url
   "C" #'url-cookie-list
   "v" #'eww-view-source
   "R" #'eww-readable
@@ -2576,4 +2577,82 @@ eww-bookmark-jump
 
 (provide 'eww)
 
+;;; Alternate links (RSS and Atom feeds, etc.)
+
+(defun eww--alternate-urls (dom &optional base)
+  "Return an alist of alternate links in DOM.
+
+Each element is a list of the form (URL TYPE TITLE) where URL is
+the href attribute of the link expanded relative to BASE, TYPE is
+its type attribute, and TITLE is its title attribute.  If any of
+these attributes is absent, the corresponding element is nil."
+  (let ((alternates
+         (seq-filter
+          (lambda (attrs) (string= (alist-get 'rel attrs)
+                                   "alternate"))
+          (mapcar #'dom-attributes (dom-by-tag dom 'link)))))
+    (mapcar (lambda (alternate)
+              (list (url-expand-file-name (alist-get 'href alternate)
+                                          base)
+                    (alist-get 'type  alternate)
+                    (alist-get 'title alternate)))
+            alternates)))
+
+(defun eww-read-alternate-url ()
+  "Get the URL of an alternate link of this page.
+
+If there is just one alternate link, return its URL.  If there
+are multiple alternate links, prompt for one in the minibuffer
+with completion.  If there are none, return nil."
+  (when-let ((alternates (eww--alternate-urls
+                          (plist-get eww-data :dom)
+                          (plist-get eww-data :url))))
+    (let ((url-max-width
+           (seq-max (mapcar #'string-pixel-width
+                            (mapcar #'car alternates))))
+          (title-max-width
+           (seq-max (mapcar #'string-pixel-width
+                            (mapcar #'caddr alternates))))
+          (sep-width (string-pixel-width " ")))
+      (if (cdr alternates)
+          (let ((completion-extra-properties
+                 (list :annotation-function
+                       (lambda (feed)
+                         (let* ((attrs (alist-get feed
+                                                  alternates
+                                                  nil
+                                                  nil
+                                                  #'string=))
+                                (type (car attrs))
+                                (title (cadr attrs)))
+                           (concat
+                            (propertize " " 'display
+                                        `(space :align-to
+                                                (,(+ sep-width
+                                                     url-max-width))))
+                            title
+                            (when type
+                              (concat
+                               (propertize " " 'display
+                                           `(space :align-to
+                                                   (,(+ (* 2 sep-width)
+                                                        url-max-width
+                                                        title-max-width))))
+                               "[" type "]"))))))))
+            (completing-read "Alternate URL: " alternates nil t))
+        (caar alternates)))))
+
+(defun eww-copy-alternate-url ()
+  "Copy an alternate URL of the current page into the kill ring.
+
+Alternate links are references that an HTML page may include to
+point to its alternative representations, such as a translated
+version or an RSS feed."
+  (interactive nil eww-mode)
+  (if-let ((url (eww-read-alternate-url)))
+      (progn
+        (kill-new url)
+        (message "Copied %s to kill ring" url))
+    (user-error "No alternate links found on this page!")))
+
 ;;; eww.el ends here
-- 
2.41.0


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

* bug#64126: [PATCH] New command 'eww-copy-alternate-url'
  2023-06-21 17:20       ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-06-24 12:00         ` Eli Zaretskii
  0 siblings, 0 replies; 10+ messages in thread
From: Eli Zaretskii @ 2023-06-24 12:00 UTC (permalink / raw)
  To: Eshel Yaron; +Cc: 64126-done

> From: Eshel Yaron <me@eshelyaron.com>
> Cc: 64126@debbugs.gnu.org
> Date: Wed, 21 Jun 2023 20:20:27 +0300
> 
> >> Yes, websites very often use these alternate links to point to their
> >> RSS/Atom feeds.  Should I add a couple of words about that in the NEWS
> >> entry as well?
> >
> > Yes, a few more words of explanation would be good there.
> 
> Sure, I've added a few words about alternate links to the NEWS entry in
> the following (updated) patch:

Thanks, installed (with a couple of minor fixes) on the master branch,
and closing the bug.





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

end of thread, other threads:[~2023-06-24 12:00 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-17 11:07 bug#64126: [PATCH] New command 'eww-copy-alternate-url' Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-06-17 13:07 ` Eli Zaretskii
2023-06-17 14:08   ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-06-17 17:08     ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-06-21  6:01       ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-06-21 11:00         ` Eli Zaretskii
2023-06-21 12:02           ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-06-21 14:04     ` Eli Zaretskii
2023-06-21 17:20       ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-06-24 12:00         ` Eli Zaretskii

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