Key Binding Pattern Story: Window Management

:: composiphrase, key-binding, vim

Let me tell you a story about key bindings.

Once upon a time, I was a young Linux user. I used emacs, but also vim. I used a tiling window manager. I had learned many key bindings, and I was continuing to learn more. But I kept getting stuck.

I knew many of the key bindings for my window manager, but I forgot the ones I didn’t use regularly. I used the terminal multiplexer tmux sometimes, which also does window management-like stuff, but only remembered a few of the key bindings. I also had to deal with the fact that emacs and vim also do some amount of window management-like stuff. With vim you can mostly ignore it, but emacs often pops up other windows for various reasons. So I had to learn at least a few bindings for window management in emacs. But of course I only remembered a couple of commands that I used frequently. Also at about that time, I used Pentadactyl, the sorely missed browser add-on that gave Firefox a good user interface🪦. Firefox had tabs, and tab groups. That felt fairly similar to tabs in emacs or vim, or workspaces in a window manager. I had all of this very similar functionality across many different programs, but I didn’t know the key bindings because they were all different.

🪦: Pentadactly no longer works since Firefox switched to the newer extension API instead of the old XUL extension API. The new API is purposely nerfed, and doesn’t provide the power needed to replace pentadactyl. Some extensions try to do part of it, but they fail to consistently even provide basic key binding replacement because they can not be active on things like Firefox’s own UI pages, new tab pages, or pages that are not yet fully loaded. Pentadactyl did so much more, and it didn’t suddenly break when you were on the wrong page or a page wasn’t loaded. I miss it so much.

So I decided on a scheme of how the different not-exactly-the-same-but-similar operations in the different programs should be correlated together into abstract operations. My window manager had windows in a workspace in a monitor, tmux had panes in a tab in a session, etc, typically hierarchically. I decided I cared about having 3 levels of hierarchy. So I chose a key for “move focus forward in level 1”, “move focus forward in level 2”, etc, as well as keys for moving the current thing within levels, eg. “move window to next space within layout (level 1), move window to next workspace (level 2), move window to next monitor (level 3)”. Also keys for various other operations, like resizing, that many of these share. I chose keys based on bindings that I already knew that felt related (eg. from vim and emacs text editing movements) or based on mnemonics. Many were based on the window manager key bindings I had at the time, but I also improved them and made them more systematic. So it was very easy to memorize the abstract scheme.

For each program, I used a different modifier key or command prefix. For my window manager, I used Super+<key> (IE Window key plus the relevant window management key). In tmux I used Control+t, <key>. Et cetera. Within a day, I knew the key bindings for every operation that I cared about for all of these programs – window manager, terminal multiplexer, editor, web browser. Creating a consistent “language” for interacting with similar operations drastically reduced the learning burden to use all of these operations in all of these programs. Suddenly it became easy to be fluent with them all, where previously I struggled. I went from being able to use maybe 30 window management operations divided between these programs (probably ~18-20 operations in the window manager, then a few each for other programs), to being able to use over 20 operations in each of emacs, vim, window manager, and tmux, as well as ~10 operations for firefox (with pentadactyl) tab and tab group management. And with a little bit of configuration, I can (and have) brought these same keys to other window managers, terminal multiplexers, and anything else that does some kind of window management (or something that feels sufficiently similar, like tab management) that I care to use.

When I made this scheme and configured all of these programs, and instantly felt fluent with all of these programs (or at least with this aspect of them all), it felt empowering and liberating. Essentially, this outcome, drastically easier command memorization, was the result of adding a pinch of abstraction to group similar commands and a dash of composability, composing something that identified a window management system (prefix or modifier key) with something that identified an operation (the operation key). Composiphrase takes that idea much farther. Instead of composing just two things, like with this window management scheme that I was so happy with (and still am, frankly), or 2-3 things like vim (operation like delete, change, yank, plus movement, plus maybe a number), it allows composition of many more things, drastically increasing the multiplicative benefits of composition. A dash of composition for window management gave me ~3-4x command memorization immediately, while also obviating the need to memorize new commands for future window managers (as long as I configure the new thing with my key layout). Composiphrase has a much bigger multiplier compared to Vim.