How to map Option-Shift-digit keys in zsh using bindkey
I am running zsh
inside tmux
inside Visual Studio Code integrated terminal. I have a Swedish Keyboard and I am on a Macbook running macOS 10.15.4 Catalina.
To get keys like meta-f and meta-d to work in this environment, i need to set the visual studio code setting terminal.integrated.macOptionIsMeta
to true
(see https://github.com/microsoft/vscode/issues/11314)
But If I do that, the following characters stop working @$|[]\{}
. Pushing them silently fails without printing anything.
The keys @$|[]
start working again if I add this to .zshrc
bindkey -s "\e2" @ # option-2 maps to the at-sign
bindkey -s "\e4" \$ # option-4 maps to dollar
bindkey -s "\e7" \| # option-7 maps to vertical bar
bindkey -s "\e8" \[ # option-8 maps to left square bracket
bindkey -s "\e9" \] # option-9 maps to right square bracket
(these are normal mappings on a Swedish Mac keyboard, e.g. Option-7
does normally print the vertical bar)
So, my remaining problem is how to make backslash, left and right curly braces, ie. \{}
, work again in this environment.
On a Swedish keyboard backslash is normally entered by pressing Option-Shift-7
. Since Shift-7
is slash (/
), I had high hopes for this:
bindkey -s "\e/" \\
But that does not help.
- How can I make
Option-Shift-7
print a backslash? - How can I make
Option-Shift-8
print a left curly brace? - How can I make
Option-Shift-9
print a right curly brace?
I found the answer by looking at the US keyboard layout
By imagining that I had a US keyboard, I could map the corresponding keys, even though those keys are not in those positions on a Swedish keyboard:
bindkey -s '\e&' \\ # option-shift-7 maps to backslash ('&' is found on the US keyboard!)
bindkey -s '\e*' \{ # option-shift-8 maps to left curly brace ('*' is found on the US keyboard!)
bindkey -s '\e(' \} # option-shift-9 maps to right curly brace ('(' is found on the US keyboard!)
For example: &
is Shift-6 on a Swedish keyboard, but Shift-7 on a US keyboard. \e&
means Meta-&
, that is Option-&
on a Mac. Which zsh
apparently interprets as Option-Shift-7
, even though it "should" be Option-Shift-6
on a Swedish keyboard.
I found the direction of setting terminal.integrated.macOptionIsMeta
to true
to be a dead end. Scripts that read input still did not understand the newly configured bindkeys.
I ended up setting back terminal.integrated.macOptionIsMeta
to false
and mapping the other way: I tested what unicode character was inserted when I press option
and a letter, then I did a bindkey
to the zsh command that should execute. For my Swedish keyboard this is the result
# binding needed in VS Code integrated terminal when "terminal.integrated.macOptionIsMeta" is false
bindkey '' accept-and-hold # option-a
bindkey 'ƒ' forward-word # option-b
bindkey 'ç' fzf-cd-widget #option-c
bindkey '∂' delete-word #option-d
bindkey '›' backward-word # option-f
bindkey '¸' get-line # option-g
bindkey '˛' run-help #option-h
bindkey 'fi' down-case-word #option-l
bindkey '‘' history-search-forward #option-n
bindkey 'π' history-search-backward #option-p
bindkey '•' push-line #option-q
bindkey 'ß' spell-word #option-s
bindkey '†' transpose-words #option-t
bindkey 'ü' up-case-word #option-u
bindkey 'Ω' copy-region-as-kill #option-w
bindkey '≈' execute-named-cmd #option-x
bindkey 'µ' yank-pop #option-y