elfeed-score icon indicating copy to clipboard operation
elfeed-score copied to clipboard

Gnus-style scoring for elfeed

#+TITLE: elfeed-score #+DESCRIPTION: Gnus-style scoring for Elfeed #+AUTHOR: Michael Herstine #+EMAIL: [email protected] #+DATE: <2023-07-26 Wed 07:28> #+AUTODATE: t #+OPTIONS: toc:nil org-md-headline-style:setext *:t ^:nil #+STARTUP: overview

[[https://melpa.org/#/elfeed-score][file:https://melpa.org/packages/elfeed-score-badge.svg]] [[https://stable.melpa.org/#/elfeed-score][file:https://stable.melpa.org/packages/elfeed-score-badge.svg]] [[https://github.com/sp1ff/elfeed-score/workflows/melpazoid/badge.svg][file:https://github.com/sp1ff/elfeed-score/workflows/melpazoid/badge.svg]]

  • Introduction

[[https://github.com/sp1ff/elfeed-score][elfeed-score]] brings Gnus-style [[https://www.gnu.org/software/emacs/manual/html_node/gnus/Scoring.html#Scoring][scoring]] to [[https://github.com/skeeto/elfeed][Elfeed]].

[[https://github.com/skeeto/elfeed][Elfeed]] is an extensible web feed reader for Emacs. By default, it will display entries in reverse chronological order. This package defines a bit of metadata for each of your feed entries: a "score". A score is an integer (negative or positive), and higher scores denote entries of greater interest to you. This package also (optionally) installs a new sort function, so that Elfeed will display entries with higher scores before entries with lower scores (entries with the same scores will still be sorted in reverse chronological order). It also provides an entry display function for the elfeed search buffer that displays each entry's score, should you choose to install it.

While you can manually assign a score to an entry, you will likely find it more convenient to create rules for scoring that will be automatically applied to each new entry every time you update Elfeed. You can score against title, feed, content, authors & entry link by defining strings that will be matched against those attributes by substring, regexp or whole-word match. You can score against the feed (on the basis of title, URL, or feed author). You can also score against the presence or absence of tags. If none of these do what you want, you can author your own functions & score based on them. Rules can be scoped by Elfeed entry tags or by their feed, so that a rule will only be applied to a subset of your entries. Each rule defines an integral value, and the rules are applied in order of definition. The new entry's score begins at =elfeed-score-scoring-default-score=, and is adjusted by the value defined by each matching scoring rule.

For instance, here's a subset of my scoring file at the moment:

#+BEGIN_SRC elisp ;;; Elfeed score file -- lisp -- (("title" (:text "OPEN THREAD" :value -1000 :type S) (:text "raymond c\(hen\)?" :value 250 :type r :tags (t . @dev)) ("content" (:text "type erasure" :value 500 :type s)) ("title-or-content" (:text "california" :title-value 150 :content-value 100 :type s) (:text "china" :title-value 150 :content-value 100 :type w)) ("feed" (:text "Essays in Idleness" :value 250 :type S :attr t) (:text "Irreal" :value 250 :type S :attr t) (:text "Julia Evans" :value 100 :type s :attr t) (:text "National Weather Service" :value 400 :type S :attr t) (:text "emacs-news – sacha chua" :value 350 :type S :attr t :comment "Essential!")) ("authors" (:text "Jim Geraghty" :value 500 :type s)) ("tag" (:tags (t . reddit-question) :value 750 :comment "Add 750 points to any entry with a tag of reddit-question")) (mark -2500)) #+END_SRC

Like Gnus scoring, this may look like Lisp code, but it is not directly eval'd. It will be read by the Lisp reader, so it must at least be a valid Lisp s-expression.

This README introduces the package and describes the various ways to install it. Detailed user documentation (including full details on the score file format) is distributed in Texinfo format with the package and is also available in HTML format [[https://www.unwoundstack.com/doc/elfeed-score/curr][here]]. There's a (nascent) developer's wiki on Github [[https://github.com/sp1ff/elfeed-score/wiki][here]].

  • Prerequisites

This package requires Emacs 26.1, and is developed against [[https://github.com/skeeto/elfeed][Elfeed]] 3.3.0 & 3.4.1. Elfeed itself requires cURL.

  • Installing

** MELPA

The easiest way to install elfeed-score is [[https://github.com/melpa/melpa][MELPA]]; assuming you've got MELPA in your =package-archives=, just say:

#+BEGIN_SRC elisp (use-package elfeed-score :ensure t :config (progn (elfeed-score-enable) (define-key elfeed-search-mode-map "=" elfeed-score-map))) #+END_SRC

** Download the Package

If you would prefer to install the package manually, you can also download the Emacs package file on the GitHub releases [[https://github.com/sp1ff/elfeed-score/releases][page]] or from my personal [[https://www.unwoundstack/distros.html][page]]. Then say:

#+BEGIN_SRC elisp (package-install-file "elfeed-score-1.2.7.tar") #+END_SRC

** Autotools Source Distributions

You can also download Autotools source tarballs (again available either on the GitHub releases [[https://github.com/sp1ff/elfeed-score/releases][page]] or from my personal [[https://www.unwoundstack/distros.html][site]]). The =make= step passes the =--batch= flag when compiling, so if the [[https://github.com/skeeto/elfeed][elfeed]] files are not installed somewhere in Emacs' default load path (if, say, they're in =~/emacs.d/elpa=), you'll need to set =EMACSLOADPATH= to pick it up; for instance:

#+BEGIN_SRC bash cd /tmp curl -L --output elfeed-score-1.2.7.tar.gz https://github.com/sp1ff/elfeed-score/releases/download/1.2.7/elfeed-score-1.2.7.tar.gz tar xvf elfeed-score-1.2.7.tar.gz && cd elfeed-score-1.2.7 export EMACSLOADPATH=$HOME/.emacs.d/elpa/elfeed-20200209.1942:$EMACSLOADPATH ./configure make sudo make install #+END_SRC

Unless you already use =EMACSLOADPATH= as part of your usual invocation of Emacs, this isn't likely to work as written-- you'll need to work out exactly how to tell Emacs to pick-up the rest of its LISP files. On an old Ubuntu 18.04 system of mine, for instance, =EMACSLOADPATH=$HOME/.emacs.d/elpa/elfeed-20200209.1942:/usr/share/emacs/25.2/lisp= worked. *** Running the Unit Tests

The unit tests require some macros defined by the [[https://github.com/skeeto/elfeed][Elfeed]] test suite, which is not distributed with the MELPA package. Therefore, you'll need to clone the Elfeed git repo & develop against that:

#+BEGIN_SRC bash cd /tmp git clone https://github.com/skeeto/elfeed.git curl -L --output=elfeed-score-1.2.7.tar.gz https://github.com/sp1ff/elfeed-score/releases/download/1.2.7/elfeed-score-1.2.7.tar.gz tar xvf elfeed-score-1.2.7.tar.gz && cd elfeed-score-1.2.7 export EMACSLOADPATH=/tmp/elfeed-score-1.2.7:/tmp/elfeed:/tmp/elfeed/tests:$EMACSLOADPATH ./configure make make check sudo make install #+END_SRC

Again, unless you already use =EMACSLOADPATH=, you'll need to set =EMACSLOADPATH= appropriately to your system, something like =EMACSLOADPATH=/tmp/elfeed-score-1.2.7:/tmp/elfeed:/tmp/elfeed/tests:/usr/share/emacs/25.2/lisp=. ** Building From Source

Finally, you can of course just clone this repo & build there. I've started a [[https://github.com/sp1ff/elfeed-score/wiki][wiki]], whose intended audience are people looking to hack on elfeed-score, that includes build instructions.

  • Upgrading Your Score File

The format of the score file is updated fairly regularly to accomodate new features, new rule types, and so forth. elfeed-score maintains backward compatibility in that score files in older formats are still recognized. The most recent format version will always be used when the score file is written to disk, however. Note than an older elfeed-score will reject a more recent score file (since it will not know how to parse it).

When elfeed-score loads a score file that uses an archaic format (i.e. a format version less than =elfeed-score-serde-current-format=) it will:

  • announce the fact that your score file will be updated
  • make a backup of your current score file in a file by the same name with a suffix of =~%d~= appended, where "%d" is the current format version
  • on successful parse, immediately re-write the score file in the most recent version

This should all be transparent to the user.

  • Status and Roadmap

I've been using [[https://github.com/sp1ff/elfeed-score][elfeed-score]] day in & day out for my RSS reading for over two years now. I wrote a post on how [[https://github.com/sp1ff/elfeed-score][elfeed-score]] works, along with the process of submitting code to MELPA, [[https://www.unwoundstack.com/blog/scoring-elfeed-entries.html][here]]. [[https://github.com/C-J-Cundy][Chris]] wrote a post on how he uses it to [[https://cundy.me/post/elfeed/][manage ArXiv RSS Feeds]]. [[https://kitchingroup.cheme.cmu.edu/][John Kitchin]] talks about [[https://github.com/skeeto/elfeed][Elfeed]] & [[https://github.com/sp1ff/elfeed-score][elfeed-score]] [[https://www.youtube.com/watch?v=rvWbUGx9U5E][here]].

The version numbers (0.X) over most of that time were chosen to suggest preliminary releases, but I'm now calling this 1.0. The 0.9 releases were hygenic: cleaning-up the test suite, improving validation on deserializing the score file, and removing obsolete functions & variables. Beginning with 1.0, I'll also comply with semver (e.g. breaking changes will be a major release, new features a minor, and bug fixes a patch).

Going forward, I'd like to use elfeed-score to explore some ideas I have about learning the user's habits automatically based on their actions in Elfeed (but without making them feel they're being stalked).

Bugs, comments, problems, PRs, feature requests &c welcome at [[mailto:[email protected]][[email protected]]] and in the [[https://github.com/sp1ff/elfeed-score/issues][issues]].