Article summary
For the past six months, I’ve used the Emacs X Window Manager daily as my main window manager and it’s been a great tool. It’s enabled me to move from using a disparate set of tools to now having an Integrated Computing Environment. It’s true: Emacs really does make a great operating system.
Starting and Stopping Polybar
Like many, I’ve adopted a lot of the configuration used by David Wilson of System Crafters. Part of that configuration includes his efs/start-panel
and efs/kill-panel
functions. These functions start a Polybar shell command from within Emacs while making sure to kill any existing processes before spawning a new instance. It does this by capturing a reference to the process that later can be passed to the built-in kill-process
function.
The Problem
Unfortunately, I run a multi-monitor setup, and David’s script that I borrowed only launches polybar
on the main screen. As a temporary workaround, I continued to use the bash script I call from within my old bspwm
configuration to launch polybar
. This didn’t feel very Emacs Zen-like, so I set out to devise a better way.
My Solution
I start by setting up an empty variable that will hold references to each running polybar
.
(defvar bp/polybar-processes nil
"A list of running polybar processes. So that we can kill them later. 👿")
In the next section, I query for a list of attached monitors, this type via polybar
itself. I could use xrandr
for this, but this output is easier to parse. Also, it’s one less dependency to rely upon from within a single script. Using cut
I split the input by the delimiter “:”, and take the first fragment, remove extraneous new lines. Finally, break the monitor names into their own entries.
(defun bp/get-monitors-list ()
"Get a list of the currently connected monitors. Requires polybar, instead of relying on xrandr, though you probably want it installed too."
(split-string
(substring
(shell-command-to-string "polybar -m | cut -d: -f 1") 0 -1) "\n"))
As defined, the bp/kill-panel
function will iterate over the list of running polybar
processes and stop them in succession, and finally, resetting the process list to nil
.
(defun bp/kill-panel ()
"Stop any running polybar processes"
(interactive)
(let ((process-list bp/polybar-processes))
(dolist
(p process-list)
(kill-process p)))
(setq bp/polybar-processes nil))
As its first order of business, the bp/start-panel
function calls the bp/kill-panel
function to clear out any existing running processes. It then calls bp/get-monitors-list
, mapping over our list monitors and interpolating their names into the shell command to start polybar
.
(defvar bp/polybar-config-location "~/.doom.d/exwm/polybar.config.ini"
"The customized location of your polybar config.ini. You'll most certainly want to customize this value. ")
(defun bp/start-panel ()
"Start polybar on each connected monitor"
(interactive)
(bp/kill-panel)
(setq bp/polybar-processes
(mapcar (lambda (monitor)
(start-process-shell-command "polybar" nil
(format "MONITOR=%s polybar -c %s --reload main" monitor bp/polybar-config-location)))
(bp/get-monitors-list))))
With these in place, I can now interactively show and hide the polybar
as needed from within Emacs.
Stay tuned for part two of this series, where we’ll set up workspace indicators on polybar
.