prompt-toolkit / prompt-toolkit/python-prompt-toolkit

Inconsistent "history forward/backward" Emacs bindings

Open
#1,794 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
10.6k
Forks
815
PR merge metrics
No merged PRs in 30d

Description

Hi !

First of all, thanks for your time working on this library.

I constantly hit a frustrating inconsistency between the bindings in Emacs and prompt_toolkit's Emacs bindings (I'm using pgcli):

Emacs prompt_toolkit with Emacs bindings
Alt-p Backward in history Letter p
Alt-n Forward in history Letter n
Ctrl-p Move cursor up one line Backward in history unless current history entry is multi-line in which case move cursor up one line
Ctrl-n Move cursor down one line Forward in history unless current history entry is multi-line in which case move cursor down one line

Hours of use of Emacs and terminals have engraved Alt-p/Alt-n in my muscle memory as the history navigation actions, so when I switch to pgcli and want to move back and forth in history, all I get is a frustrating list of p and n.

I've managed to get the expected Emacs behavior with the simple following changes:

diff --git a/src/prompt_toolkit/key_binding/bindings/emacs.py b/src/prompt_toolkit/key_binding/bindings/emacs.py
index 80a66fd2..88b456c6 100644
--- a/src/prompt_toolkit/key_binding/bindings/emacs.py
+++ b/src/prompt_toolkit/key_binding/bindings/emacs.py
@@ -107,12 +107,20 @@ def load_emacs_bindings() -> KeyBindingsBase:
     @handle("c-n")
     def _next(event: E) -> None:
         "Next line."
-        event.current_buffer.auto_down()
+        event.current_buffer.cursor_down(count=event.arg)

     @handle("c-p")
     def _prev(event: E) -> None:
         "Previous line."
-        event.current_buffer.auto_up(count=event.arg)
+        event.current_buffer.cursor_up(count=event.arg)
+
+    @handle("escape", "p")
+    def _history_backward(event: E) -> None:
+        event.current_buffer.history_backward(count=event.arg)
+
+    @handle("escape", "n")
+    def _history_forward(event: E) -> None:
+        event.current_buffer.history_forward(count=event.arg)

     def handle_digit(c: str) -> None:
         """

To be fair, in order for this to work, I also need to remove pgcli's own customization:

diff --git a/pgcli/key_bindings.py b/pgcli/key_bindings.py
index 9c016f7f..eb847aee 100644
--- a/pgcli/key_bindings.py
+++ b/pgcli/key_bindings.py
@@ -120,14 +120,4 @@ def pgcli_bindings(pgcli):
         _logger.debug("Detected alt-enter key.")
         event.app.current_buffer.insert_text("\n")

-    @kb.add("c-p", filter=~has_selection)
-    def _(event):
-        """Move up in history."""
-        event.current_buffer.history_backward(count=event.arg)
-
-    @kb.add("c-n", filter=~has_selection)
-    def _(event):
-        """Move down in history."""
-        event.current_buffer.history_forward(count=event.arg)
-
     return kb

For the sake of consistency, one could want to also set this behavior for ViM bindings though I wouldn't as there isn't anything broken per-se in the ViM bindings:

diff --git a/src/prompt_toolkit/key_binding/bindings/vi.py b/src/prompt_toolkit/key_binding/bindings/vi.py
index 436a553c..39e0151d 100644
--- a/src/prompt_toolkit/key_binding/bindings/vi.py
+++ b/src/prompt_toolkit/key_binding/bindings/vi.py
@@ -454,7 +454,7 @@ def load_vi_bindings() -> KeyBindingsBase:
         """
         Arrow up and ControlP in navigation mode go up.
         """
-        event.current_buffer.auto_up(count=event.arg)
+        event.current_buffer.cursor_up(count=event.arg)

     @handle("k", filter=vi_navigation_mode)
     def _go_up(event: E) -> None:
@@ -472,7 +472,7 @@ def load_vi_bindings() -> KeyBindingsBase:
         """
         Arrow down and Control-N in navigation mode.
         """
-        event.current_buffer.auto_down(count=event.arg)
+        event.current_buffer.cursor_down(count=event.arg)

     @handle("j", filter=vi_navigation_mode)
     def _go_down2(event: E) -> None:

Would you be open to adding these changes ?

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/prompt_toolkit/key_binding/bindings/emacs.py at load_emacs_bindings, then review the pgcli customization linked in pgcli/key_bindings.py. Confirm how the proposed Alt-p/Alt-n history actions and Ctrl-p/Ctrl-n line movement should interact with multiline entries; done means the Emacs bindings match the stated behavior without requiring pgcli overrides.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.