Odd behavior of 'vi' mode in ipython - ipython

I'm trying to understand some annoying behaviour from ipython. I have vi mode enabled, I can confirm this like so;
[ins] In [1]: from IPython import get_ipython
...: ipython = get_ipython()
...: ipython.editing_mode
Out[1]: 'vi'
Mostly it works, but if I hit esc then two other keys in quick succession, only the first of the two is treated as a "normal" mode command ([nav]), the other one gets treated as an insert mode command ([ins]).
For example, say the cursor is at the end of the line
[nav] In [2]: who = ["some", "person"]
and I hit the b key 4 times quickly, the result is
[ins] In [2]: who = ["some", "personbbb"]
so the first press did what I expected, took the cursor back a word. Pressed 2,3 and 4 all acted in insert mode, resulting in "personbbb".
On the other hand, if I hit esc, wait a second or so, and then hit b 4 times I get exactly what I expect
[nav] In [2]: who = ["some", "person"]
and the cursor is by the 'e' in "some".
Hitting esc multiple times also ensures I stay in normal mode properly, no matter how fast I hit keys.
Is this a setting somewhere?
What I've tried
All the sugestions in How do I use vi keys in ipython under *nix? just in case I wasn't setting 'vi' mode properly.
Also updating my ipython, in case it was a bug in this version.
Searching for questions about 'vi' mode in ipython. The one I've just listed is the main thing that comes up, but I'm pretty surprised that this behaviour hasn't been mentioned before?
What I'm using
My zsh version is 5.8.1 (x86_64-apple-darwin21.0).
My ipython version is 8.6.0
My ~/.inputrc has
set editing-mode vi
set keymap vi
My ~/.ipython/profile_default/ipython_config.py has
c.TerminalInteractiveShell.editing_mode = 'vi'
(excluding comments)
I was torn between asking this here, and asking on the macOS stack exchange, because I don't know if this is an ipython issue, or a mac issue. I've only seen it on my mac using zsh.

Related

How to fix some tmux things (screen instead of xterm; function keys)?

