Article summary
Welcome back. This is part two of two posts about working with polybar
in EXWM, the Emacs X Window Manager. If you haven’t yet, go to Part 1 and have a read.Β Today we’re going over how to add workspace indicators to Polybar.
Workspace Indicators in `polybar`
The Problem
At present, EXWM does not play nice with the default xworkspaces
Polybar module. I think this might happen because we’re rendering these workspaces within Emacs itself and not in separate X workspaces. Instead, we utilized polybar
‘s IPC functionality to hook into the EXWM workspace change hook and update the index of the workspace via Elisp. Below is my solution for this.
My Solution
First, let’s open our polybar
configuration. This file may be at ~/.config/polybar/config.ini
for you, but I tend to keep my EXWM-specific configuration in ~/.config/doom/exwm/polybar.config.ini
.
[module/exwm-ws-indicator]
type = custom/ipc
hook-0 = emacsclient -e "(bp/polybar-exwm-ws-indicator)" -s default | sed -e 's/^"//' -e 's/"$//'
initial = 1
format-underline = ${colors.magenta}
format-foreground = ${colors.magenta}
format-margin = 1
Then, add the module to the modules-* section of your choice. Here I’m placing it in the center of the bar. Also very important, ensure you’re using the appropriate font for your icon set. I’m using Iosevka Nerd Font. For this post, which is not rendered in a Nerd Font, I’ll use emojis to illustrate the selected workspaces.
...
font-0 = Iosevka Nerd Font:style=Medium,Regular
...
modules-center = exwm-ws-indicator
...
As you can see in the above configuration, we’ll need to define the bp-polybar-ws-indicator
function. But, first, let’s make sure Emacs and polybar
can communicate via IPC, or Inter-process Communication. Credit to David Wilson of System Crafters for this function, which can be used for general IPC between polybar
and Emacs. See his video on crafting the “Perfect Panel” here.
(defun bp/send-polybar-hook (module-name hook-index)
"Generic IPC hook function for communicating with Polybar"
(start-process-shell-command "polybar-msg" nil
(format "polybar-msg hook %s %s" module-name hook-index)))
Next, we define our hook-wrapping function, which specifies polybar
to the module we’re hooking into and passes the initial value.
(defun bp/send-polybar-exwm-ws-indicator ()
"Wraps the hook for the 'exwm-ws-indicator' Polybar module"
(bp/send-polybar-hook "exwm-ws-indicator" 1))
Now, we’ll send polybar
the text we want it to display for our indicator module. Yes, I’m certain I could write more clever Elisp code to properly insert the “current” icon into the appropriate index in the list. But, I’ll leave that as an exercise for the reader.
For now, we’ll write a switch case statement, which in Elisp is called pcase
, where p stands for predicate. With this in place, we can select which indicator set to display in the polybar
panel.
(defun bp/polybar-exwm-ws-indicator ()
"Switch case to select the appropriate indicator"
(pcase exwm-workspace-current-index
(0 "π βͺ βͺ βͺ βͺ βͺ βͺ βͺ βͺ βͺ ")
(1 "βͺ π βͺ βͺ βͺ βͺ βͺ βͺ βͺ βͺ ")
(2 "βͺ βͺ π βͺ βͺ βͺ βͺ βͺ βͺ βͺ ")
(3 "βͺ βͺ βͺ π βͺ βͺ βͺ βͺ βͺ βͺ ")
(4 "βͺ βͺ βͺ βͺ π βͺ βͺ βͺ βͺ βͺ ")
(5 "βͺ βͺ βͺ βͺ βͺ π βͺ βͺ βͺ βͺ ")
(6 "βͺ βͺ βͺ βͺ βͺ βͺ π βͺ βͺ βͺ ")
(7 "βͺ βͺ βͺ βͺ βͺ βͺ βͺ π βͺ βͺ ")
(8 "βͺ βͺ βͺ βͺ βͺ βͺ βͺ βͺ π βͺ ")
(9 "βͺ βͺ βͺ βͺ βͺ βͺ βͺ βͺ βͺ π ")))
I’ve represented empty circle icons as the workspaces, with the filled icon indicating the current workspace. However, you can easily swap the icons. If you’re using a Nerd Font variant, and I highly recommend that you do, you can check out their cheat-sheet for more icons.
Finally, we add a hook to respond to workspace switch events, which in turn calls our hook method and updates the icons in the panel.
;; Update panel indicator when workspace changes
(add-hook 'exwm-workspace-switch-hook #'bp/send-polybar-exwm-ws-indicator)
With those in place, we should see the workspace indicators in the polybar
panel, and when we switch workspaces, we should see it update.
Polybar and Workspace Indicators
This concludes this two-part series on working with polybar
in EXWM. I hope this information will serve you well in your EXWM “ricing” endeavors and that you’re able to extrapolate your own custom EXWM/polybar
modules from here.