Today, on matters concerning my existence...
Yes, I'm back. Been a couple years, but for absolutely no reason whatsoever I felt like doing a little bit of public blogging today.
Today's topic is what I hope to be a fairly quick project that I want to hack on: rewriting the easy-window-switcher.
... what is the easy-window-switcher?
Well, if you're too lazy to go read the README, it's basically a small Python script that wraps around some CLI tools to allow me to more easily switch focus between windows (go figure) in Ubuntu.
I've got four monitors and alt-tab just doesn't cut it. So, instead, this nifty little script allows me to switch window focus either relatively (i.e. to the closest leftmost or rightmost window relative to the currently-focused window) or absolutely (i.e. to the window on "monitor 1", "monitor 2", etc) by binding some keyboard shortcuts to the tool's commands.
I'm sure there's gotta be other tools that already do this, but my original motivation boiled down to "well, I know wmctrl
can be used to focus windows, so surely I could write a small wrapper to do what I want", and sure enough I could.
... so why rewrite it?
Just cause I think I can ¯\_(ツ)_/¯
But also because I want to specifically rewrite it in Rust (yes, I've become one of those people) and get some more Rust experience under my belt.
I've been playing with Rust for the last year or so and have come to quite enjoy it (once I got past the initial learning curve). As I keep saying to those I evangelize it to: "I've never quite enjoyed being yelled at by a computer so much".
I first started using it slightly out of necessity — I needed it to do backend Yjs document manipulation in Elixir (via the yrs library) for Knopic (which is a whole other story we're not gonna get into today), but I've recently been just trying to force it where I can for non-web app projects, and rewriting the easy-window-switcher
seems like a very natural progression. After all, it's a fairly self-contained program (only depending on some other CLI tools), and it's a program that's in the hotpath of my day-to-day workflow (i.e. speed is nice to have).
That being said, there is literally nothing wrong with the way I've been using easy-window-switcher
so far — it's not noticeably slow by any means. I just want to write more Rust ¯\_(ツ)_/¯
However, there is one small improvement I hope to make to the program from a "business logic" POV: being able to configure the monitor arrangement more easily. Right now, the monitor configuration (i.e. the number, size, arrangement, and order of monitors) is hard-coded and spread across a couple files in the Python implementation, so I want to consolidate that into one place, as well probably make it configurable via env vars or a config file.
Oh right, I guess the other 'big' thing we'd get out of this rewrite is making it easier to install the tool — can just distribute a binary instead of having to pip install
it from the repo. Small in the grand scheme of things, but a nice win nonetheless.
Otherwise, this is just a "light coding project to fill some time". All I've done so far is open an empty repo and bootstrap a Rust project, along with doing some basic design thinking (copied below), so we'll see where this goes I guess.
Design Thoughts
We have the following structure the Python implementation:
Main entrypoint that invokes the CLI
commands/
The CLI commands that invoke the services
services/
window_focuser.py
The primary service that handles all the business logic
external_services/
wmctrl.py
A wrapper service around the
wmctrl
CLI utility for measuring/controlling windows
data_models/
window.py
A struct for modelling the attributes of a single window
workspace.py
A struct for modelling the attributes of a 'workspace' (aka a monitor)
workspace_grid.py
A struct for modeeling the attributes of a 'grid of workspaces' (i.e. a single Ubuntu workspace's worth of monitors)
First thoughts:
Not sure why we call them "workspaces" instead of just "monitors", since "workspaces" means something else entirely in Ubuntu land; should rename them
This is quite a simple program and it's actually pretty well structured for something I wrote a long time ago
... I say that, but then I go check the logs and find that I actually only wrote it in 2020...
Main thing to figure out will be how to handle the calls out to the
wmctrl
CLIAlso
xdotool
that I found from inspection (and reading the dependencies list in the README...)
Improvements we can make:
Allow the monitor configuration to be more easily configurable
Right now, it's all hard-coded as constants in various files, along with a function that must be modifed to indicate how the monitors are laid out
Approach for the rewrite:
Rewrite it more-or-less 1-1 and then refactor once we have it working