zsh (z shell) numpad/numlock doesn't work

I just upgraded to zsh/oh-my-zsh. Almost immediately I notice on my machine that the 10-digit numpad is not working. It was working in bash and fish shell.

Oddly, if I hold down the fn/function key it acts like numlock and works, but it doesn't "lock" and I would have to keep holding down fn to type out the numbers.

Any ideas out there?


Solution 1:

The numpad key do not send the same key symbols as the 'normal' number key in the top row. For example: The numpad-1-key sends KP_1 while the 1-key just sends 1.

Some terminals automatically remap the numpad key to send the same codes to the shell. Also, some shells (for example bash) just interprete the numpad keys like their equivalents in the main block.

zsh does not do the mapping automatically, but you can use bindkey to do the mapping on your own. I have the following in my ~/.zshrc to get the keypad working:

# Keypad
# 0 . Enter
bindkey -s "^[Op" "0"
bindkey -s "^[Ol" "."
bindkey -s "^[OM" "^M"
# 1 2 3
bindkey -s "^[Oq" "1"
bindkey -s "^[Or" "2"
bindkey -s "^[Os" "3"
# 4 5 6
bindkey -s "^[Ot" "4"
bindkey -s "^[Ou" "5"
bindkey -s "^[Ov" "6"
# 7 8 9
bindkey -s "^[Ow" "7"
bindkey -s "^[Ox" "8"
bindkey -s "^[Oy" "9"
# + -  * /
bindkey -s "^[Ok" "+"
bindkey -s "^[Om" "-"
bindkey -s "^[Oj" "*"
bindkey -s "^[Oo" "/"

bindkey -s in-string out-string binds in-string to out-string. If in-string is typed out-string is pushed back and treated as input.

The actual codes (for example ^[Oq) may be different on your system. You can press Ctrl+v followed by the key in question to get the code for your terminal.

Solution 2:

To complete the answer that @adaephon gave, the following are the correct bindings for the Apple USB keyboard (A1243). These need to be added to ~/.zshrc.

# Fix numeric keypad
# 0 . Enter
bindkey -s "^[Op" "0"
bindkey -s "^[On" "."
bindkey -s "^[OM" "^M"
# 1 2 3
bindkey -s "^[Oq" "1"
bindkey -s "^[Or" "2"
bindkey -s "^[Os" "3"
# 4 5 6
bindkey -s "^[Ot" "4"
bindkey -s "^[Ou" "5"
bindkey -s "^[Ov" "6"
# 7 8 9
bindkey -s "^[Ow" "7"
bindkey -s "^[Ox" "8"
bindkey -s "^[Oy" "9"
# + -  * / =
bindkey -s "^[Ol" "+"
bindkey -s "^[Om" "-"
bindkey -s "^[Oj" "*"
bindkey -s "^[Oo" "/"
bindkey -s "^[OX" "="

Solution 3:

Also complementing answer from @adaephon. Here is what I had to use for my Dell Desktop, might be of help. Just add it in your .zshrc file.

(BTW dont add bindings from all answers, you should just have one binding per key)

# Keypad
# 0 . Enter
bindkey -s "^[Op" "0"
bindkey -s "^[On" "."
bindkey -s "^[OM" "^M"
# 1 2 3
bindkey -s "^[Oq" "1"
bindkey -s "^[Or" "2"
bindkey -s "^[Os" "3"
# 4 5 6
bindkey -s "^[Ot" "4"
bindkey -s "^[Ou" "5"
bindkey -s "^[Ov" "6"
# 7 8 9
bindkey -s "^[Ow" "7"
bindkey -s "^[Ox" "8"
bindkey -s "^[Oy" "9"
# + -  * /
bindkey -s "^[OQ" "/"
bindkey -s "^[OR" "*"
bindkey -s "^[OS" "-"
bindkey -s "^[Ol" "+"
#END Keypad

Solution 4:

On my Mac OSX El Capitan, the period key is ^[0n instead of ^[01. Also I have a Logitech wireless keyboard for the Mac and it has an = sign on the numpad too. My final mapping looks like below:

# Keypad
# 0 . Enter
bindkey -s "^[Op" "0"
bindkey -s "^[On" "."
bindkey -s "^[OM" "^M"
# 1 2 3
bindkey -s "^[Oq" "1"
bindkey -s "^[Or" "2"
bindkey -s "^[Os" "3"
# 4 5 6
bindkey -s "^[Ot" "4"
bindkey -s "^[Ou" "5"
bindkey -s "^[Ov" "6"
# 7 8 9
bindkey -s "^[Ow" "7"
bindkey -s "^[Ox" "8"
bindkey -s "^[Oy" "9"
# + -  * / =
bindkey -s "^[Ok" "+"
bindkey -s "^[Om" "-"
bindkey -s "^[Oj" "*"
bindkey -s "^[Oo" "/"
bindkey -s "^[OX" "="

The solution others proposed works correctly however.