Emacs/Feeds
Elfeed is an RSS and Atom client for Emacs. Combined with org-feeds
it can be used to setup feed client.
Requirements
- Git: distributed version control system
- GNU/GUIX: a functional package management system
- LitDoc: literate programming utility
Introduction
Elfeed package is an Emacs RSS and Atom client.
In combination with Org-Feeds it can be used to setup
RSS client per a git project or system-wide.
Customization
File Paths
Template project feed file
(defconst feeds:template-feed-file
(expand-file-name
"share/templates/feeds.org"
(substitute-in-file-name "${LITDOC_CACHEDIR}/feeds"))
"Template project feed file")Template project dashboard file path
(defconst feeds:template-dashboard-file
(expand-file-name
"share/templates/dashboard.org"
(substitute-in-file-name "${LITDOC_CACHEDIR}/feeds"))
"Template project dashboard file path")Default feed file
(defconst feeds:default-file
(expand-file-name
"news.feed"
(substitute-in-file-name "${HOME}/Documents/planner"))
"system wide default feed file")Templates
Template Feeds dashboard:
*Basics
[U] Update Elfeed
[s] Search
[E] Edit
[g] Refresh counts
[q] Kill dashboard
*Bookmarks
[u] Unread ([[elfeed:+unread][ 688]]/[[elfeed:][ 7882]])
[e] Emacs ([[elfeed:+unread +emacs][ 1]]/[[elfeed:+emacs][ 3634]])
[b] Blogs ([[elfeed:+unread +blog][ 506]]/[[elfeed:+blog][------]])
[m] Monitoring ([[elfeed:+unread +monitoring][ 0]]/[[elfeed:+monitoring][------]])
[n] News ([[elfeed:+unread +news][ 70]]/[[elfeed:+news][------]])
[v] Video ([[elfeed:+unread +video][ 10]]/[[elfeed:+video][------]])
:PROPERTIES:
:VISIBILITY: hideall
:END:
Press "E" to edit and M-x elfeed-dashboard-mode to go back
#+STARTUP: showall showstars indent
#+KEYMAP: u | elfeed-dashboard-query "+unread"
#+KEYMAP: e | elfeed-dashboard-query "+unread +emacs"
#+KEYMAP: b | elfeed-dashboard-query "+unread +blogs"
#+KEYMAP: m | elfeed-dashboard-query "+unread +monitoring"
#+KEYMAP: v | elfeed-dashboard-query "+unread +video"
#+KEYMAP: n | elfeed-dashboard-query "+unread +news"
#+KEYMAP: s | elfeed
#+KEYMAP: g | elfeed-dashboard-update-links
#+KEYMAP: U | elfeed-dashboard-update
#+KEYMAP: E | elfeed-dashboard-edit
#+KEYMAP: q | kill-current-bufferTemplate Feeds Page
* Blogs :elfeed:
** Title: \(linux\|linus\|ubuntu\|kde\|gnome\) :linux:
** exampl.com/index.rss :mustread:Key Bindings
Elfeed's elfeed-show-mode-map keybindings are useful for controlling the elfeed buffer once it is loaded.
(kb::def :states 'normal
"o" '(:ignore t :which-key "Org")
"oe" '(:ignore t :which-key "News Feed(Elfeed)")
"oee" '(feeds::open :which-key "Open Elfeed")
"oed" '(feeds::close :which-key "Exit Elfeed")
"oeE" '(feeds::edit-feed-file :which-key "Edit Feed File"))Functions
Where to Find feed files?
Feed files are configured either per project or globally. A project feed file is stored
under the current project's org directory, [project-root]/.config/feeds.org. The global
feed file location can be configured using feeds::default-file.
(cl-defun feeds::find-project-feed-file ( )
"Retruns the current project's feed file.
If current project is not available it returns nil.
Otherwise, it returns feed file path wether it exists or not."
(require 'pm)
(require 'log)
(let ((in-project-dir? (pm::is-available))
(project-dir nil)
(feed-file nil))
;; is inside a git project?
(unless in-project-dir?
(cl-return-from feeds::find-project-feed-file))
;; is project directory path valid?
(setq project-dir (pm::root-dir))
(unless (file-directory-p project-dir)
(cl-return-from feeds::find-project-feed-file))
;; return feed file path
(setq feed-file (expand-file-name "news.feed" project-dir))
(unless (file-exists-p feed-file)
(setq feed-file feeds:default-file))
feed-file))Edit feed files
Problem it's easy to forget the location and format of feed files.
Commands in this section can be used to quickly edit existing feed file or create a new one from a template feed file.
(defun feeds::edit-feed-file ( )
"Edit the default `elfeed-org' feed file."
(interactive)
(require 'fs)
(require 'org)
(let ((feed-file (feeds::find-project-feed-file))
(feed-buffer nil))
(cond
(;; if not in a project, then there's nothing to do
(null feed-file)
(log::info "edit feed file got canceled")
(log::sub-info "unable to locate current project")
(log::sub-info "unable to locate project feed file"))
(;; feed file exists?
(file-exists-p feed-file)
(setq feed-buffer (find-file-noselect feed-file))
(with-current-buffer feed-buffer
(org-mode))
(switch-to-buffer feed-buffer))
(t ;; file is configured, but does not exist yet.
;; In this case, just open a template feed file
;; for the user to edit
(feeds:fs/dir-ensure (file-name-directory feed-file))
(setq feed-buffer (find-file-noselect feed-file))
(with-current-buffer feed-buffer
(org-mode)
(insert-file-contents feeds:template-feed-file))
(switch-to-buffer feed-buffer)))))Open Feeds
Functions to support syncing feeds by forcing
elfeed reads index from disk before launching
(defun feeds::open ()
"Open feeds UI"
(interactive)
(feeds::open-internal))
(cl-defun feeds::open-internal ( )
"Start elfeed after syncing it with database(if necessary)"
(require 'elfeed)
(require 'elfeed-db)
(require 'elfeed-search)
(require 'elfeed-org)
(require 'f)
(require 'log)
(require 'fs)
(let ((project-root nil)
(feed-file (feeds::find-project-feed-file)))
;; revert to system default feed file
(when (null feed-file)
(setq feed-file feeds:default-file))
(log::info "checking for feed file ..." )
(unless (file-exists-p feed-file)
(log::info "feed file not found: <%s>" feed-file)
(log::info "Please, use `feeds::edit-feed-file' to edit feed files first")
(cl-return-from feeds::open-internal))
(log::sub-info "found feed file ... [%s]" feed-file)
;; project specific dashboard
(let ((rmh-elfeed-org-files `( ,feed-file)))
;; prepare el-feed database
(log::info "preparing elfeed database index ...")
(log::sub-info "database path: %s" elfeed-db-directory)
(fs::dir-ensure elfeed-db-directory)
(elfeed-db-load)
(elfeed)
(elfeed-search-update--force))))Saving Feeds
(defun feeds::close( )
"Save the elfeed db to disk before deleting buffer"
(interactive)
(require 'elfeed-db)
(elfeed-db-save)
(quit-window))Mark All Feeds in Inbox as Read
(defun feeds::inbox-mark-all-as-read ( )
"Marks all feeds as read"
(interactive)
(require 'elfeed-search)
(mark-whole-buffer)
(elfeed-search-untag-all-unread))Packages
Package: elfeed-feed
This main elfeed package can be installed directly from guix default channel.
(defface elfeed-feed-face
'((default :weight bold :height 1.2)
(((class color) (background dark)) :foreground "white")
(((class color) (background light)) :foreground "black"))
"Face for news feeds."
:group 'elfeed-face)
(use-package elfeed
:guix (:name emacs-elfeed))
Package: elfeed-org
Elfeed-org enables managing Elfeed subscriptions using
using org-mode file. The package is available in
GNU/Guixdefault default channel. The channel method is the
prefered method of installation.
(use-package elfeed-org
:guix (:name emacs-elfeed-org)
:config
(require 'fs)
(setq elfeed-db-directory (fs::dir-ensure "${HOME}/.config/litdoc/elfeed/elfeed-db"))
(elfeed-org))
Package: elfeed-show
(use-package elfeed-show
:init
(defun elfeed-show::setup-font ( )
(set-face-attribute
'variable-pitch
(selected-frame)
:font
(font-spec :family "Vollkorn" :size 20)))
;; :hook
;; (elfeed-show-mode . elfeed-show::setup-font)
:config
(setq fill-column 90))