Bash – Unexpected Behavior from Readline’s Bind Command

bashreadline

I hadn’t yet researched whether or not bracketed paste mode is supported by the version of Bash/Readline on my Ubuntu 16.04 system (it isn’t) and out of curiosity, I ran the following command presented in this Ask Ubuntu answer.

bind 'set-enable-bracketed-paste off'

If the set-enable-bracketed-paste setting didn’t exist, I’d expect bind to either complain about bad syntax or to do nothing. Instead, it unbound the lower case p, i.e., the character disappears into a black hole when typed.

It seems that this usage of the bind command unbinds the character that immediately follows the last hyphen before the first space character (if there’s any space in the string). E.g., I ran the following commands:

This results in the r character being unbound:

bind '__-r anymorecharacters'

This unbinds the character, 2:

bind 'xxxx-1-2xxx'

The characters can still be entered by typing CtrlV
before entering the character, thus allowing them to be re-bound:

bind 'r: self-insert'
bind '2: self-insert'

To me, this is unexpected and surprising behaviour and I’d consider it to be a bug. However, I’m not very familiar with Readline so I thought I’d ask here to check if there’s a reasonable explanation for this behaviour.

Best Answer

Readline's configuration file parser has some poor error checking.

set-enable-bracketed-paste is parsed in the way that, say, control-DEL or meta-q would be parsed. Readline takes the final minus-delimited part and tries to understand it as a key name, and takes the rest and tries to understand it as a sequences of modifiers.

The code that recognizes the key blithely falls back to just looking at the first character if no name in its table of key names matches. So paste is taken to denote the p key.

The code that looks for modifiers does not care if there are other non-modifier things in the string and does not expect modifiers to be minus-terminated. So set-enable-bracketed- is simply treated as no modifiers.

This does not "unbind the p key". It re-binds the p key to the function named "off". The code that does that does not raise an error if no function named "off" can be found in the function table. The default function table has no such function.