When Elfeed, an RSS-reading extension for Emacs, is set up and functional, it is easy to browse the items. The two main views are the list of items from all feeds (named “elfeed-search”) and a single item (named “elfeed-entry”). In both views, the y
key is bound to copy the link of the current item. But how to copy the headline?
Item titles are actually available in the Elfeed code, but not accessible out of the box. There is neither a ready function or keybind to grab the title of the current item. Moreover, both “elfeed-search” and “elfeed-entry” are different files of the Elfeed extension with their own functions and keymaps, i.e. basically distinct modes, so both need to be configured separately. For the following modifications to work, the extension needs to be first required in the config:
(require 'elfeed)
Functions and bindings in Elfeed entry (the item view)
In Elfeed entry or item view, the y
key copies the link of the item. The original code that does it looks as follows:
(defun elfeed-show-yank ()
"Copy the current entry link URL to the clipboard."
(interactive)
(let ((link (elfeed-entry-link elfeed-show-entry)))
(when link
(kill-new link)
(if (fboundp 'gui-set-selection)
(gui-set-selection 'PRIMARY link)
(with-no-warnings
(x-set-selection 'PRIMARY link)))
(message "Yanked: %s" link))))
Arriving at a code that copies the title instead is as easy as changing all occurrences of “link” to “title”. Note that obviously we must change the function’s name and documentation a bit too:
(defun elfeed-show-yank-title ()
"Copy the current entry title to the clipboard."
(interactive)
(let ((title (elfeed-entry-title elfeed-show-entry)))
(when title
(kill-new title)
(if (fboundp 'gui-set-selection)
(gui-set-selection 'PRIMARY title)
(with-no-warnings
(x-set-selection 'PRIMARY title)))
(message "Yanked: %s" title))))
And t
happens to be available in the keymap:
(with-eval-after-load "elfeed-show"
(define-key elfeed-show-mode-map "t" #'elfeed-show-yank-title))
Now the t
key will copy the headline of the current item.
How about copying the title and the link at one go? Isn’t it more sophisticated? It is, namely:
(defun elfeed-show-title-and-link ()
"Copy the current entry title and URL to the clipboard."
(interactive)
(let ((title-and-link (concat
(elfeed-entry-title elfeed-show-entry)
" " (elfeed-entry-link elfeed-show-entry)
)))
(when title-and-link
(kill-new title-and-link)
(if (fboundp 'gui-set-selection)
(gui-set-selection 'PRIMARY title-and-link)
(with-no-warnings
(x-set-selection 'PRIMARY title-and-link)))
(message "Yanked: %s" title-and-link))))
(with-eval-after-load "elfeed-show"
(define-key elfeed-show-mode-map "T" #'elfeed-show-title-and-link))
Functions and bindings in Elfeed search (the list view)
In Elfeed list view, the y
key is bound to a more complicated activity. In the list view it is easy to select multiple items and then y
copies the links of all selected items! The corresponding original code looks as follows:
(defun elfeed-search-yank ()
"Copy the selected feed items to clipboard and kill-ring."
(interactive)
(let* ((entries (elfeed-search-selected))
(links (mapcar #'elfeed-entry-link entries))
(links-str (mapconcat #'identity links " ")))
(when entries
(elfeed-untag entries 'unread)
(kill-new links-str)
(if (fboundp 'gui-set-selection)
(gui-set-selection elfeed-search-clipboard-type links-str)
(with-no-warnings
(x-set-selection elfeed-search-clipboard-type links-str)))
(message "Copied: %s" links-str)
(mapc #'elfeed-search-update-entry entries)
(unless (or elfeed-search-remain-on-entry (use-region-p))
(forward-line)))))
To make it grab headlines instead of links is still as easy as changing all occurrences of “link” to “title” with the following result:
(defun elfeed-search-yank-title ()
"Copy the selected feed titles to clipboard and kill-ring."
(interactive)
(let* ((entries (elfeed-search-selected))
(titles (mapcar #'elfeed-entry-title entries))
(titles-str (mapconcat #'identity titles " ")))
(when entries
(elfeed-untag entries 'unread)
(kill-new titles-str)
(if (fboundp 'gui-set-selection)
(gui-set-selection elfeed-search-clipboard-type titles-str)
(with-no-warnings
(x-set-selection elfeed-search-clipboard-type titles-str)))
(message "Copied: %s" titles-str)
(mapc #'elfeed-search-update-entry entries)
(unless (or elfeed-search-remain-on-entry (use-region-p))
(forward-line)))))
(with-eval-after-load "elfeed-search"
(define-key elfeed-search-mode-map "t" #'elfeed-search-yank-title))
Creating a function that copies both titles and links at one go is again somewhat more involved, but doable:
(defun elfeed-search-title-and-link ()
"Copy the selected feed items to clipboard and kill-ring."
(interactive)
(let* ((entries (elfeed-search-selected))
(titles-and-links
(let (ringit)
(dolist (entry entries)
(setq ringit
(concat ringit
(elfeed-entry-title entry)
" "
(elfeed-entry-link entry) "\n")))
(string-chop-newline ringit))))
(when entries
(elfeed-untag entries 'unread)
(kill-new titles-and-links)
(if (fboundp 'gui-set-selection)
(gui-set-selection elfeed-search-clipboard-type titles-and-links)
(with-no-warnings
(x-set-selection elfeed-search-clipboard-type titles-and-links)))
(message "Copied: %s" titles-and-links)
(mapc #'elfeed-search-update-entry entries)
(unless (or elfeed-search-remain-on-entry (use-region-p))
(forward-line)))))
(with-eval-after-load "elfeed-search"
(define-key elfeed-search-mode-map "T" #'elfeed-search-title-and-link))
Bonus: Copy link at point in Eww
Emacs’ inbuilt webbrowser, Eww, uses the keybind w
to copy the webpage URL, but there is neither keybind or function to copy the link at point. When hopping from link to link on a webpage in Eww, the URLs are sent to the *Messages* buffer and one idea is to grab the URLs from there.
Elfeed’s elfeed-kill-link-url-at-point
fixes this, as it works in Eww without modification. In Elfeed, the function is bound to the c
key, so I am using the same key also in Eww.
(with-eval-after-load "eww"
(define-key eww-mode-map "c" #'elfeed-kill-link-url-at-point))