diff options
| author | Eshel Yaron | 2023-06-17 13:48:51 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2023-06-24 14:52:23 +0300 |
| commit | dfba4347c71d70b8357979ff0fb4bb070b0ed60c (patch) | |
| tree | 7e7dd66cbe9751ce766de5e0272570527adc13a4 | |
| parent | 8e8667246a4c06c8362515cbd6bead889babb748 (diff) | |
| download | emacs-dfba4347c71d70b8357979ff0fb4bb070b0ed60c.tar.gz emacs-dfba4347c71d70b8357979ff0fb4bb070b0ed60c.zip | |
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.
(Bug#64126)
| -rw-r--r-- | doc/misc/eww.texi | 15 | ||||
| -rw-r--r-- | etc/NEWS | 7 | ||||
| -rw-r--r-- | lisp/net/eww.el | 79 |
3 files changed, 101 insertions, 0 deletions
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 @@ web page hit @kbd{g} (@code{eww-reload}). | |||
| 115 | @kbd{w} calls @code{eww-copy-page-url}, which will copy the current | 115 | @kbd{w} calls @code{eww-copy-page-url}, which will copy the current |
| 116 | page's URL to the kill ring instead. | 116 | page's URL to the kill ring instead. |
| 117 | 117 | ||
| 118 | @findex eww-copy-alternate-url | ||
| 119 | @kindex A | ||
| 120 | The @kbd{A} command (@code{eww-copy-alternate-url}) copies the URL | ||
| 121 | of an alternate link of the current page into the kill ring. If the | ||
| 122 | page specifies multiple alternate links, this command prompts for one | ||
| 123 | of them in the minibuffer, with completion. Alternate links are | ||
| 124 | references that an @acronym{HTML} page may include to point to other | ||
| 125 | documents that act as its alternative representations. Notably, | ||
| 126 | @acronym{HTML} pages can use alternate links to point to their | ||
| 127 | translated versions and to @acronym{RSS} feeds. Alternate links | ||
| 128 | appear in the @samp{<head>} section of @acronym{HTML} pages as | ||
| 129 | @samp{<link>} elements with @samp{rel} attribute equal to | ||
| 130 | @samp{``alternate''}, they are part of the page's metadata and are not | ||
| 131 | visible in its rendered content. | ||
| 132 | |||
| 118 | @findex eww-open-in-new-buffer | 133 | @findex eww-open-in-new-buffer |
| 119 | @kindex M-RET | 134 | @kindex M-RET |
| 120 | The @kbd{M-@key{RET}} command (@code{eww-open-in-new-buffer}) opens the | 135 | The @kbd{M-@key{RET}} command (@code{eww-open-in-new-buffer}) opens the |
| @@ -266,6 +266,13 @@ The interactive minibuffer prompt when invoking 'eww' now provides | |||
| 266 | completions from 'eww-suggest-uris'. 'eww-suggest-uris' now includes | 266 | completions from 'eww-suggest-uris'. 'eww-suggest-uris' now includes |
| 267 | bookmark URIs. | 267 | bookmark URIs. |
| 268 | 268 | ||
| 269 | +++ | ||
| 270 | *** New command 'eww-copy-alternate-url'. | ||
| 271 | It copies an alternate link to the page currently visited in EWW into | ||
| 272 | the kill ring. Alternate links are optional metadata that HTML pages | ||
| 273 | use for linking to their alternative representations, such as | ||
| 274 | translated versions or associated RSS feeds. | ||
| 275 | |||
| 269 | ** go-ts-mode | 276 | ** go-ts-mode |
| 270 | 277 | ||
| 271 | +++ | 278 | +++ |
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 @@ the like." | |||
| 1086 | "&" #'eww-browse-with-external-browser | 1086 | "&" #'eww-browse-with-external-browser |
| 1087 | "d" #'eww-download | 1087 | "d" #'eww-download |
| 1088 | "w" #'eww-copy-page-url | 1088 | "w" #'eww-copy-page-url |
| 1089 | "A" #'eww-copy-alternate-url | ||
| 1089 | "C" #'url-cookie-list | 1090 | "C" #'url-cookie-list |
| 1090 | "v" #'eww-view-source | 1091 | "v" #'eww-view-source |
| 1091 | "R" #'eww-readable | 1092 | "R" #'eww-readable |
| @@ -2576,4 +2577,82 @@ Otherwise, the restored buffer will contain a prompt to do so by using | |||
| 2576 | 2577 | ||
| 2577 | (provide 'eww) | 2578 | (provide 'eww) |
| 2578 | 2579 | ||
| 2580 | ;;; Alternate links (RSS and Atom feeds, etc.) | ||
| 2581 | |||
| 2582 | (defun eww--alternate-urls (dom &optional base) | ||
| 2583 | "Return an alist of alternate links in DOM. | ||
| 2584 | |||
| 2585 | Each element is a list of the form (URL TYPE TITLE) where URL is | ||
| 2586 | the href attribute of the link expanded relative to BASE, TYPE is | ||
| 2587 | its type attribute, and TITLE is its title attribute. If any of | ||
| 2588 | these attributes is absent, the corresponding element is nil." | ||
| 2589 | (let ((alternates | ||
| 2590 | (seq-filter | ||
| 2591 | (lambda (attrs) (string= (alist-get 'rel attrs) | ||
| 2592 | "alternate")) | ||
| 2593 | (mapcar #'dom-attributes (dom-by-tag dom 'link))))) | ||
| 2594 | (mapcar (lambda (alternate) | ||
| 2595 | (list (url-expand-file-name (alist-get 'href alternate) | ||
| 2596 | base) | ||
| 2597 | (alist-get 'type alternate) | ||
| 2598 | (alist-get 'title alternate))) | ||
| 2599 | alternates))) | ||
| 2600 | |||
| 2601 | (defun eww-read-alternate-url () | ||
| 2602 | "Get the URL of an alternate link of this page. | ||
| 2603 | |||
| 2604 | If there is just one alternate link, return its URL. If there | ||
| 2605 | are multiple alternate links, prompt for one in the minibuffer | ||
| 2606 | with completion. If there are none, return nil." | ||
| 2607 | (when-let ((alternates (eww--alternate-urls | ||
| 2608 | (plist-get eww-data :dom) | ||
| 2609 | (plist-get eww-data :url)))) | ||
| 2610 | (let ((url-max-width | ||
| 2611 | (seq-max (mapcar #'string-pixel-width | ||
| 2612 | (mapcar #'car alternates)))) | ||
| 2613 | (title-max-width | ||
| 2614 | (seq-max (mapcar #'string-pixel-width | ||
| 2615 | (mapcar #'caddr alternates)))) | ||
| 2616 | (sep-width (string-pixel-width " "))) | ||
| 2617 | (if (cdr alternates) | ||
| 2618 | (let ((completion-extra-properties | ||
| 2619 | (list :annotation-function | ||
| 2620 | (lambda (feed) | ||
| 2621 | (let* ((attrs (alist-get feed | ||
| 2622 | alternates | ||
| 2623 | nil | ||
| 2624 | nil | ||
| 2625 | #'string=)) | ||
| 2626 | (type (car attrs)) | ||
| 2627 | (title (cadr attrs))) | ||
| 2628 | (concat | ||
| 2629 | (propertize " " 'display | ||
| 2630 | `(space :align-to | ||
| 2631 | (,(+ sep-width | ||
| 2632 | url-max-width)))) | ||
| 2633 | title | ||
| 2634 | (when type | ||
| 2635 | (concat | ||
| 2636 | (propertize " " 'display | ||
| 2637 | `(space :align-to | ||
| 2638 | (,(+ (* 2 sep-width) | ||
| 2639 | url-max-width | ||
| 2640 | title-max-width)))) | ||
| 2641 | "[" type "]")))))))) | ||
| 2642 | (completing-read "Alternate URL: " alternates nil t)) | ||
| 2643 | (caar alternates))))) | ||
| 2644 | |||
| 2645 | (defun eww-copy-alternate-url () | ||
| 2646 | "Copy an alternate URL of the current page into the kill ring. | ||
| 2647 | |||
| 2648 | Alternate links are references that an HTML page may include to | ||
| 2649 | point to its alternative representations, such as a translated | ||
| 2650 | version or an RSS feed." | ||
| 2651 | (interactive nil eww-mode) | ||
| 2652 | (if-let ((url (eww-read-alternate-url))) | ||
| 2653 | (progn | ||
| 2654 | (kill-new url) | ||
| 2655 | (message "Copied %s to kill ring" url)) | ||
| 2656 | (user-error "No alternate links found on this page!"))) | ||
| 2657 | |||
| 2579 | ;;; eww.el ends here | 2658 | ;;; eww.el ends here |