What do these strings, 'M^?' and '^M?', represent in zsh/ZLE?
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?
^? 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-^? 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.