Google Reader alternative for Emacs Ninjas

Posted on by Idorobots

With Google Reader being discontinued and everyone looking for alternatives I've decided to look for a little less "standard" solution, and hey, it turns out Emacs can be a pretty powerful RSS reader.

Newsticker.el

News Ticker is a built-in Emacs feed reader that doesn't get much attention for some reason. It is feature-rich, handles both RSS 2.0 and Atom feeds and has quite a bunch of tweakable options. Here's a simple setup to start with:

(require 'newsticker)

; W3M HTML renderer isn't essential, but it's pretty useful.
(require 'w3m)
(setq newsticker-html-renderer 'w3m-region)

; We want our feeds pulled every 10 minutes.
(setq newsticker-retrieval-interval 600)

; Setup the feeds. We'll have a look at these in just a second.
(setq newsticker-url-list-defaults nil)
(setq newsticker-url-list '("..."))

; Optionally bind a shortcut for your new RSS reader.
(global-set-key (kbd "C-c r") 'newsticker-treeview)

; Don't forget to start it!
(newsticker-start)

Migration

First of all, you have to export your Google Reader data; you can do this here by following these instructions. Download and unzip it into a safe location.Now, all you will need to migrate from Google Reader to News Ticker is this little piece of code:

(require 'xml)

(defun assoc-or-error (what where &optional err-string)
  (or (assoc what where)
      (error (or err-string
                 "Suddenly errors! Thousands of them!"))))

(defun google-reader-to-newsticker (filename)
  "Parses your google-reader feed subscription XML
 and returns newsticker compatible feed alist."
  (with-temp-buffer
    (insert-file-contents filename)
    (let* ((opml (assoc-or-error
                  'opml
                  (xml-parse-region (point-min)
                                    (point-max))
                  "Not a valid feed XML!"))
           (body (assoc-or-error
                  'body
                  opml
                  "Not a valid feed XML!"))
           (outlines (delq nil
                           (map 'list
                                (lambda (element)
                                  (and (consp element)
                                       (equal (car element)
                                              'outline)
                                       element))
                                body)))
           (alist
            (map 'list
                 (lambda (outline)
                   (let ((title (assoc-or-error
                                 'title
                                 outline
                                 (concat "No title in an outline "
                                         "- malformed feed XML?"))
                         (feed (assoc-or-error
                                'xmlUrl
                                outline
                                (concat "No feed link in an outline "
                                        '"- check your feed XML!")))
                     (list (cdr title) (cdr feed))))
                 (map 'list
                      #'cadr
                      outlines))))
      alist)))

Simply eval it in your Emacs and run the following lines to import all your Google Reader feeds directly to News Ticker.

(setq newsticker-url-list
  (google-reader-to-newsticker "/path/to/subscriptions.xml"))

You might want to save your feeds for later via Newsticker Url List setting under:

M-x customize-group newsticker-retrieval

As with anything Emacs, you can bend News Ticker to your will and make it do whatever you please. Depending on your Emacs theme it might look something like this:

feeds

Go ahead, customize all the things!

Extra ninja

If you, like me, read loads of feeds every day you might consider adding a tiny notification thing-a-ma-jigger to your Emacs mode-line, just place the following code in your custom mode-line-format...

(setq-default mode-line-format
  (list
    ; ...

    '(:eval (let ((unread (or (newsticker--stat-num-items-total 'new)
                              0)))
              (when (> unread 0)
                (propertize
                  ; Any text will do, be creative!
                  (format "RSS: %d" unread)
                  'face 'some-colorful-font-face
                  'help-echo (format "You have %d unread RSS items!"
                                     unread)
                  'mouse-face 'mode-line-highlight))))))

...and enjoy it popping into existence every now and then (note the use of awesome Font Awesome):

1unread

2016-02-05: Adjusted some links.