Skip to content

Commit

Permalink
Backport PR ipython#14080: Add pass-through filter for shortcuts
Browse files Browse the repository at this point in the history
  • Loading branch information
Carreau authored and meeseeksmachine committed Sep 12, 2023
1 parent 502d765 commit e7861a1
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 3 deletions.
3 changes: 2 additions & 1 deletion IPython/terminal/shortcuts/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,8 @@ def create_identifier(handler: Callable):
["right"],
"is_cursor_at_the_end_of_line"
" & default_buffer_focused"
" & emacs_like_insert_mode",
" & emacs_like_insert_mode"
" & pass_through",
),
]

Expand Down
7 changes: 6 additions & 1 deletion IPython/terminal/shortcuts/auto_suggest.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
from IPython.core.getipython import get_ipython
from IPython.utils.tokenutil import generate_tokens

from .filters import pass_through


def _get_query(document: Document):
return document.lines[document.cursor_position_row]
Expand Down Expand Up @@ -267,7 +269,10 @@ def backspace_and_resume_hint(event: KeyPressEvent):

def resume_hinting(event: KeyPressEvent):
"""Resume autosuggestions"""
return _update_hint(event.current_buffer)
pass_through.reply(event)
# Order matters: if update happened first and event reply second, the
# suggestion would be auto-accepted if both actions are bound to same key.
_update_hint(event.current_buffer)


def up_and_update_hint(event: KeyPressEvent):
Expand Down
34 changes: 33 additions & 1 deletion IPython/terminal/shortcuts/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@

from prompt_toolkit.application.current import get_app
from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER
from prompt_toolkit.filters import Condition, emacs_insert_mode, has_completions
from prompt_toolkit.key_binding import KeyPressEvent
from prompt_toolkit.filters import Condition, Filter, emacs_insert_mode, has_completions
from prompt_toolkit.filters import has_focus as has_focus_impl
from prompt_toolkit.filters import (
Always,
Expand Down Expand Up @@ -175,6 +176,36 @@ def is_windows_os():
return sys.platform == "win32"


class PassThrough(Filter):
"""A filter allowing to implement pass-through behaviour of keybindings.
Prompt toolkit key processor dispatches only one event per binding match,
which means that adding a new shortcut will suppress the old shortcut
if the keybindings are the same (unless one is filtered out).
To stop a shortcut binding from suppressing other shortcuts:
- add the `pass_through` filter to list of filter, and
- call `pass_through.reply(event)` in the shortcut handler.
"""

def __init__(self):
self._is_replying = False

def reply(self, event: KeyPressEvent):
self._is_replying = True
try:
event.key_processor.reset()
event.key_processor.feed_multiple(event.key_sequence)
event.key_processor.process_keys()
finally:
self._is_replying = False

def __call__(self):
return not self._is_replying


pass_through = PassThrough()

# these one is callable and re-used multiple times hence needs to be
# only defined once beforhand so that transforming back to human-readable
# names works well in the documentation.
Expand Down Expand Up @@ -248,6 +279,7 @@ def is_windows_os():
"followed_by_single_quote": following_text("^'"),
"navigable_suggestions": navigable_suggestions,
"cursor_in_leading_ws": cursor_in_leading_ws,
"pass_through": pass_through,
}


Expand Down
2 changes: 2 additions & 0 deletions docs/autogen_shortcuts.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ def format_filter(
return result
elif s in ["Never", "Always"]:
return s.lower()
elif s == "PassThrough":
return "pass_through"
else:
raise ValueError(f"Unknown filter type: {filter_}")

Expand Down

0 comments on commit e7861a1

Please sign in to comment.