The timeout of the modeline indicates how often it refreshes in seconds. I think two seconds is good.

(setf *mode-line-timeout* 2)

Formatting Options

Next we get to the content of the modeline. This format follows the format indicated in the manpage of date.

(setf *time-modeline-string* "%F %H:%M")

Let’s also indicate how the groupname is displayed.

(setf *group-format* "%t")

The window format should display first its window number, then its titled, limited to 30 characters.

(setf *window-format* "%n: %30t")

Mode-Line Theme

The modeline is pretty easy. First, let’s load the colors.lisp file we just created:

(load "~/.stumpwm.d/colors.lisp")

Next, we can set some colours for the modeline. Let’s set the background of the modeline to Nord1 and the foreground to Nord5, I think this is a pretty good combination.

(setf *mode-line-background-color* phundrak-nord1
      *mode-line-foreground-color* phundrak-nord5)

We could also use some borders in the modeline. But we won’t. Let’s still set its colour to Nord1, just in case.

(setf *mode-line-border-color* phundrak-nord1
      *mode-line-border-width* 0)

Mode-Line Modules

Here are some modules that we will load for the modeline:

Module NameWhy Do I Need It?
battery-portableGet information on the battery level of a laptop
cpuGet the CPU usage
mpdDisplay MPD’s status
memGet the memory usage
(load-module "battery-portable")
(load-module "cpu")
(load-module "mpd")
(load-module "mem")

We need to set some variables, so modules can be displayed correctly. Note that the character between the font switchers in the second CPU formatter is U+E082, which symbolizes the CPU.

(setf cpu::*cpu-modeline-fmt*        "%c"
      cpu::*cpu-usage-modeline-fmt*  "^f2^f0^[~A~2D%^]"
      mem::*mem-modeline-fmt*        "%a%p"
      mpd:*mpd-modeline-fmt*         "%a - %t"
      mpd:*mpd-status-fmt*           "%a - %t"
      *hidden-window-color*          "^**"
      *mode-line-highlight-template* "«~A»")

Generating the Mode-Line

We can indicate what to display in our modeline. Each formatter will be separated by a Powerline separator with the code point 0xE0B0 in the font I am using (see Fonts).

FormatterWhat it doesCommand?
%gDisplay list of groups
%WDisplay list of windows in the current group and head
^>Rest of the modeline align to the right
docker-runningDisplay number of docker containers currently runningyes
mu-unreadDisplay number of unread emailsyes
%mDisplay current MPD song
%CDisplay CPU usage
%MDisplay RAM usage
%BDisplay battery status
%dDisplay date
(defvar *mode-line-formatter-list*
  '(("%g") ("%W") ("^>") ("docker-running" . t) ("mu-unread" . t) ("%m") ("%C") ("%M") ("%B") ("%d"))
  "List of formatters for the modeline.")

As you can see, generate-modeline generates the string defining *screen-mode-line-format* from the list of formatters we gave it with the table 2.

(defun generate-modeline (elements &optional not-invertedp rightp)
  "Generate a modeline for StumpWM.
ELEMENTS should be a list of `cons'es which `car' is the modeline
formatter or the shell command to run, and their `cdr' is either nil
when the `car' is a formatter and t when it is a shell command."
  (when elements
    (cons (format nil
                  " ^[~A^]^(:bg \"~A\") "
                  (format nil "^(:fg \"~A\")^(:bg \"~A\")^f1~A^f0"
                          (if (xor not-invertedp rightp) phundrak-nord1 phundrak-nord3)
                          (if (xor not-invertedp rightp) phundrak-nord3 phundrak-nord1)
                          (if rightp "" ""))
                  (if not-invertedp phundrak-nord3 phundrak-nord1))
          (let* ((current-element (car elements))
                 (formatter       (car current-element))
                 (commandp        (cdr current-element)))
            (cons (if commandp
                      `(:eval (run-shell-command ,formatter t))
                    (format nil "~A" formatter))
                  (generate-modeline (cdr elements)
                                     (not not-invertedp)
                                     (if (string= "^>" (caar elements)) t rightp)))))))

It is then easy to define a command that can call this function and set this variable, so we can sort of reload the mode-line.

(defcommand reload-modeline () ()
  "Reload modeline."
   (lambda ()
     (setf *screen-mode-line-format*
           (cdr (generate-modeline *mode-line-formatter-list*))))))

And actually, let’s reload the modeline immediately.