In fish shell, The generic key binding that matches if no other binding does can be set by specifying a SEQUENCE of the empty string (that is, '' ).

For example:

bind '' self-insert

I checked the documentation of zsh for similar functionality, it says:


Add the built-in set of meta-key bindings to the selected keymap. Only keys that are unbound or bound to self-insert are affected.

I am not sure whether i can use it for my purpose.

What is the generic key binding that matches if no other binding does in zsh?

1 Answer 1


In zsh, the widget that is invoked when no mapping is found for a key (byte sequence sent by the terminal) is the undefined-key widget which by default beeps, but you could redefine it to something else such as:

undefined-key() {
  zle -M "${(q+)KEYS} is not bound to anything"
  zle .$WIDGET
zle -N undefined-key

Or make it insert those bytes raw left of the cursor with:

undefined-key() LBUFFER+=$KEYS
zle -N undefined-key

It is not self-insert, self-insert in keymaps such as emacs or viins is bound to keys by virtue of it being bound to Ranges of bytes:

$ bindkey | awk '$NF == "self-insert"'
" "-"~" self-insert
"\M-^@"-"\M-^?" self-insert

That's all byte values for 32 (space) to 255 (M-^?) here excluding 127 (^? which is bound to backward-delete-char).

You can bind to something else with:

my-self-insert() { zle -M "You entered <$KEYS>"; zle self-insert; }
zle -N my-self-insert
for range (' -~' '\x80-\xff') bindkey -R $range my-self-insert

Though a maybe more idiomatic way is to redefine self-insert:

self-insert() { zle -M "You entered <$KEYS>"; zle .$WIDGET; }

Beware that for multibyte characters, the widget is invoked once for each byte in the character and AFAIK, bounds of the range can only be single bytes.

self-insert also only works for single bytes, though you could always do:

my-self-insert() {
  zle -M "You entered <$KEYS>"
  repeat ${NUMERIC-1} LBUFFER+=$KEYS
for c ({$'\ua0'..$'\uff'}) bindkey $c my-self-insert

To bind my-self-insert to Unicode character U+00A1 to U+00FF and do the self-inserting by hand by appending $KEYS (the bytes or sequence of bytes sent by the terminal that led to invoking the widget) to $LBUFFER (the section of the line editing buffer left of the cursor).

  • shift+del print 2~, alt+del print 3~, ctrl+del print 5~ in the terminal when I use all the three functions. I am not understanding the reason. Jun 11, 2023 at 11:17
  • 1
    @AhmadIsmail, that's not really related. My terminal emulator sends ESC[3;2~ upon pressing Shift+Del. There's no mapping for that sequence. There's a mapping for \e[3~ (the sequence sent upon Del) which is the closest, after reading \e[3 zle waits for the extra characters that may complete the sequence but that ; doesn't satisfy so you get beep and so that's discarded. Next come 2~ which are bound to self-insert. Jun 11, 2023 at 11:29
  • This information was very helpful. Jun 11, 2023 at 11:31
  • 1
    @AhmadIsmail, see edit for the mention of the undefined-key widget which I realise might have been what you were looking for (and is responsible for the beep I mention in my earlier comment). Jun 11, 2023 at 16:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .