Emacs can do a lot. This is hardly news! One of the things you can use Emacs for is to browse twitter. Why might you want to do this? Well, the main benefit is that you remain in Emacs! This means I can capture tweets easily into my org-roam database and then have them available to cite, or link, and include in my research.

The main way of browsing twitter within Emacs is to use Yuto Hayamizu’s twittering-mode. This is a great package that gives a tweetdeck-like interface within the editor for browsing twitter.

There are some limitations of course. Video in particular can’t be viewed within an Emacs buffer using this mode but images should be able to! Yet - they don’t. And it seems the mode’s maintainer has been on a bit of hiatus from the project and there haven’t been many updates recently. I found an issue related to this: twittering-mode/issues/136 where Alexander Fu provided a solution by adding a new format code for tweet rendering that will show the attached image! Fantastic.

A little explanation is in order here. Twittering-mode, like much of Emacs, is very customizable and this includes how tweets are displayed. It provides numerous format codes which are little two character sigils that correspond to parts of a tweet like the user, the date, the text itself, etc. So what Alexander did was effectively adding a brand new format code that handles the image part of a tweet properly.

Now, Alexander’s posted solution works but it completely replaces twittering-mode’s function that handles these format codes. This seemed rather intrusive to me since all we really want is just to add a new code to the list of valid ones. I ended up taking the core of Alexander’s implementation and implemented it differently using Emacs’ (defadvice :around) The :around key is the important bit - rather than completely replacing the function this adds a wrapper function that gets called instead. This wrapper function gets passed in the original function and any arguments to it, and Emacs will use whatever value this wrapper function returns instead!

This is exactly what we need. I created a new function to wrap around the existing twittering-mode function. This new function calls the original function which returns a list of valid format codes. Then my wrapper just adds the new image format code to this list and returns it. Super clean. Defadvice is really powerful and acts as an escape hatch that lets you customize code you don’t own. Just one of the many things that makes Emacs such an amazingly productive environment.

Enough talk, here’s the code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
;;;  Twittering
(after! twittering-mode
  ;; https://github.com/hayamiz/twittering-mode/issues/136#issuecomment-375902630
  (defun +lh/twittering-add-image-format (format-table-func status-sym prefix-sym)
    "Adds the I format code to display images in the twittering-mode format table."
    (let ((format-table (funcall format-table-func status-sym prefix-sym)))
      (push `("I" .
              (let* ((entities (cdr (assq 'entity ,status-sym)))
                     text)
                (mapc (lambda (url-info)
                        (setq text (or (cdr (assq 'media-url url-info)) "")))
                      (cdr (assq 'media entities)))
                (if (string-equal "" text)
                    text
                  (let ((twittering-convert-fix-size 360))
                    (twittering-make-icon-string nil nil text))))) format-table)))
  (advice-add #'twittering-generate-format-table :around #'+lh/twittering-add-image-format)
  (setq twittering-icon-mode t
        twittering-use-icon-storage t
        twittering-icon-storage-limit 10000
        twittering-convert-fix-size 40
        twittering-status-format "
  %i  %FACE[font-lock-function-name-face]{  @%s}  %FACE[italic]{%@}  %FACE[error]{%FIELD-IF-NONZERO[❤ %d]{favorite_count}}  %FACE[warning]{%FIELD-IF-NONZERO[↺ %d]{retweet_count}}

%FOLD[   ]{%FILL{%t}
%QT{
%FOLD[   ]{%FACE[font-lock-function-name-face]{@%s}\t%FACE[shadow]{%@}
%FOLD[ ]{%FILL{%t}}
}}}

    %I

%FACE[twitter-divider]{                                                                                                                                                                                  }
"))

Here you can see +lh/twittering-add-image-format is our new wrapper function. We add this to twittering-generate-format-table using (advice-add). Then we set some general parameters - for twittering-mode implementation reasons images are handled as “icons.” Lastly the most important bit is setting twittering-status-format which is just the default format that twittering-mode provides but with the addition of our new format code %I!

And once you have that in place here’s what it looks like:

Et voila!