Why does tmux change the terminal from xterm to screen, and how can I fix the resulting text color change in emacs? I think the easiest way would be to prevent it from changing to screen in the first place.
I can use TERM=xterm emacs file.ext to do it temporarily, but that's just a workaround that doesn't solve the root of the problem.
Furthermore, the function keys no longer work in emacs when using tmux. Instead of F3 and F4 being macro shortcuts, they just print a tilde as they would in the shell. This seems unrelated to xterm/screen mentioned above. What is happening here, and how I can fix this?
tmux sets TERM to screen because that terminal description is limited to things that tmux knows how to work with. Like screen, tmux translates features from the outer terminal description to the inner.
If a special key (function-key, cursor-key, etc) does not have an exact match in the terminal description, tmux will ignore it.
The default configuration for PuTTY sends different escape sequences for F1-F4. The sequences which PuTTY sends are not in the terminal description for xterm.
Here's a comparison of the two (as a CSV file, but readable enough):
NAME,putty,xterm
kf1,\E[11~,\EOP
kf2,\E[12~,\EOQ
kf3,\E[13~,\EOR
kf4,\E[14~,\EOS
kf5,\E[15~,\E[15~
kf6,\E[17~,\E[17~
kf7,\E[18~,\E[18~
kf8,\E[19~,\E[19~
kf9,\E[20~,\E[20~
kf10,\E[21~,\E[21~
kf11,\E[23~,\E[23~
kf12,\E[24~,\E[24~
kf13,\E[25~,\E[1;2P
kf14,\E[26~,\E[1;2Q
kf15,\E[28~,\E[1;2R
kf16,\E[29~,\E[1;2S
kf17,\E[31~,\E[15;2~
kf18,\E[32~,\E[17;2~
kf19,\E[33~,\E[18;2~
kf20,\E[34~,\E[19;2~
You'd have trouble getting PuTTY to send F13-F20, but will certainly run into trouble using PuTTY and tmux with TERM=xterm.
Regarding colors, the same issue applies. The screen terminal description tells applications that the terminal can support 8 colors, and tells how to display those eight colors. If your external terminal can do more, then tmux and screen hide that.
The conversion is not perfect. GNU screen has a feature where it looks for a corresponding screen.$TERM terminal description (i.e., concatenating the outer TERM value to screen). tmux does not do that: it makes assumptions regarding xterm. But PuTTY is not xterm...
ncurses has several of those concatenated terminal-names for terminal descriptions, but no one has suggested a way for tmux to use them automatically.

Complete command from history in ipython

For reasons outside of my control I'm stuck using python 2.6.6 and IPython 0.10.2. I also normally use the tcsh shell, and have gotten quite used to completing a command from the history using <A-p> (i.e. pressing the ALT key and p). However, this doesn't work in IPython. I know I can press <C-r> and then start typing a command, but what inevitably is happening is that I start a command, press <A-p>, get a colon indicating some weird state, then exit out of that state, delete my command, press <C-r> then search for my command. It's getting rather irritating. Is there any way to make <A-p> complete my already started command by relying on the history?
Ouch, this is an old version of IPython, Python (and pip). The bad news is I don't have much experience with such an old version of IPython, the good new is; it was way simpler at that time.
Most of the shortcut and feature are provided using readline, and the python bindings of stdlib. Meaning that most likely what you are trying to configure is readline itself and not only IPython; so you can find more information on that outside of IPython !
The secret is to grep in the source-code for parse_and_bind, then you'll find the following example configuration, leading me to change the ~/.ipython/ipy_user_conf.py to be like so at around line 99 (all indented an extra 4 space to be in the main() function):
import readline
readline.parse_and_bind('set completion-query-items 1000')
readline.parse_and_bind('set page-completions no')
rlopts = """\
tab: complete
"\C-l": possible-completions
set show-all-if-ambiguous on
"\C-o": tab-insert
"\M-i": " "
"\M-o": "\d\d\d\d"
"\M-I": "\d\d\d\d"
"\C-r": reverse-search-history
"\C-s": forward-search-history
"\C-p": history-search-backward
"\C-n": history-search-forward
"\e[A": history-search-backward
"\e[B": history-search-forward
"\C-k": kill-line
"\C-u": unix-line-discard"""
for cmd in rlopts.split('\n'):
readline.parse_and_bind(cmd)
The repetition of commands make me think that what \C,\M or [e mean might be system dependant. I would bet on \C being Control, and \M being Meta (Alt, Opt), but at least one of these line did the trick for me (and also now tab allows to complete). See also man readline for the list of commands you can bind to what, and enjoy! Hoping you can upgrade to Python 3 and IPython 6 at some point.
[Edit]
See Eric Carlsen second comment under this answer for how it was resolved.

Emacs key bindings change in terminal emulator

I notice that some Emacs key bindings change in terminal emulator (xfce4-terminal).
For example: M-SPC under TTY sets the mark, but in xfce4-terminal it does nothing.
Also:
C-- is undo in TTY and does nothing in terminal emulator
C-/ is erase char backward in TTY, and undo in terminal emulator
Is there any solution to prevent the burden of learning two rules? I just want them as usual in TTY console.
It's not an Emacs problem so much as a terminal problem. Terminal emulators can be limited in the control and escape sequences they can send, so it's probably the case that the emulators you cited are swallowing your special characters before they even reach Emacs. Try hitting C-h l (or M-x view-lossage) to see if your key combinations are arriving in Emacs.
In addition to the answer that Legoscia cited, also check out this thread and this thread.
Unless you have a strong reason to stay in a terminal, you might consider running the GUI version and then running one of the various shells within it (eg, shell, eshell, ansi-term).

C-<SPC> is intercepted in emacs -nw (terminal intercept?)

I use urxvt (terminal) under awesome (window manager) and ubuntu (os).
In graphical mode, c- set the mark but in text mode it inserts a space.
The problem is solved when using gnome-terminal but some other key combinations still does not work. For instance, C-: insert a : in both terminals.
I do not know where to look at to correct this behaviour.
C-h k (help on key combination) followed by one of these combination shows only the key pressed along ctrl, for instance C- is interpreted as .
As stated in comments, the terminal is probably the cause. I believe that C- should not enter a space at the terminal prompt, which it does here.
I identified this question as being related. This one too.
In my case, Ctrl-Space was being used to change input methods. Running ibus-setup and unbinding it fixed my problem (it now produces Nul)
See also: https://askubuntu.com/questions/243639/ctrlspace-has-been-bound-to-invoke-some-input-method-and-does-not-work-in-ema

IPython's history-search-backward not working as desired

IPython's history-search-backward feature is one of my favorite features. history-search-backward allows you to type part of a command and then search backward through your readline history for commands that began with that part of the command. By default (I believe) these are bound to UpArrow or Ctrl+P and DownArrow or Ctrl+N (for backward and forward respectively).
They are not working for me. Instead they just go linearly through my history instead of taking into account the characters I've already typed to (allgedly) filter my history.
I'm running IPython 0.13.2 (with Python 2 and 3) on Arch Linux from within XTerm.
If I hit Escape, Ctrl+P, then UpArrow and DownArrow work exactly as I want them to.
Additionally if I change my ipython_config.py to include
c.TerminalInteractiveShell.readline_parse_and_bind = ['"\\e[B": history-search-forward', '"\\e[A": history-search-backward']
then I can just do Escape UpArrow for the desired behaviour. (Here's the rest of my config file.)
Ctrl+V UpArrow produces ^[[A as I expect. I have the python readline library installed (which seems to fix common problems with macs running IPython).
I have these lines in my .bashrc
bind '"\e[A": history-search-backward'
bind '"\e[B": history-search-forward'
and they work exactly as I want them to within bash.
I have no idea what else to try next, so I've come here. Please help, I hope I've included enough information and done enough research.
The culprit was set keymap vi set in my .inputrc. I removed that and IPython history went back to what I expected. Thanks to #Thomas K!