index rss mastodon twitter github linkedin email
Álvaro Ramírez
sponsor

Álvaro Ramírez

11 September 2024 Spiffing up those echo messages

Well-ingrained into every Emacs user is the echo area, a one-stop shop to receive any kind of message from the editor, located at the bottom of the frame. Posting messages to this area from elisp couldn't be simpler:

(message "Hello world")

svg-hello-world.gif

If we want to get a little fancier, we can propertize the text to add some styling.

(message (propertize "hello " 'face '(:foreground "#C3E88D"))
         (propertize "world" 'face '(:foreground "#FF5370")))

svg-hello-world-colors.gif

With this in mind, I set out to add a tiny command to ready-player.

I wanted the ability to ask what's on without switching to another buffer. The echo area is perfect for that. It should display track title, artist, and album.

(message (concat "Ahead " ;; title
                 (propertize "Wire " 'face '(:foreground "#C3E88D")) ;; artist
                 (propertize "The Ideal Copy" 'face '(:foreground "#FF5370")))) ;; album

svg-ready-player-colors.gif

This kinda works, but I wasn't convinced with the styling. Maybe I need multi-line?

(message (concat "Ahead\n" ;; title
                 (propertize "Wire\n" 'face '(:foreground "#C3E88D")) ;; artist
                 (propertize "The Ideal Copy" 'face '(:foreground "#FF5370")))) ;; album

svg-ready-player-colors-multiline.gif

I felt something was missing. If I could just add the album artwork as a thumbnail… The ideal layout would maybe look something like:

+-------+
|       | Ahead
| image | Wire
|       | The Ideal Copy
+-------+

While the text-everywhere nature of Emacs buffers has many advantages, building more involved layouts can have its challenges. But hey, for that simple read-only message we're aiming at, we can certainly get creative without too much trouble. You see, Emacs has native svg support, so we can craft our fancy layout in elisp and tell Emacs to render it for us.

While I'm a noob at doing anything in svg from Emacs, adding an image and three labels, really isn't that difficult.

(message
 (let* ((image-width 90)
        (image-height 90)
        (text-height 25)
        (svg (svg-create (frame-pixel-width) image-height)))
   (svg-embed svg "path/to/thumbnail.png"
              "image/png" nil
              :x 0 :y 0 :width image-width :height image-height)
   (svg-text svg "Ahead"
             :x (+ image-width 10) :y text-height
             :fill (face-attribute 'default :foreground))
   (svg-text svg "Wire"
             :x (+ image-width 10) :y (* 2 text-height)
             :fill "#C3E88D")
   (svg-text svg "The Ideal Copy" :x (+ image-width 10) :y (* 3 text-height)
             :fill "#FF5370")
   (with-temp-buffer
     (svg-insert-image svg)
     (buffer-string))))

The code is fairly self-explanatory. While there may be an even simpler way (please lemme know), I used a temporary buffer to embed the svg in the propertized text prior to feeding to the handy message function.

…and with that, we get a richer display of the current track.

svg-ready-player-colors-image.gif

While I haven't experimented with other ways of creating multi-column layouts in Emacs (including images), I'd love to know if there's anything else available besides svg.

Enjoying these tips? Using one of my Emacs packages?

Help make them sustainable. Consider supporting this work.