Repository: ipython/ipython

Issue:
Behavior of Control-p changed with prompt toolkit and vi bindings
Before the new prompt toolkit changes, in the old readline days, your average vim users would put something like this in their `~/.inputrc`:

```
$include /etc/inputrc
set editing-mode vi
$if mode=vi
set keymap vi-command
$endif
```

With this setup, we startup IPython, and we are in editing mode by default, as seems natural.  In editing mode, Control-p brings up previous lines from the history.   ESC (or its vim equivalents) puts us into navigation mode, which has the same Control-p behavior.

In the new prompt_toolkit terminal emulation, I believe we need to add the following to `~/.ipython/profile_default/ipython_config.py`:

```
# Configuration file for all things ipython
c = get_config()
c.TerminalInteractiveShell.editing_mode = 'vi'
```

In this case, when I start IPython, I am again in editing mode (good) but now Control-p starts autocompletion, until I exit to navigation mode with ESC (etc).   I use Control-p all the time, so it's a significant inconvenience having to prefix all my Control-p's with ESC.   As a vim user, as you can imagine, I hate using the cursor keys, which would be my other option.

It would be good to keep the previous Control-p behavior, and probably by default, but at least available by configuration.

Behavior of Control-p changed with prompt toolkit and vi bindings
Before the new prompt toolkit changes, in the old readline days, your average vim users would put something like this in their `~/.inputrc`:

```
$include /etc/inputrc
set editing-mode vi
$if mode=vi
set keymap vi-command
$endif
```

With this setup, we startup IPython, and we are in editing mode by default, as seems natural.  In editing mode, Control-p brings up previous lines from the history.   ESC (or its vim equivalents) puts us into navigation mode, which has the same Control-p behavior.

In the new prompt_toolkit terminal emulation, I believe we need to add the following to `~/.ipython/profile_default/ipython_config.py`:

```
# Configuration file for all things ipython
c = get_config()
c.TerminalInteractiveShell.editing_mode = 'vi'
```

In this case, when I start IPython, I am again in editing mode (good) but now Control-p starts autocompletion, until I exit to navigation mode with ESC (etc).   I use Control-p all the time, so it's a significant inconvenience having to prefix all my Control-p's with ESC.   As a vim user, as you can imagine, I hate using the cursor keys, which would be my other option.

It would be good to keep the previous Control-p behavior, and probably by default, but at least available by configuration.



Discussion:
cc @jonathanslenders 

Thanks @matthew-brett for the detailed explanation. I'll see if we can do something in IPython itself. 

cc @jonathanslenders 

Thanks @matthew-brett for the detailed explanation. I'll see if we can do something in IPython itself. 


Resolving patch:
diff --git a/IPython/terminal/ptshell.py b/IPython/terminal/ptshell.py
--- a/IPython/terminal/ptshell.py
+++ b/IPython/terminal/ptshell.py
@@ -202,6 +202,24 @@ def _(event):
             else:
                 b.insert_text('\n' + (' ' * (indent or 0)))
 
+        @kbmanager.registry.add_binding(Keys.ControlP, filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER)))
+        def _previous_history_or_previous_completion(event):
+            """
+            Control-P in vi edit mode on readline is history next, unlike default prompt toolkit.
+
+            If completer is open this still select previous completion.
+            """
+            event.current_buffer.auto_up()
+
+        @kbmanager.registry.add_binding(Keys.ControlN, filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER)))
+        def _next_history_or_next_completion(event):
+            """
+            Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit.
+
+            If completer is open this still select next completion.
+            """
+            event.current_buffer.auto_down()
+
         @kbmanager.registry.add_binding(Keys.ControlG, filter=(
             HasFocus(DEFAULT_BUFFER) & HasCompletions()
             ))
@@ -210,9 +228,6 @@ def _dismiss_completion(event):
             if b.complete_state:
                 b.cancel_completion()
 
-
-
-
         @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER))
         def _reset_buffer(event):
             b = event.current_buffer


Test patch: