Work with Polybar in Emacs X Window Manager, Part 2: Add Workspace Indicators

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.

  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.


Join the conversation

Your email address will not be published. Required fields are marked *