I invested a chunk of time yesterday resolving one of life's great mysteries:
Why does Ctrl-W in the Python shell on the Mac delete the whole previous line instead of only the previous word?
Normally in readline programs, Ctrl-W is bound to the
unix-word-rubout command, which deletes the previous word. I'm used to using it to undo typos or change the ends of commands in bash, so it's enraging when using it in the Python shell deletes the rest of the juicy useful line accidentally.
I read a bunch of interesting things about readline, none of which actually seemed to affect the shell at all. For instance, Ctrl-Underscore should be useful to undo Ctrl-W's infuriating line-blanking... except that also, for the same mysterious reason, doesn't work on the Mac. According to
man readline, this (on demand, in the Python shell) should fix it:
>>> readline.bind_and_parse(r'C-w: unix-word-rubout')
and yet that, too, does absolutely nothing.
The Python inteterpreter [sic] supports editing of the current input line and history substitution, similar to facilities found in the Korn shell and the GNU Bash shell. However, rather than being implemented using the GNU Readline library, this Python interpreter uses the BSD EditLine library editline(3) with a GNU Readline emulation layer.
I was doubly astrayed from this conclusion because man readline worked perfectly well on my Mac, so obviously the readline library is available. When I look where it is, though, I realize:
mark@mac:~$ man -w readline /usr/local/share/man/man3/readline.3 mark@mac:~$ readlink `man -w readline` ../../../Cellar/readline/6.0/share/man/man3/readline.3
it's finding the Homebrew version of readline, which of course isn't what the stock Mac Python's readline module is using.
What to do about it
The PyPI description of readline suggests installing it and being done. I decided to take an alternate tack, which was to make a new
.editrc file to configurate editline apps. Editline doesn't even use the same command names for the regular commands, so instead of
unix-word-rubout, I consulted
man editrc to find that:
readline.parse_and_bind()s I tried in the Python shell didn't work because the bind command syntax is entirely different, and
- I wanted
ed-delete-prev-wordto delete the previous word.
.editrc ends up like this:
bind ^W ed-delete-prev-word bind ^R ed-search-prev-history bind ^_ vi-undo
Unfortunately editline also includes a much less awesome history search, so maybe I should just install readline from PyPI anyway. At least I can again delete bad words with impunity—which is great, since it aroused so many to choose from.