Article posted on: 2021-11-01 19:13
Last edited on: 2021-11-01 19:13
Written by: Sylvain Gauthier
Recently (like a few months ago), I had the unpleasant surprise to see that
newsboat
, my okay-ish terminal based feed reader, had been rewritten in Rust.
Of course, because of the abomination that is cargo
, this also meant that the
build was broken on Gentoo, so I decided to switch to the excellent
sfeed, a minimal,
modular RSS/atom parser.
After a bit of experimenting, I settled with a pretty good, minimal system that I think is worth presenting here, since it uses our homemade menu selector choice.
sfeed
is made of different little C programs that are meant to work together,
to separate fetching, parsing and delivery.
Fetching feeds and parsing them into the TAB-separated format is done with
sfeed_update
, which will source ~/.sfeed/sfeedrc
to get the feeds,
man sfeed_update
for more details. It will create one TAB-separated feed file
per feed, located in ~/.sfeed/feeds
.
You can then use the different delivery / parsing programs included in sfeed
to parse those feed files and do what you want with the result.
In my system, I use sfeed_plain
, which, as the name implies, output the feeds'
timestamp, name, title and URL, in a nice fancy column format. It crops the
articles' titles to 70 characters. Here is what a typical output looks like:
$ sfeed_plain ~/.sfeed/feeds/codemadness
2021-10-23 11:00 codemadness Setup an OpenBSD RISCV-64 VM in QEMU https://www.codemadness.org/openbsd-riscv64-vm.html
2021-10-23 11:00 codemadness Setup an OpenBSD RISCV64 VM in QEMU https://www.codemadness.org/openbsd-riscv64-vm.html
2020-06-25 10:00 codemadness Sfeed_curses: a curses UI front-end for sfeed https://www.codemadness.org/sfeed_curses-ui.html
2019-11-10 11:00 codemadness hurl: HTTP, HTTPS and Gopher file grabber https://www.codemadness.org/hurl.html
2019-10-13 11:00 codemadness json2tsv: a JSON to TSV converter https://www.codemadness.org/json2tsv.html
2019-04-24 10:00 codemadness OpenBSD: setup a local auto-installation server https://www.codemadness.org/openbsd-autoinstall.html
2019-02-10 11:00 codemadness Idiotbox: Youtube interface https://www.codemadness.org/idiotbox.html
2018-08-17 10:00 codemadness Gopher HTTP proxy https://www.codemadness.org/gopher-proxy.html
2018-03-10 11:00 codemadness Setup your own file paste service https://www.codemadness.org/paste-service.html
2018-02-25 11:00 codemadness Setup your own git hosting service https://www.codemadness.org/setup-git-hosting.html
2017-12-11 11:00 codemadness Setup an OpenBSD SPARC64 VM in QEMU https://www.codemadness.org/openbsd-sparc64-vm.html
2017-09-24 10:00 codemadness jsdatatable: a small datatable Javascript https://www.codemadness.org/datatable.html
2017-09-24 10:00 codemadness Tscrape: a Twitter scraper https://www.codemadness.org/tscrape.html
2017-08-04 10:00 codemadness Stagit-gopher: a static git page generator for gopher https://www.codemadness.org/stagit-gopher.html
2017-06-10 10:00 codemadness Saait: a boring HTML page generator https://www.codemadness.org/saait.html
2017-05-10 10:00 codemadness Stagit: a static git page generator https://www.codemadness.org/stagit.html
2015-07-05 10:00 codemadness OpenBSD httpd, slowcgi and cgit https://www.codemadness.org/openbsd-httpd-and-cgit.html
2014-11-23 11:00 codemadness twitch: application to watch Twitch streams https://www.codemadness.org/twitch-interface.html
2014-03-02 11:00 codemadness Userscript: focus input field https://www.codemadness.org/userscript-focus-input-field.html
2013-02-21 11:00 codemadness Userscript: Youtube circumvent age verification https://www.codemadness.org/userscript-youtube-circumvent-age-verification.html
2012-10-21 11:00 codemadness Userscript: block stupid fonts https://www.codemadness.org/userscript-block-stupid-fonts.html
2011-04-01 11:00 codemadness Sfeed: simple RSS and Atom parser https://www.codemadness.org/sfeed-simple-feed-parser.html
2011-01-07 11:00 codemadness Vim theme: relaxed https://www.codemadness.org/vim-theme-relaxed.html
2010-10-31 11:00 codemadness GTK2 theme: gtk-murrine-rape https://www.codemadness.org/gtk2-theme-gtk-murrine-rape.html
2010-10-31 11:00 codemadness Seturgent: set urgency hints for X applications https://www.codemadness.org/seturgent-set-urgency-hints-for-x-applications.html
2010-08-12 10:00 codemadness DWM-hiltjo: my windowmanager configuration https://www.codemadness.org/dwm-hiltjo-my-windowmanager-configuration.html
2010-04-21 10:00 codemadness Query unused CSS rules on current document state https://www.codemadness.org/query-unused-css-rules-on-current-document-state.html
2009-07-05 10:00 codemadness Driconf: enabling S3 texture compression on Linux https://www.codemadness.org/driconf-enabling-s3-texture-compression-on-linux.html
2009-04-13 10:00 codemadness Getting the USB-powerline bridge to work on Linux https://www.codemadness.org/getting-the-usb-powerline-bridge-to-work-on-linux.html
2009-04-12 10:00 codemadness Gothic 1 game guide https://www.codemadness.org/gothic-1-guide.html
I think the “intended” use, at least from glancing over the examples, is to then
feed that to a selector like dmenu
. My system is not much different, except I
use choice
for this purpose. It has the advantage of being purely
terminal-based, very (VERY) fast at filtering/searching entries and I am
familiar enough with the code to add features myself.
First, I reformat things a little bit to make it work optimally on choice
.
choice
hides the first space-delimited field of each line (the “key”) to show
only values, but once a value is selected, it outputs the “key”. In that use
case, the key is of course the article URL, and the value is the timestamp and
description. To do the trick:
sfeed_plain $feed | sed 's/\(.*\) \([^ ]*\)$/\2 \1/g'
Which outputs:
https://www.codemadness.org/openbsd-riscv64-vm.html 2021-10-23 11:00 codemadness Setup an OpenBSD RISCV-64 VM in QEMU
https://www.codemadness.org/openbsd-riscv64-vm.html 2021-10-23 11:00 codemadness Setup an OpenBSD RISCV64 VM in QEMU
https://www.codemadness.org/sfeed_curses-ui.html 2020-06-25 10:00 codemadness Sfeed_curses: a curses UI front-end for sfeed
https://www.codemadness.org/hurl.html 2019-11-10 11:00 codemadness hurl: HTTP, HTTPS and Gopher file grabber
https://www.codemadness.org/json2tsv.html 2019-10-13 11:00 codemadness json2tsv: a JSON to TSV converter
https://www.codemadness.org/openbsd-autoinstall.html 2019-04-24 10:00 codemadness OpenBSD: setup a local auto-installation server
https://www.codemadness.org/idiotbox.html 2019-02-10 11:00 codemadness Idiotbox: Youtube interface
https://www.codemadness.org/gopher-proxy.html 2018-08-17 10:00 codemadness Gopher HTTP proxy
https://www.codemadness.org/paste-service.html 2018-03-10 11:00 codemadness Setup your own file paste service
https://www.codemadness.org/setup-git-hosting.html 2018-02-25 11:00 codemadness Setup your own git hosting service
https://www.codemadness.org/openbsd-sparc64-vm.html 2017-12-11 11:00 codemadness Setup an OpenBSD SPARC64 VM in QEMU
https://www.codemadness.org/datatable.html 2017-09-24 10:00 codemadness jsdatatable: a small datatable Javascript
https://www.codemadness.org/tscrape.html 2017-09-24 10:00 codemadness Tscrape: a Twitter scraper
https://www.codemadness.org/stagit-gopher.html 2017-08-04 10:00 codemadness Stagit-gopher: a static git page generator for gopher
https://www.codemadness.org/saait.html 2017-06-10 10:00 codemadness Saait: a boring HTML page generator
https://www.codemadness.org/stagit.html 2017-05-10 10:00 codemadness Stagit: a static git page generator
https://www.codemadness.org/openbsd-httpd-and-cgit.html 2015-07-05 10:00 codemadness OpenBSD httpd, slowcgi and cgit
https://www.codemadness.org/twitch-interface.html 2014-11-23 11:00 codemadness twitch: application to watch Twitch streams
https://www.codemadness.org/userscript-focus-input-field.html 2014-03-02 11:00 codemadness Userscript: focus input field
https://www.codemadness.org/userscript-youtube-circumvent-age-verification.html 2013-02-21 11:00 codemadness Userscript: Youtube circumvent age verification
https://www.codemadness.org/userscript-block-stupid-fonts.html 2012-10-21 11:00 codemadness Userscript: block stupid fonts
https://www.codemadness.org/sfeed-simple-feed-parser.html 2011-04-01 11:00 codemadness Sfeed: simple RSS and Atom parser
https://www.codemadness.org/vim-theme-relaxed.html 2011-01-07 11:00 codemadness Vim theme: relaxed
https://www.codemadness.org/gtk2-theme-gtk-murrine-rape.html 2010-10-31 11:00 codemadness GTK2 theme: gtk-murrine-rape
https://www.codemadness.org/seturgent-set-urgency-hints-for-x-applications.html 2010-10-31 11:00 codemadness Seturgent: set urgency hints for X applications
https://www.codemadness.org/dwm-hiltjo-my-windowmanager-configuration.html 2010-08-12 10:00 codemadness DWM-hiltjo: my windowmanager configuration
https://www.codemadness.org/query-unused-css-rules-on-current-document-state.html 2010-04-21 10:00 codemadness Query unused CSS rules on current document state
https://www.codemadness.org/driconf-enabling-s3-texture-compression-on-linux.html 2009-07-05 10:00 codemadness Driconf: enabling S3 texture compression on Linux
https://www.codemadness.org/getting-the-usb-powerline-bridge-to-work-on-linux.html 2009-04-13 10:00 codemadness Getting the USB-powerline bridge to work on Linux
https://www.codemadness.org/gothic-1-guide.html 2009-04-12 10:00 codemadness Gothic 1 game guide
Looks ugly, but then, when fed into choice
, things become much more
aesthetic.
That’s the core idea. A bit of bash sweetener on top of it to make it more
usable, and here is the final script, which I named sneed
for the chuckle:
#!/bin/bash
BROWSER=elinks
feed="$(find "$HOME/.sfeed/feeds/$1" -type f)"
test -n "$feed" || exit 1
while true ; do
url="$(sfeed_plain $feed | sed 's/\(.*\) \([^ ]*\)$/\2 \1/g' | choice)"
test -n "$url" || exit 0
$BROWSER "$url"
done
I also patched sfeed_plain
to not crop articles' description at 70 character.
This “feature” seems very arbitrary to me and doesn’t make much sense. It should
be left to the reader to crop things if needed.
diff --git a/sfeed_plain.c b/sfeed_plain.c
index 1b11a71..773bf66 100644
--- a/sfeed_plain.c
+++ b/sfeed_plain.c
@@ -43,7 +43,7 @@ printfeed(FILE *fp, const char *feedname)
printutf8pad(stdout, feedname, 15, ' ');
fputs(" ", stdout);
}
- printutf8pad(stdout, fields[FieldTitle], 70, ' ');
+ printf("%s", fields[FieldTitle]);
printf(" %s\n", fields[FieldLink]);
}
}
Here is the final result in action:
Typing sneed <feed_name>
will restrict the display to only that particular
feed. Typing sneed
alone will open/concatenate all feeds, sorted first by name
then by date. choice
allows for lightning-fast search through all feeds.
Since the date is part of the searchable value, you can easily filter by date,
get only entries for the month, etc. The selected entry is opened using
$BROWSER
.
There is no notion of “opened” feed. sfeed_plain
displays a N
flag for
entries less than one day old, that’s it. While it seems like a limitation, it’s
actually not that big of a deal. I have been using this for the past two months
without caring too much for it. It still suits my needs better than any other
bloated solutions out there.