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