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.