A minimal elisp status_command (May, 2024)

I wanted to experiment with dwl-guile this weekend, in an effort to be able to use guile scheme to configure and control even more components of my GNU Guix system and be able to geiser-connect-local to a REPL controlling my window manager.

Most days I run emacs in fullscreen and use my modeline for all kind of information, if it wasn't for the three-to-four percent of time spend outside of emacs and the convenience of having a workspace indicator, I could've perfectly lived without a status bar altogether. This considered, I choose to use a simple STDIN based status bar called somebar with dwl-guile, which means a simple status_command for time, battery information and so on was needed.

Requirements

My requirements for a status_command are pretty simple. Datetime, battery and displaying my currently clocked-in org agenda task. So I started out writing something small in guile that gathers these information and was called from mcron periodically.

I already had a elisp function, which is a modified version of this: Org-mode clock in i3blocks | bendersteed.tech, I've been using for ages to get the currently clocked-in task; so my guile script had to call emacsclient to retrieve this information.

Accidentally figuring out a better solution

Quarter an hour into this I found myself taking away more and more functionality from the guile script I just came up with integrating those into my elisp function; as it had to be called anyways, so simplifying things by offloading information gathering to elisp felt right. In fact, Emacs already had everything I need (almost) out of box.

There's format-time-string to get the current time neatly formatted, a battery-status-function in elisp and to get the current battery status. So the only thing my guile script had left to do was calling emacsclient and writing the output to a named pipe; which means I could just call emacsclient and pipe its output; and do so from mcron every minute.

We've got cron at home, cron at home:

At the end I've replaced my status_command script with a simple elisp function, but still depended on emacsclient for it to be executed and mcron to periodically execute it. A write-region later, my elisp function was able to directly update the status bar; and a run-with-timer later, having mcron taking care of periodically calling emacsclient was no more.

My elisp status_command

All that's left to do was adding my status_command to my init.el alongside adding a timer that calls it every 60 seconds:

(require 'org-clock)
(defun wilkos-status-command ()
  (let ((somebar-fifo (concat (getenv "XDG_RUNTIME_DIR") "/somebar-0")))
    (if (file-exists-p somebar-fifo)
    (write-region (format "status %s | %s | %s λ\n"
              (if (org-clocking-p)
                  (format "%s (%s)"
                      org-clock-heading
                      (format-seconds "%h:%m" (* (org-clock-get-clocked-time) 60)))
                (format "no running task"))
              (format "%s"
                  (let ((battery-echo-area-format "%p% (%c mAh, %b%t remaining)"))
                    (battery-format battery-echo-area-format (funcall battery-status-function))))
                  (format-time-string "%Y-%m-%dT%H:%M (w%U)"))
          nil somebar-fifo
          nil 'quiet)
    (message (format "%s does not exist" somebar-fifo)))))

(run-with-timer 0 (* 1 60) 'wilkos-status-command)

and call it a day.