1

In the documentation for the Zsh Line Editor, there is a section that says:

For either in-string or out-string, the following escape sequences are recognised:

\a

    bell character 
\b

    backspace 
\e, \E

    escape 
\f

    form feed 
\n

    linefeed (newline) 
\r

    carriage return 
\t

    horizontal tab 
\v

    vertical tab 
\NNN

    character code in octal 
\xNN

    character code in hexadecimal 
\uNNNN

    unicode character code in hexadecimal 
\UNNNNNNNN

    unicode character code in hexadecimal 
\M[-]X

    character with meta bit set 
\C[-]X

    control character 
^X

    control character 

In all other cases, ‘\’ escapes the following character. Delete is written as ‘^?’. Note that ‘\M^?’ and ‘^\M?’ are not the same...

How should those last two sequences be interpreted? My guess is:

\M^?  - delete with the meta bit set?
^\M? - control + question mark with the meta bit set

Is this correct?

1
  • The first set, from the top down to around \xNN are from the standard C language escape sequences to represent various characters. See en.wikipedia.org/wiki/Escape_sequences_in_C . The ones after \xNN are probably extensions since the invention of Unicode. I don't know how to interpret ^\M? Commented Sep 5, 2023 at 2:33

1 Answer 1

2

^? is the byte 127 = 0x7f, which is commonly sent by the Backspace key (unless it's set to send ^H and the Delete key is set to ^?).

\M^? or \M-^? is the same but with the upper bit set, i.e. 255 = 0xff. On modern systems, non-ASCII characters are encoded in UTF-8. On some ancient systems, or on modern systems with some backward compatibility settings designed for ASCII-only input, typing an ASCII character while holding Meta sends the corresponding byte with the upper bit set. If your terminal does that and it sends ^? for Ctrl+?, you should be able to input this byte with Meta+Ctrl+?.

% bindkey '^\M?' wibble
% bindkey | grep wibble
"\M-^_" wibble

^\M? is parsed as controlifying \M?, which is metaifying ?, i.e. setting the upper bit (bit 7) in ?. ? is 0x3f = 0b00111111 so \M? is the byte 0xcf = 0b10111111. Controlifying apparently sets bits 5 and 6 to 0 for every character except ?, for which it changes the value to 0x7f. Thus ^\M? ends up being 0x9f = 0b10011111, which is normally written \M^_ (set the upper bit of ^_). That's not useful behavior, it's just an edge case in the implementation.

1
  • Controllifying is meant to flip bit 6. zsh is a bit of any exception here (you can compare the output of printf %s $'\Cx' for various values of x between ksh and zsh). I guess the zeroing of bit 5 is so that ^a is treated the same as ^A. zsh does it for everything but ?, ksh only for a-z. ksh flips bit 6 for every byte, zsh zeroes it for all but ?. In practice though, ^X is only expected to work and only useful for ^@, ^A..^Z, ^[, ^\ , ^], ^^, ^_, ^?. Commented Sep 10, 2023 at 16:23

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.