Last year, in a semi-useful exercise, I make a list of zsh key bindings enabled by default in the macOS Terminal. Reviewing the list helped me learn a few additional shortcuts and add a couple new ones.
Now it’s time to up my game. I’ve created a function, bindlist, which makes it easier than ever to display, filter, and reformat key bindings.
Being able to view the bindings so easily is really useful, even more than I’d expected. I’ve already learned a couple things that had previously escaped my notice, hidden in a sea of special characters spanning several pages.
Based on using zsh for a couple years and the lastest careful review, these are my observations and recommendations.
Limitations
Some limitations I’ve encountered:
- ctrl + number can’t be bound to anything
- ctrlc can’t be bound to anything and isn’t listed
- ctrlq can’t be bound (listed as push-line)
- ctrls can’t be bound (listed as history-incremental-search-forward)
- control characters are case insensitive, ctrlA = ctrla, but options bindings are case sensitive
Undefined keys
These keys are undefined by default and avaiable for use:
- ⌥ - E/e, I/i, J/j, K/k, M/m, O/o, R/r, V/v, X , Y , Z
-
⌥ctrl - Many
⌥^
bindings, which are case insensitive, are unused. - ctrlz - still works as a signal after binding another command to it
Recommended bindings
I prefer to make the best of default settings, only making a change when it clearly enhances my productivity.
So far, I’ve only added five bindings, removed two that don’t actually work, and removed another six redundant bindings I’m unlikely to ever use.
I might update these recommendations at some point but don’t expect them to change much, if at all.
Additional bindings
I used this shortcut a lot while reviewing and verify bindings:
bindkey "^[^K" describe-key-briefly
I’m never sure if I’ll ever use to use yank/pop, or if I even want to. But I might give it a try, especially now I can easily refresh my memory with the bindlist
function. That’s why I added kill-region
, which was oddly missing from the default bindings:
bindkey "^[k" kill-region
The default set-mark-command
binding is hard to remember and not so easy to use. I added opt-m for mark and opt-M for exchange-point-and-mark
:
bindkey "^[m" set-mark-command
bindkey "^[M" exchange-point-and-mark
I could never remember the various default bindings for undo.
After verifying using ^z
for undo doesn’t break its function as a signal, I happily added this bind to my configuration:
bindkey "^Z" undo
Bindings to remove (optional)
This is entirely unnecessary, perhaps even a bad idea, but I also removed some default bindings, just to clean up the list a bit.
I removed a couple of bindings that are listed by bindkey
but don’t actually work (and have other keys bound to the same command):
# remove redundant bindings that don't actually work
bindkey -r "^S"
bindkey -r "^Q"
Then I removed bindings that are redudant, either by default or because I’ve added alternative binding:
# redundant bindings (by default)
bindkey -r "^[\$" # spell-word
# redundant bindings (replaced by my additions)
bindkey -r "^@" # set-mark-command
bindkey -r "^X^X" # exchange-point-and-mark
bindkey -r "^X^U" # undo
bindkey -r "^Xu" # undo
bindkey -r "^_" # undo