summaryrefslogtreecommitdiffstats
path: root/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding
diff options
context:
space:
mode:
authormonster <[email protected]>2022-07-07 14:41:37 +0300
committermonster <[email protected]>2022-07-07 14:41:37 +0300
commit06e5c21a835c0e923506c4ff27929f34e00761c2 (patch)
tree75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding
parent03f024c4412e3aa613bb543cf1660176320ba8f4 (diff)
fix ya.make
Diffstat (limited to 'contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding')
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/__init__.py20
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/__init__.py0
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/auto_suggest.py63
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/basic.py253
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/completion.py203
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/cpr.py28
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/emacs.py557
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/focus.py24
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/mouse.py347
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/named_commands.py687
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/open_in_editor.py49
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/page_navigation.py82
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/scroll.py187
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/search.py93
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/vi.py2221
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/defaults.py60
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/digraphs.py1377
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/emacs_state.py36
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/key_bindings.py672
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/key_processor.py528
-rw-r--r--contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/vi_state.py107
21 files changed, 0 insertions, 7594 deletions
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/__init__.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/__init__.py
deleted file mode 100644
index be105369152..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from .key_bindings import (
- ConditionalKeyBindings,
- DynamicKeyBindings,
- KeyBindings,
- KeyBindingsBase,
- merge_key_bindings,
-)
-from .key_processor import KeyPress, KeyPressEvent
-
-__all__ = [
- # key_bindings.
- "ConditionalKeyBindings",
- "DynamicKeyBindings",
- "KeyBindings",
- "KeyBindingsBase",
- "merge_key_bindings",
- # key_processor
- "KeyPress",
- "KeyPressEvent",
-]
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/__init__.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/__init__.py
+++ /dev/null
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/auto_suggest.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/auto_suggest.py
deleted file mode 100644
index c016c0688fe..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/auto_suggest.py
+++ /dev/null
@@ -1,63 +0,0 @@
-"""
-Key bindings for auto suggestion (for fish-style auto suggestion).
-"""
-import re
-
-from prompt_toolkit.application.current import get_app
-from prompt_toolkit.filters import Condition, emacs_mode
-from prompt_toolkit.key_binding.key_bindings import KeyBindings
-from prompt_toolkit.key_binding.key_processor import KeyPressEvent
-
-__all__ = [
- "load_auto_suggest_bindings",
-]
-
-E = KeyPressEvent
-
-
-def load_auto_suggest_bindings() -> KeyBindings:
- """
- Key bindings for accepting auto suggestion text.
-
- (This has to come after the Vi bindings, because they also have an
- implementation for the "right arrow", but we really want the suggestion
- binding when a suggestion is available.)
- """
- key_bindings = KeyBindings()
- handle = key_bindings.add
-
- @Condition
- def suggestion_available() -> bool:
- app = get_app()
- return (
- app.current_buffer.suggestion is not None
- and len(app.current_buffer.suggestion.text) > 0
- and app.current_buffer.document.is_cursor_at_the_end
- )
-
- @handle("c-f", filter=suggestion_available)
- @handle("c-e", filter=suggestion_available)
- @handle("right", filter=suggestion_available)
- def _accept(event: E) -> None:
- """
- Accept suggestion.
- """
- b = event.current_buffer
- suggestion = b.suggestion
-
- if suggestion:
- b.insert_text(suggestion.text)
-
- @handle("escape", "f", filter=suggestion_available & emacs_mode)
- def _fill(event: E) -> None:
- """
- Fill partial suggestion.
- """
- b = event.current_buffer
- suggestion = b.suggestion
-
- if suggestion:
- t = re.split(r"(\S+\s+)", suggestion.text)
- b.insert_text(next(x for x in t if x))
-
- return key_bindings
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/basic.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/basic.py
deleted file mode 100644
index fc8f9643596..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/basic.py
+++ /dev/null
@@ -1,253 +0,0 @@
-# pylint: disable=function-redefined
-from prompt_toolkit.application.current import get_app
-from prompt_toolkit.filters import (
- Condition,
- emacs_insert_mode,
- has_selection,
- in_paste_mode,
- is_multiline,
- vi_insert_mode,
-)
-from prompt_toolkit.key_binding.key_processor import KeyPress, KeyPressEvent
-from prompt_toolkit.keys import Keys
-
-from ..key_bindings import KeyBindings
-from .named_commands import get_by_name
-
-__all__ = [
- "load_basic_bindings",
-]
-
-E = KeyPressEvent
-
-
-def if_no_repeat(event: E) -> bool:
- """Callable that returns True when the previous event was delivered to
- another handler."""
- return not event.is_repeat
-
-
-def load_basic_bindings() -> KeyBindings:
- key_bindings = KeyBindings()
- insert_mode = vi_insert_mode | emacs_insert_mode
- handle = key_bindings.add
-
- @handle("c-a")
- @handle("c-b")
- @handle("c-c")
- @handle("c-d")
- @handle("c-e")
- @handle("c-f")
- @handle("c-g")
- @handle("c-h")
- @handle("c-i")
- @handle("c-j")
- @handle("c-k")
- @handle("c-l")
- @handle("c-m")
- @handle("c-n")
- @handle("c-o")
- @handle("c-p")
- @handle("c-q")
- @handle("c-r")
- @handle("c-s")
- @handle("c-t")
- @handle("c-u")
- @handle("c-v")
- @handle("c-w")
- @handle("c-x")
- @handle("c-y")
- @handle("c-z")
- @handle("f1")
- @handle("f2")
- @handle("f3")
- @handle("f4")
- @handle("f5")
- @handle("f6")
- @handle("f7")
- @handle("f8")
- @handle("f9")
- @handle("f10")
- @handle("f11")
- @handle("f12")
- @handle("f13")
- @handle("f14")
- @handle("f15")
- @handle("f16")
- @handle("f17")
- @handle("f18")
- @handle("f19")
- @handle("f20")
- @handle("f21")
- @handle("f22")
- @handle("f23")
- @handle("f24")
- @handle("c-@") # Also c-space.
- @handle("c-\\")
- @handle("c-]")
- @handle("c-^")
- @handle("c-_")
- @handle("backspace")
- @handle("up")
- @handle("down")
- @handle("right")
- @handle("left")
- @handle("s-up")
- @handle("s-down")
- @handle("s-right")
- @handle("s-left")
- @handle("home")
- @handle("end")
- @handle("s-home")
- @handle("s-end")
- @handle("delete")
- @handle("s-delete")
- @handle("c-delete")
- @handle("pageup")
- @handle("pagedown")
- @handle("s-tab")
- @handle("tab")
- @handle("c-s-left")
- @handle("c-s-right")
- @handle("c-s-home")
- @handle("c-s-end")
- @handle("c-left")
- @handle("c-right")
- @handle("c-up")
- @handle("c-down")
- @handle("c-home")
- @handle("c-end")
- @handle("insert")
- @handle("s-insert")
- @handle("c-insert")
- @handle("<sigint>")
- @handle(Keys.Ignore)
- def _ignore(event: E) -> None:
- """
- First, for any of these keys, Don't do anything by default. Also don't
- catch them in the 'Any' handler which will insert them as data.
-
- If people want to insert these characters as a literal, they can always
- do by doing a quoted insert. (ControlQ in emacs mode, ControlV in Vi
- mode.)
- """
- pass
-
- # Readline-style bindings.
- handle("home")(get_by_name("beginning-of-line"))
- handle("end")(get_by_name("end-of-line"))
- handle("left")(get_by_name("backward-char"))
- handle("right")(get_by_name("forward-char"))
- handle("c-up")(get_by_name("previous-history"))
- handle("c-down")(get_by_name("next-history"))
- handle("c-l")(get_by_name("clear-screen"))
-
- handle("c-k", filter=insert_mode)(get_by_name("kill-line"))
- handle("c-u", filter=insert_mode)(get_by_name("unix-line-discard"))
- handle("backspace", filter=insert_mode, save_before=if_no_repeat)(
- get_by_name("backward-delete-char")
- )
- handle("delete", filter=insert_mode, save_before=if_no_repeat)(
- get_by_name("delete-char")
- )
- handle("c-delete", filter=insert_mode, save_before=if_no_repeat)(
- get_by_name("delete-char")
- )
- handle(Keys.Any, filter=insert_mode, save_before=if_no_repeat)(
- get_by_name("self-insert")
- )
- handle("c-t", filter=insert_mode)(get_by_name("transpose-chars"))
- handle("c-i", filter=insert_mode)(get_by_name("menu-complete"))
- handle("s-tab", filter=insert_mode)(get_by_name("menu-complete-backward"))
-
- # Control-W should delete, using whitespace as separator, while M-Del
- # should delete using [^a-zA-Z0-9] as a boundary.
- handle("c-w", filter=insert_mode)(get_by_name("unix-word-rubout"))
-
- handle("pageup", filter=~has_selection)(get_by_name("previous-history"))
- handle("pagedown", filter=~has_selection)(get_by_name("next-history"))
-
- # CTRL keys.
-
- @Condition
- def has_text_before_cursor() -> bool:
- return bool(get_app().current_buffer.text)
-
- handle("c-d", filter=has_text_before_cursor & insert_mode)(
- get_by_name("delete-char")
- )
-
- @handle("enter", filter=insert_mode & is_multiline)
- def _newline(event: E) -> None:
- """
- Newline (in case of multiline input.
- """
- event.current_buffer.newline(copy_margin=not in_paste_mode())
-
- @handle("c-j")
- def _newline2(event: E) -> None:
- r"""
- By default, handle \n as if it were a \r (enter).
- (It appears that some terminals send \n instead of \r when pressing
- enter. - at least the Linux subsystem for Windows.)
- """
- event.key_processor.feed(KeyPress(Keys.ControlM, "\r"), first=True)
-
- # Delete the word before the cursor.
-
- @handle("up")
- def _go_up(event: E) -> None:
- event.current_buffer.auto_up(count=event.arg)
-
- @handle("down")
- def _go_down(event: E) -> None:
- event.current_buffer.auto_down(count=event.arg)
-
- @handle("delete", filter=has_selection)
- def _cut(event: E) -> None:
- data = event.current_buffer.cut_selection()
- event.app.clipboard.set_data(data)
-
- # Global bindings.
-
- @handle("c-z")
- def _insert_ctrl_z(event: E) -> None:
- """
- By default, control-Z should literally insert Ctrl-Z.
- (Ansi Ctrl-Z, code 26 in MSDOS means End-Of-File.
- In a Python REPL for instance, it's possible to type
- Control-Z followed by enter to quit.)
-
- When the system bindings are loaded and suspend-to-background is
- supported, that will override this binding.
- """
- event.current_buffer.insert_text(event.data)
-
- @handle(Keys.BracketedPaste)
- def _paste(event: E) -> None:
- """
- Pasting from clipboard.
- """
- data = event.data
-
- # Be sure to use \n as line ending.
- # Some terminals (Like iTerm2) seem to paste \r\n line endings in a
- # bracketed paste. See: https://github.com/ipython/ipython/issues/9737
- data = data.replace("\r\n", "\n")
- data = data.replace("\r", "\n")
-
- event.current_buffer.insert_text(data)
-
- @Condition
- def in_quoted_insert() -> bool:
- return get_app().quoted_insert
-
- @handle(Keys.Any, filter=in_quoted_insert, eager=True)
- def _insert_text(event: E) -> None:
- """
- Handle quoted insert.
- """
- event.current_buffer.insert_text(event.data, overwrite=False)
- event.app.quoted_insert = False
-
- return key_bindings
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/completion.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/completion.py
deleted file mode 100644
index a30b54e632d..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/completion.py
+++ /dev/null
@@ -1,203 +0,0 @@
-"""
-Key binding handlers for displaying completions.
-"""
-import asyncio
-import math
-from typing import TYPE_CHECKING, List
-
-from prompt_toolkit.application.run_in_terminal import in_terminal
-from prompt_toolkit.completion import (
- CompleteEvent,
- Completion,
- get_common_complete_suffix,
-)
-from prompt_toolkit.formatted_text import StyleAndTextTuples
-from prompt_toolkit.key_binding.key_bindings import KeyBindings
-from prompt_toolkit.key_binding.key_processor import KeyPressEvent
-from prompt_toolkit.keys import Keys
-from prompt_toolkit.utils import get_cwidth
-
-if TYPE_CHECKING:
- from prompt_toolkit.application import Application
- from prompt_toolkit.shortcuts import PromptSession
-
-__all__ = [
- "generate_completions",
- "display_completions_like_readline",
-]
-
-E = KeyPressEvent
-
-
-def generate_completions(event: E) -> None:
- r"""
- Tab-completion: where the first tab completes the common suffix and the
- second tab lists all the completions.
- """
- b = event.current_buffer
-
- # When already navigating through completions, select the next one.
- if b.complete_state:
- b.complete_next()
- else:
- b.start_completion(insert_common_part=True)
-
-
-def display_completions_like_readline(event: E) -> None:
- """
- Key binding handler for readline-style tab completion.
- This is meant to be as similar as possible to the way how readline displays
- completions.
-
- Generate the completions immediately (blocking) and display them above the
- prompt in columns.
-
- Usage::
-
- # Call this handler when 'Tab' has been pressed.
- key_bindings.add(Keys.ControlI)(display_completions_like_readline)
- """
- # Request completions.
- b = event.current_buffer
- if b.completer is None:
- return
- complete_event = CompleteEvent(completion_requested=True)
- completions = list(b.completer.get_completions(b.document, complete_event))
-
- # Calculate the common suffix.
- common_suffix = get_common_complete_suffix(b.document, completions)
-
- # One completion: insert it.
- if len(completions) == 1:
- b.delete_before_cursor(-completions[0].start_position)
- b.insert_text(completions[0].text)
- # Multiple completions with common part.
- elif common_suffix:
- b.insert_text(common_suffix)
- # Otherwise: display all completions.
- elif completions:
- _display_completions_like_readline(event.app, completions)
-
-
-def _display_completions_like_readline(
- app: "Application[object]", completions: List[Completion]
-) -> "asyncio.Task[None]":
- """
- Display the list of completions in columns above the prompt.
- This will ask for a confirmation if there are too many completions to fit
- on a single page and provide a paginator to walk through them.
- """
- from prompt_toolkit.formatted_text import to_formatted_text
- from prompt_toolkit.shortcuts.prompt import create_confirm_session
-
- # Get terminal dimensions.
- term_size = app.output.get_size()
- term_width = term_size.columns
- term_height = term_size.rows
-
- # Calculate amount of required columns/rows for displaying the
- # completions. (Keep in mind that completions are displayed
- # alphabetically column-wise.)
- max_compl_width = min(
- term_width, max(get_cwidth(c.display_text) for c in completions) + 1
- )
- column_count = max(1, term_width // max_compl_width)
- completions_per_page = column_count * (term_height - 1)
- page_count = int(math.ceil(len(completions) / float(completions_per_page)))
- # Note: math.ceil can return float on Python2.
-
- def display(page: int) -> None:
- # Display completions.
- page_completions = completions[
- page * completions_per_page : (page + 1) * completions_per_page
- ]
-
- page_row_count = int(math.ceil(len(page_completions) / float(column_count)))
- page_columns = [
- page_completions[i * page_row_count : (i + 1) * page_row_count]
- for i in range(column_count)
- ]
-
- result: StyleAndTextTuples = []
-
- for r in range(page_row_count):
- for c in range(column_count):
- try:
- completion = page_columns[c][r]
- style = "class:readline-like-completions.completion " + (
- completion.style or ""
- )
-
- result.extend(to_formatted_text(completion.display, style=style))
-
- # Add padding.
- padding = max_compl_width - get_cwidth(completion.display_text)
- result.append((completion.style, " " * padding))
- except IndexError:
- pass
- result.append(("", "\n"))
-
- app.print_text(to_formatted_text(result, "class:readline-like-completions"))
-
- # User interaction through an application generator function.
- async def run_compl() -> None:
- "Coroutine."
- async with in_terminal(render_cli_done=True):
- if len(completions) > completions_per_page:
- # Ask confirmation if it doesn't fit on the screen.
- confirm = await create_confirm_session(
- f"Display all {len(completions)} possibilities?",
- ).prompt_async()
-
- if confirm:
- # Display pages.
- for page in range(page_count):
- display(page)
-
- if page != page_count - 1:
- # Display --MORE-- and go to the next page.
- show_more = await _create_more_session(
- "--MORE--"
- ).prompt_async()
-
- if not show_more:
- return
- else:
- app.output.flush()
- else:
- # Display all completions.
- display(0)
-
- return app.create_background_task(run_compl())
-
-
-def _create_more_session(message: str = "--MORE--") -> "PromptSession[bool]":
- """
- Create a `PromptSession` object for displaying the "--MORE--".
- """
- from prompt_toolkit.shortcuts import PromptSession
-
- bindings = KeyBindings()
-
- @bindings.add(" ")
- @bindings.add("y")
- @bindings.add("Y")
- @bindings.add(Keys.ControlJ)
- @bindings.add(Keys.ControlM)
- @bindings.add(Keys.ControlI) # Tab.
- def _yes(event: E) -> None:
- event.app.exit(result=True)
-
- @bindings.add("n")
- @bindings.add("N")
- @bindings.add("q")
- @bindings.add("Q")
- @bindings.add(Keys.ControlC)
- def _no(event: E) -> None:
- event.app.exit(result=False)
-
- @bindings.add(Keys.Any)
- def _ignore(event: E) -> None:
- "Disable inserting of text."
-
- return PromptSession(message, key_bindings=bindings, erase_when_done=True)
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/cpr.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/cpr.py
deleted file mode 100644
index 07b0fa75273..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/cpr.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from prompt_toolkit.key_binding.key_processor import KeyPressEvent
-from prompt_toolkit.keys import Keys
-
-from ..key_bindings import KeyBindings
-
-__all__ = [
- "load_cpr_bindings",
-]
-
-E = KeyPressEvent
-
-
-def load_cpr_bindings() -> KeyBindings:
- key_bindings = KeyBindings()
-
- @key_bindings.add(Keys.CPRResponse, save_before=lambda e: False)
- def _(event: E) -> None:
- """
- Handle incoming Cursor-Position-Request response.
- """
- # The incoming data looks like u'\x1b[35;1R'
- # Parse row/col information.
- row, col = map(int, event.data[2:-1].split(";"))
-
- # Report absolute cursor position to the renderer.
- event.app.renderer.report_absolute_cursor_row(row)
-
- return key_bindings
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/emacs.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/emacs.py
deleted file mode 100644
index a4a5e348f83..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/emacs.py
+++ /dev/null
@@ -1,557 +0,0 @@
-# pylint: disable=function-redefined
-from typing import Dict, Union
-
-from prompt_toolkit.application.current import get_app
-from prompt_toolkit.buffer import Buffer, indent, unindent
-from prompt_toolkit.completion import CompleteEvent
-from prompt_toolkit.filters import (
- Condition,
- emacs_insert_mode,
- emacs_mode,
- has_arg,
- has_selection,
- in_paste_mode,
- is_multiline,
- is_read_only,
- shift_selection_mode,
- vi_search_direction_reversed,
-)
-from prompt_toolkit.key_binding.key_bindings import Binding
-from prompt_toolkit.key_binding.key_processor import KeyPressEvent
-from prompt_toolkit.keys import Keys
-from prompt_toolkit.selection import SelectionType
-
-from ..key_bindings import ConditionalKeyBindings, KeyBindings, KeyBindingsBase
-from .named_commands import get_by_name
-
-__all__ = [
- "load_emacs_bindings",
- "load_emacs_search_bindings",
- "load_emacs_shift_selection_bindings",
-]
-
-E = KeyPressEvent
-
-
-def load_emacs_bindings() -> KeyBindingsBase:
- """
- Some e-macs extensions.
- """
- # Overview of Readline emacs commands:
- # http://www.catonmat.net/download/readline-emacs-editing-mode-cheat-sheet.pdf
- key_bindings = KeyBindings()
- handle = key_bindings.add
-
- insert_mode = emacs_insert_mode
-
- @handle("escape")
- def _esc(event: E) -> None:
- """
- By default, ignore escape key.
-
- (If we don't put this here, and Esc is followed by a key which sequence
- is not handled, we'll insert an Escape character in the input stream.
- Something we don't want and happens to easily in emacs mode.
- Further, people can always use ControlQ to do a quoted insert.)
- """
- pass
-
- handle("c-a")(get_by_name("beginning-of-line"))
- handle("c-b")(get_by_name("backward-char"))
- handle("c-delete", filter=insert_mode)(get_by_name("kill-word"))
- handle("c-e")(get_by_name("end-of-line"))
- handle("c-f")(get_by_name("forward-char"))
- handle("c-left")(get_by_name("backward-word"))
- handle("c-right")(get_by_name("forward-word"))
- handle("c-x", "r", "y", filter=insert_mode)(get_by_name("yank"))
- handle("c-y", filter=insert_mode)(get_by_name("yank"))
- handle("escape", "b")(get_by_name("backward-word"))
- handle("escape", "c", filter=insert_mode)(get_by_name("capitalize-word"))
- handle("escape", "d", filter=insert_mode)(get_by_name("kill-word"))
- handle("escape", "f")(get_by_name("forward-word"))
- handle("escape", "l", filter=insert_mode)(get_by_name("downcase-word"))
- handle("escape", "u", filter=insert_mode)(get_by_name("uppercase-word"))
- handle("escape", "y", filter=insert_mode)(get_by_name("yank-pop"))
- handle("escape", "backspace", filter=insert_mode)(get_by_name("backward-kill-word"))
- handle("escape", "\\", filter=insert_mode)(get_by_name("delete-horizontal-space"))
-
- handle("c-home")(get_by_name("beginning-of-buffer"))
- handle("c-end")(get_by_name("end-of-buffer"))
-
- handle("c-_", save_before=(lambda e: False), filter=insert_mode)(
- get_by_name("undo")
- )
-
- handle("c-x", "c-u", save_before=(lambda e: False), filter=insert_mode)(
- get_by_name("undo")
- )
-
- handle("escape", "<", filter=~has_selection)(get_by_name("beginning-of-history"))
- handle("escape", ">", filter=~has_selection)(get_by_name("end-of-history"))
-
- handle("escape", ".", filter=insert_mode)(get_by_name("yank-last-arg"))
- handle("escape", "_", filter=insert_mode)(get_by_name("yank-last-arg"))
- handle("escape", "c-y", filter=insert_mode)(get_by_name("yank-nth-arg"))
- handle("escape", "#", filter=insert_mode)(get_by_name("insert-comment"))
- handle("c-o")(get_by_name("operate-and-get-next"))
-
- # ControlQ does a quoted insert. Not that for vt100 terminals, you have to
- # disable flow control by running ``stty -ixon``, otherwise Ctrl-Q and
- # Ctrl-S are captured by the terminal.
- handle("c-q", filter=~has_selection)(get_by_name("quoted-insert"))
-
- handle("c-x", "(")(get_by_name("start-kbd-macro"))
- handle("c-x", ")")(get_by_name("end-kbd-macro"))
- handle("c-x", "e")(get_by_name("call-last-kbd-macro"))
-
- @handle("c-n")
- def _next(event: E) -> None:
- "Next line."
- event.current_buffer.auto_down()
-
- @handle("c-p")
- def _prev(event: E) -> None:
- "Previous line."
- event.current_buffer.auto_up(count=event.arg)
-
- def handle_digit(c: str) -> None:
- """
- Handle input of arguments.
- The first number needs to be preceded by escape.
- """
-
- @handle(c, filter=has_arg)
- @handle("escape", c)
- def _(event: E) -> None:
- event.append_to_arg_count(c)
-
- for c in "0123456789":
- handle_digit(c)
-
- @handle("escape", "-", filter=~has_arg)
- def _meta_dash(event: E) -> None:
- """"""
- if event._arg is None:
- event.append_to_arg_count("-")
-
- @handle("-", filter=Condition(lambda: get_app().key_processor.arg == "-"))
- def _dash(event: E) -> None:
- """
- When '-' is typed again, after exactly '-' has been given as an
- argument, ignore this.
- """
- event.app.key_processor.arg = "-"
-
- @Condition
- def is_returnable() -> bool:
- return get_app().current_buffer.is_returnable
-
- # Meta + Enter: always accept input.
- handle("escape", "enter", filter=insert_mode & is_returnable)(
- get_by_name("accept-line")
- )
-
- # Enter: accept input in single line mode.
- handle("enter", filter=insert_mode & is_returnable & ~is_multiline)(
- get_by_name("accept-line")
- )
-
- def character_search(buff: Buffer, char: str, count: int) -> None:
- if count < 0:
- match = buff.document.find_backwards(
- char, in_current_line=True, count=-count
- )
- else:
- match = buff.document.find(char, in_current_line=True, count=count)
-
- if match is not None:
- buff.cursor_position += match
-
- @handle("c-]", Keys.Any)
- def _goto_char(event: E) -> None:
- "When Ctl-] + a character is pressed. go to that character."
- # Also named 'character-search'
- character_search(event.current_buffer, event.data, event.arg)
-
- @handle("escape", "c-]", Keys.Any)
- def _goto_char_backwards(event: E) -> None:
- "Like Ctl-], but backwards."
- # Also named 'character-search-backward'
- character_search(event.current_buffer, event.data, -event.arg)
-
- @handle("escape", "a")
- def _prev_sentence(event: E) -> None:
- "Previous sentence."
- # TODO:
-
- @handle("escape", "e")
- def _end_of_sentence(event: E) -> None:
- "Move to end of sentence."
- # TODO:
-
- @handle("escape", "t", filter=insert_mode)
- def _swap_characters(event: E) -> None:
- """
- Swap the last two words before the cursor.
- """
- # TODO
-
- @handle("escape", "*", filter=insert_mode)
- def _insert_all_completions(event: E) -> None:
- """
- `meta-*`: Insert all possible completions of the preceding text.
- """
- buff = event.current_buffer
-
- # List all completions.
- complete_event = CompleteEvent(text_inserted=False, completion_requested=True)
- completions = list(
- buff.completer.get_completions(buff.document, complete_event)
- )
-
- # Insert them.
- text_to_insert = " ".join(c.text for c in completions)
- buff.insert_text(text_to_insert)
-
- @handle("c-x", "c-x")
- def _toggle_start_end(event: E) -> None:
- """
- Move cursor back and forth between the start and end of the current
- line.
- """
- buffer = event.current_buffer
-
- if buffer.document.is_cursor_at_the_end_of_line:
- buffer.cursor_position += buffer.document.get_start_of_line_position(
- after_whitespace=False
- )
- else:
- buffer.cursor_position += buffer.document.get_end_of_line_position()
-
- @handle("c-@") # Control-space or Control-@
- def _start_selection(event: E) -> None:
- """
- Start of the selection (if the current buffer is not empty).
- """
- # Take the current cursor position as the start of this selection.
- buff = event.current_buffer
- if buff.text:
- buff.start_selection(selection_type=SelectionType.CHARACTERS)
-
- @handle("c-g", filter=~has_selection)
- def _cancel(event: E) -> None:
- """
- Control + G: Cancel completion menu and validation state.
- """
- event.current_buffer.complete_state = None
- event.current_buffer.validation_error = None
-
- @handle("c-g", filter=has_selection)
- def _cancel_selection(event: E) -> None:
- """
- Cancel selection.
- """
- event.current_buffer.exit_selection()
-
- @handle("c-w", filter=has_selection)
- @handle("c-x", "r", "k", filter=has_selection)
- def _cut(event: E) -> None:
- """
- Cut selected text.
- """
- data = event.current_buffer.cut_selection()
- event.app.clipboard.set_data(data)
-
- @handle("escape", "w", filter=has_selection)
- def _copy(event: E) -> None:
- """
- Copy selected text.
- """
- data = event.current_buffer.copy_selection()
- event.app.clipboard.set_data(data)
-
- @handle("escape", "left")
- def _start_of_word(event: E) -> None:
- """
- Cursor to start of previous word.
- """
- buffer = event.current_buffer
- buffer.cursor_position += (
- buffer.document.find_previous_word_beginning(count=event.arg) or 0
- )
-
- @handle("escape", "right")
- def _start_next_word(event: E) -> None:
- """
- Cursor to start of next word.
- """
- buffer = event.current_buffer
- buffer.cursor_position += (
- buffer.document.find_next_word_beginning(count=event.arg)
- or buffer.document.get_end_of_document_position()
- )
-
- @handle("escape", "/", filter=insert_mode)
- def _complete(event: E) -> None:
- """
- M-/: Complete.
- """
- b = event.current_buffer
- if b.complete_state:
- b.complete_next()
- else:
- b.start_completion(select_first=True)
-
- @handle("c-c", ">", filter=has_selection)
- def _indent(event: E) -> None:
- """
- Indent selected text.
- """
- buffer = event.current_buffer
-
- buffer.cursor_position += buffer.document.get_start_of_line_position(
- after_whitespace=True
- )
-
- from_, to = buffer.document.selection_range()
- from_, _ = buffer.document.translate_index_to_position(from_)
- to, _ = buffer.document.translate_index_to_position(to)
-
- indent(buffer, from_, to + 1, count=event.arg)
-
- @handle("c-c", "<", filter=has_selection)
- def _unindent(event: E) -> None:
- """
- Unindent selected text.
- """
- buffer = event.current_buffer
-
- from_, to = buffer.document.selection_range()
- from_, _ = buffer.document.translate_index_to_position(from_)
- to, _ = buffer.document.translate_index_to_position(to)
-
- unindent(buffer, from_, to + 1, count=event.arg)
-
- return ConditionalKeyBindings(key_bindings, emacs_mode)
-
-
-def load_emacs_search_bindings() -> KeyBindingsBase:
- key_bindings = KeyBindings()
- handle = key_bindings.add
- from . import search
-
- # NOTE: We don't bind 'Escape' to 'abort_search'. The reason is that we
- # want Alt+Enter to accept input directly in incremental search mode.
- # Instead, we have double escape.
-
- handle("c-r")(search.start_reverse_incremental_search)
- handle("c-s")(search.start_forward_incremental_search)
-
- handle("c-c")(search.abort_search)
- handle("c-g")(search.abort_search)
- handle("c-r")(search.reverse_incremental_search)
- handle("c-s")(search.forward_incremental_search)
- handle("up")(search.reverse_incremental_search)
- handle("down")(search.forward_incremental_search)
- handle("enter")(search.accept_search)
-
- # Handling of escape.
- handle("escape", eager=True)(search.accept_search)
-
- # Like Readline, it's more natural to accept the search when escape has
- # been pressed, however instead the following two bindings could be used
- # instead.
- # #handle('escape', 'escape', eager=True)(search.abort_search)
- # #handle('escape', 'enter', eager=True)(search.accept_search_and_accept_input)
-
- # If Read-only: also include the following key bindings:
-
- # '/' and '?' key bindings for searching, just like Vi mode.
- handle("?", filter=is_read_only & ~vi_search_direction_reversed)(
- search.start_reverse_incremental_search
- )
- handle("/", filter=is_read_only & ~vi_search_direction_reversed)(
- search.start_forward_incremental_search
- )
- handle("?", filter=is_read_only & vi_search_direction_reversed)(
- search.start_forward_incremental_search
- )
- handle("/", filter=is_read_only & vi_search_direction_reversed)(
- search.start_reverse_incremental_search
- )
-
- @handle("n", filter=is_read_only)
- def _jump_next(event: E) -> None:
- "Jump to next match."
- event.current_buffer.apply_search(
- event.app.current_search_state,
- include_current_position=False,
- count=event.arg,
- )
-
- @handle("N", filter=is_read_only)
- def _jump_prev(event: E) -> None:
- "Jump to previous match."
- event.current_buffer.apply_search(
- ~event.app.current_search_state,
- include_current_position=False,
- count=event.arg,
- )
-
- return ConditionalKeyBindings(key_bindings, emacs_mode)
-
-
-def load_emacs_shift_selection_bindings() -> KeyBindingsBase:
- """
- Bindings to select text with shift + cursor movements
- """
-
- key_bindings = KeyBindings()
- handle = key_bindings.add
-
- def unshift_move(event: E) -> None:
- """
- Used for the shift selection mode. When called with
- a shift + movement key press event, moves the cursor
- as if shift is not pressed.
- """
- key = event.key_sequence[0].key
-
- if key == Keys.ShiftUp:
- event.current_buffer.auto_up(count=event.arg)
- return
- if key == Keys.ShiftDown:
- event.current_buffer.auto_down(count=event.arg)
- return
-
- # the other keys are handled through their readline command
- key_to_command: Dict[Union[Keys, str], str] = {
- Keys.ShiftLeft: "backward-char",
- Keys.ShiftRight: "forward-char",
- Keys.ShiftHome: "beginning-of-line",
- Keys.ShiftEnd: "end-of-line",
- Keys.ControlShiftLeft: "backward-word",
- Keys.ControlShiftRight: "forward-word",
- Keys.ControlShiftHome: "beginning-of-buffer",
- Keys.ControlShiftEnd: "end-of-buffer",
- }
-
- try:
- # Both the dict lookup and `get_by_name` can raise KeyError.
- binding = get_by_name(key_to_command[key])
- except KeyError:
- pass
- else: # (`else` is not really needed here.)
- if isinstance(binding, Binding):
- # (It should always be a binding here)
- binding.call(event)
-
- @handle("s-left", filter=~has_selection)
- @handle("s-right", filter=~has_selection)
- @handle("s-up", filter=~has_selection)
- @handle("s-down", filter=~has_selection)
- @handle("s-home", filter=~has_selection)
- @handle("s-end", filter=~has_selection)
- @handle("c-s-left", filter=~has_selection)
- @handle("c-s-right", filter=~has_selection)
- @handle("c-s-home", filter=~has_selection)
- @handle("c-s-end", filter=~has_selection)
- def _start_selection(event: E) -> None:
- """
- Start selection with shift + movement.
- """
- # Take the current cursor position as the start of this selection.
- buff = event.current_buffer
- if buff.text:
- buff.start_selection(selection_type=SelectionType.CHARACTERS)
-
- if buff.selection_state is not None:
- # (`selection_state` should never be `None`, it is created by
- # `start_selection`.)
- buff.selection_state.enter_shift_mode()
-
- # Then move the cursor
- original_position = buff.cursor_position
- unshift_move(event)
- if buff.cursor_position == original_position:
- # Cursor didn't actually move - so cancel selection
- # to avoid having an empty selection
- buff.exit_selection()
-
- @handle("s-left", filter=shift_selection_mode)
- @handle("s-right", filter=shift_selection_mode)
- @handle("s-up", filter=shift_selection_mode)
- @handle("s-down", filter=shift_selection_mode)
- @handle("s-home", filter=shift_selection_mode)
- @handle("s-end", filter=shift_selection_mode)
- @handle("c-s-left", filter=shift_selection_mode)
- @handle("c-s-right", filter=shift_selection_mode)
- @handle("c-s-home", filter=shift_selection_mode)
- @handle("c-s-end", filter=shift_selection_mode)
- def _extend_selection(event: E) -> None:
- """
- Extend the selection
- """
- # Just move the cursor, like shift was not pressed
- unshift_move(event)
- buff = event.current_buffer
-
- if buff.selection_state is not None:
- if buff.cursor_position == buff.selection_state.original_cursor_position:
- # selection is now empty, so cancel selection
- buff.exit_selection()
-
- @handle(Keys.Any, filter=shift_selection_mode)
- def _replace_selection(event: E) -> None:
- """
- Replace selection by what is typed
- """
- event.current_buffer.cut_selection()
- get_by_name("self-insert").call(event)
-
- @handle("enter", filter=shift_selection_mode & is_multiline)
- def _newline(event: E) -> None:
- """
- A newline replaces the selection
- """
- event.current_buffer.cut_selection()
- event.current_buffer.newline(copy_margin=not in_paste_mode())
-
- @handle("backspace", filter=shift_selection_mode)
- def _delete(event: E) -> None:
- """
- Delete selection.
- """
- event.current_buffer.cut_selection()
-
- @handle("c-y", filter=shift_selection_mode)
- def _yank(event: E) -> None:
- """
- In shift selection mode, yanking (pasting) replace the selection.
- """
- buff = event.current_buffer
- if buff.selection_state:
- buff.cut_selection()
- get_by_name("yank").call(event)
-
- # moving the cursor in shift selection mode cancels the selection
- @handle("left", filter=shift_selection_mode)
- @handle("right", filter=shift_selection_mode)
- @handle("up", filter=shift_selection_mode)
- @handle("down", filter=shift_selection_mode)
- @handle("home", filter=shift_selection_mode)
- @handle("end", filter=shift_selection_mode)
- @handle("c-left", filter=shift_selection_mode)
- @handle("c-right", filter=shift_selection_mode)
- @handle("c-home", filter=shift_selection_mode)
- @handle("c-end", filter=shift_selection_mode)
- def _cancel(event: E) -> None:
- """
- Cancel selection.
- """
- event.current_buffer.exit_selection()
- # we then process the cursor movement
- key_press = event.key_sequence[0]
- event.key_processor.feed(key_press, first=True)
-
- return ConditionalKeyBindings(key_bindings, emacs_mode)
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/focus.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/focus.py
deleted file mode 100644
index 40844db641c..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/focus.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from prompt_toolkit.key_binding.key_processor import KeyPressEvent
-
-__all__ = [
- "focus_next",
- "focus_previous",
-]
-
-E = KeyPressEvent
-
-
-def focus_next(event: E) -> None:
- """
- Focus the next visible Window.
- (Often bound to the `Tab` key.)
- """
- event.app.layout.focus_next()
-
-
-def focus_previous(event: E) -> None:
- """
- Focus the previous visible Window.
- (Often bound to the `BackTab` key.)
- """
- event.app.layout.focus_previous()
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/mouse.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/mouse.py
deleted file mode 100644
index 916cd41132f..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/mouse.py
+++ /dev/null
@@ -1,347 +0,0 @@
-import sys
-from typing import TYPE_CHECKING, FrozenSet
-
-from prompt_toolkit.data_structures import Point
-from prompt_toolkit.key_binding.key_processor import KeyPress, KeyPressEvent
-from prompt_toolkit.keys import Keys
-from prompt_toolkit.mouse_events import (
- MouseButton,
- MouseEvent,
- MouseEventType,
- MouseModifier,
-)
-
-from ..key_bindings import KeyBindings
-
-if TYPE_CHECKING:
- from prompt_toolkit.key_binding.key_bindings import NotImplementedOrNone
-
-__all__ = [
- "load_mouse_bindings",
-]
-
-E = KeyPressEvent
-
-# fmt: off
-# flake8: noqa E201
-SCROLL_UP = MouseEventType.SCROLL_UP
-SCROLL_DOWN = MouseEventType.SCROLL_DOWN
-MOUSE_DOWN = MouseEventType.MOUSE_DOWN
-MOUSE_MOVE = MouseEventType.MOUSE_MOVE
-MOUSE_UP = MouseEventType.MOUSE_UP
-
-NO_MODIFIER : FrozenSet[MouseModifier] = frozenset()
-SHIFT : FrozenSet[MouseModifier] = frozenset({MouseModifier.SHIFT})
-ALT : FrozenSet[MouseModifier] = frozenset({MouseModifier.ALT})
-SHIFT_ALT : FrozenSet[MouseModifier] = frozenset({MouseModifier.SHIFT, MouseModifier.ALT})
-CONTROL : FrozenSet[MouseModifier] = frozenset({MouseModifier.CONTROL})
-SHIFT_CONTROL : FrozenSet[MouseModifier] = frozenset({MouseModifier.SHIFT, MouseModifier.CONTROL})
-ALT_CONTROL : FrozenSet[MouseModifier] = frozenset({MouseModifier.ALT, MouseModifier.CONTROL})
-SHIFT_ALT_CONTROL: FrozenSet[MouseModifier] = frozenset({MouseModifier.SHIFT, MouseModifier.ALT, MouseModifier.CONTROL})
-UNKNOWN_MODIFIER : FrozenSet[MouseModifier] = frozenset()
-
-LEFT = MouseButton.LEFT
-MIDDLE = MouseButton.MIDDLE
-RIGHT = MouseButton.RIGHT
-NO_BUTTON = MouseButton.NONE
-UNKNOWN_BUTTON = MouseButton.UNKNOWN
-
-xterm_sgr_mouse_events = {
- ( 0, 'm') : (LEFT, MOUSE_UP, NO_MODIFIER), # left_up 0+ + + =0
- ( 4, 'm') : (LEFT, MOUSE_UP, SHIFT), # left_up Shift 0+4+ + =4
- ( 8, 'm') : (LEFT, MOUSE_UP, ALT), # left_up Alt 0+ +8+ =8
- (12, 'm') : (LEFT, MOUSE_UP, SHIFT_ALT), # left_up Shift Alt 0+4+8+ =12
- (16, 'm') : (LEFT, MOUSE_UP, CONTROL), # left_up Control 0+ + +16=16
- (20, 'm') : (LEFT, MOUSE_UP, SHIFT_CONTROL), # left_up Shift Control 0+4+ +16=20
- (24, 'm') : (LEFT, MOUSE_UP, ALT_CONTROL), # left_up Alt Control 0+ +8+16=24
- (28, 'm') : (LEFT, MOUSE_UP, SHIFT_ALT_CONTROL), # left_up Shift Alt Control 0+4+8+16=28
-
- ( 1, 'm') : (MIDDLE, MOUSE_UP, NO_MODIFIER), # middle_up 1+ + + =1
- ( 5, 'm') : (MIDDLE, MOUSE_UP, SHIFT), # middle_up Shift 1+4+ + =5
- ( 9, 'm') : (MIDDLE, MOUSE_UP, ALT), # middle_up Alt 1+ +8+ =9
- (13, 'm') : (MIDDLE, MOUSE_UP, SHIFT_ALT), # middle_up Shift Alt 1+4+8+ =13
- (17, 'm') : (MIDDLE, MOUSE_UP, CONTROL), # middle_up Control 1+ + +16=17
- (21, 'm') : (MIDDLE, MOUSE_UP, SHIFT_CONTROL), # middle_up Shift Control 1+4+ +16=21
- (25, 'm') : (MIDDLE, MOUSE_UP, ALT_CONTROL), # middle_up Alt Control 1+ +8+16=25
- (29, 'm') : (MIDDLE, MOUSE_UP, SHIFT_ALT_CONTROL), # middle_up Shift Alt Control 1+4+8+16=29
-
- ( 2, 'm') : (RIGHT, MOUSE_UP, NO_MODIFIER), # right_up 2+ + + =2
- ( 6, 'm') : (RIGHT, MOUSE_UP, SHIFT), # right_up Shift 2+4+ + =6
- (10, 'm') : (RIGHT, MOUSE_UP, ALT), # right_up Alt 2+ +8+ =10
- (14, 'm') : (RIGHT, MOUSE_UP, SHIFT_ALT), # right_up Shift Alt 2+4+8+ =14
- (18, 'm') : (RIGHT, MOUSE_UP, CONTROL), # right_up Control 2+ + +16=18
- (22, 'm') : (RIGHT, MOUSE_UP, SHIFT_CONTROL), # right_up Shift Control 2+4+ +16=22
- (26, 'm') : (RIGHT, MOUSE_UP, ALT_CONTROL), # right_up Alt Control 2+ +8+16=26
- (30, 'm') : (RIGHT, MOUSE_UP, SHIFT_ALT_CONTROL), # right_up Shift Alt Control 2+4+8+16=30
-
- ( 0, 'M') : (LEFT, MOUSE_DOWN, NO_MODIFIER), # left_down 0+ + + =0
- ( 4, 'M') : (LEFT, MOUSE_DOWN, SHIFT), # left_down Shift 0+4+ + =4
- ( 8, 'M') : (LEFT, MOUSE_DOWN, ALT), # left_down Alt 0+ +8+ =8
- (12, 'M') : (LEFT, MOUSE_DOWN, SHIFT_ALT), # left_down Shift Alt 0+4+8+ =12
- (16, 'M') : (LEFT, MOUSE_DOWN, CONTROL), # left_down Control 0+ + +16=16
- (20, 'M') : (LEFT, MOUSE_DOWN, SHIFT_CONTROL), # left_down Shift Control 0+4+ +16=20
- (24, 'M') : (LEFT, MOUSE_DOWN, ALT_CONTROL), # left_down Alt Control 0+ +8+16=24
- (28, 'M') : (LEFT, MOUSE_DOWN, SHIFT_ALT_CONTROL), # left_down Shift Alt Control 0+4+8+16=28
-
- ( 1, 'M') : (MIDDLE, MOUSE_DOWN, NO_MODIFIER), # middle_down 1+ + + =1
- ( 5, 'M') : (MIDDLE, MOUSE_DOWN, SHIFT), # middle_down Shift 1+4+ + =5
- ( 9, 'M') : (MIDDLE, MOUSE_DOWN, ALT), # middle_down Alt 1+ +8+ =9
- (13, 'M') : (MIDDLE, MOUSE_DOWN, SHIFT_ALT), # middle_down Shift Alt 1+4+8+ =13
- (17, 'M') : (MIDDLE, MOUSE_DOWN, CONTROL), # middle_down Control 1+ + +16=17
- (21, 'M') : (MIDDLE, MOUSE_DOWN, SHIFT_CONTROL), # middle_down Shift Control 1+4+ +16=21
- (25, 'M') : (MIDDLE, MOUSE_DOWN, ALT_CONTROL), # middle_down Alt Control 1+ +8+16=25
- (29, 'M') : (MIDDLE, MOUSE_DOWN, SHIFT_ALT_CONTROL), # middle_down Shift Alt Control 1+4+8+16=29
-
- ( 2, 'M') : (RIGHT, MOUSE_DOWN, NO_MODIFIER), # right_down 2+ + + =2
- ( 6, 'M') : (RIGHT, MOUSE_DOWN, SHIFT), # right_down Shift 2+4+ + =6
- (10, 'M') : (RIGHT, MOUSE_DOWN, ALT), # right_down Alt 2+ +8+ =10
- (14, 'M') : (RIGHT, MOUSE_DOWN, SHIFT_ALT), # right_down Shift Alt 2+4+8+ =14
- (18, 'M') : (RIGHT, MOUSE_DOWN, CONTROL), # right_down Control 2+ + +16=18
- (22, 'M') : (RIGHT, MOUSE_DOWN, SHIFT_CONTROL), # right_down Shift Control 2+4+ +16=22
- (26, 'M') : (RIGHT, MOUSE_DOWN, ALT_CONTROL), # right_down Alt Control 2+ +8+16=26
- (30, 'M') : (RIGHT, MOUSE_DOWN, SHIFT_ALT_CONTROL), # right_down Shift Alt Control 2+4+8+16=30
-
- (32, 'M') : (LEFT, MOUSE_MOVE, NO_MODIFIER), # left_drag 32+ + + =32
- (36, 'M') : (LEFT, MOUSE_MOVE, SHIFT), # left_drag Shift 32+4+ + =36
- (40, 'M') : (LEFT, MOUSE_MOVE, ALT), # left_drag Alt 32+ +8+ =40
- (44, 'M') : (LEFT, MOUSE_MOVE, SHIFT_ALT), # left_drag Shift Alt 32+4+8+ =44
- (48, 'M') : (LEFT, MOUSE_MOVE, CONTROL), # left_drag Control 32+ + +16=48
- (52, 'M') : (LEFT, MOUSE_MOVE, SHIFT_CONTROL), # left_drag Shift Control 32+4+ +16=52
- (56, 'M') : (LEFT, MOUSE_MOVE, ALT_CONTROL), # left_drag Alt Control 32+ +8+16=56
- (60, 'M') : (LEFT, MOUSE_MOVE, SHIFT_ALT_CONTROL), # left_drag Shift Alt Control 32+4+8+16=60
-
- (33, 'M') : (MIDDLE, MOUSE_MOVE, NO_MODIFIER), # middle_drag 33+ + + =33
- (37, 'M') : (MIDDLE, MOUSE_MOVE, SHIFT), # middle_drag Shift 33+4+ + =37
- (41, 'M') : (MIDDLE, MOUSE_MOVE, ALT), # middle_drag Alt 33+ +8+ =41
- (45, 'M') : (MIDDLE, MOUSE_MOVE, SHIFT_ALT), # middle_drag Shift Alt 33+4+8+ =45
- (49, 'M') : (MIDDLE, MOUSE_MOVE, CONTROL), # middle_drag Control 33+ + +16=49
- (53, 'M') : (MIDDLE, MOUSE_MOVE, SHIFT_CONTROL), # middle_drag Shift Control 33+4+ +16=53
- (57, 'M') : (MIDDLE, MOUSE_MOVE, ALT_CONTROL), # middle_drag Alt Control 33+ +8+16=57
- (61, 'M') : (MIDDLE, MOUSE_MOVE, SHIFT_ALT_CONTROL), # middle_drag Shift Alt Control 33+4+8+16=61
-
- (34, 'M') : (RIGHT, MOUSE_MOVE, NO_MODIFIER), # right_drag 34+ + + =34
- (38, 'M') : (RIGHT, MOUSE_MOVE, SHIFT), # right_drag Shift 34+4+ + =38
- (42, 'M') : (RIGHT, MOUSE_MOVE, ALT), # right_drag Alt 34+ +8+ =42
- (46, 'M') : (RIGHT, MOUSE_MOVE, SHIFT_ALT), # right_drag Shift Alt 34+4+8+ =46
- (50, 'M') : (RIGHT, MOUSE_MOVE, CONTROL), # right_drag Control 34+ + +16=50
- (54, 'M') : (RIGHT, MOUSE_MOVE, SHIFT_CONTROL), # right_drag Shift Control 34+4+ +16=54
- (58, 'M') : (RIGHT, MOUSE_MOVE, ALT_CONTROL), # right_drag Alt Control 34+ +8+16=58
- (62, 'M') : (RIGHT, MOUSE_MOVE, SHIFT_ALT_CONTROL), # right_drag Shift Alt Control 34+4+8+16=62
-
- (35, 'M') : (NO_BUTTON, MOUSE_MOVE, NO_MODIFIER), # none_drag 35+ + + =35
- (39, 'M') : (NO_BUTTON, MOUSE_MOVE, SHIFT), # none_drag Shift 35+4+ + =39
- (43, 'M') : (NO_BUTTON, MOUSE_MOVE, ALT), # none_drag Alt 35+ +8+ =43
- (47, 'M') : (NO_BUTTON, MOUSE_MOVE, SHIFT_ALT), # none_drag Shift Alt 35+4+8+ =47
- (51, 'M') : (NO_BUTTON, MOUSE_MOVE, CONTROL), # none_drag Control 35+ + +16=51
- (55, 'M') : (NO_BUTTON, MOUSE_MOVE, SHIFT_CONTROL), # none_drag Shift Control 35+4+ +16=55
- (59, 'M') : (NO_BUTTON, MOUSE_MOVE, ALT_CONTROL), # none_drag Alt Control 35+ +8+16=59
- (63, 'M') : (NO_BUTTON, MOUSE_MOVE, SHIFT_ALT_CONTROL), # none_drag Shift Alt Control 35+4+8+16=63
-
- (64, 'M') : (NO_BUTTON, SCROLL_UP, NO_MODIFIER), # scroll_up 64+ + + =64
- (68, 'M') : (NO_BUTTON, SCROLL_UP, SHIFT), # scroll_up Shift 64+4+ + =68
- (72, 'M') : (NO_BUTTON, SCROLL_UP, ALT), # scroll_up Alt 64+ +8+ =72
- (76, 'M') : (NO_BUTTON, SCROLL_UP, SHIFT_ALT), # scroll_up Shift Alt 64+4+8+ =76
- (80, 'M') : (NO_BUTTON, SCROLL_UP, CONTROL), # scroll_up Control 64+ + +16=80
- (84, 'M') : (NO_BUTTON, SCROLL_UP, SHIFT_CONTROL), # scroll_up Shift Control 64+4+ +16=84
- (88, 'M') : (NO_BUTTON, SCROLL_UP, ALT_CONTROL), # scroll_up Alt Control 64+ +8+16=88
- (92, 'M') : (NO_BUTTON, SCROLL_UP, SHIFT_ALT_CONTROL), # scroll_up Shift Alt Control 64+4+8+16=92
-
- (65, 'M') : (NO_BUTTON, SCROLL_DOWN, NO_MODIFIER), # scroll_down 64+ + + =65
- (69, 'M') : (NO_BUTTON, SCROLL_DOWN, SHIFT), # scroll_down Shift 64+4+ + =69
- (73, 'M') : (NO_BUTTON, SCROLL_DOWN, ALT), # scroll_down Alt 64+ +8+ =73
- (77, 'M') : (NO_BUTTON, SCROLL_DOWN, SHIFT_ALT), # scroll_down Shift Alt 64+4+8+ =77
- (81, 'M') : (NO_BUTTON, SCROLL_DOWN, CONTROL), # scroll_down Control 64+ + +16=81
- (85, 'M') : (NO_BUTTON, SCROLL_DOWN, SHIFT_CONTROL), # scroll_down Shift Control 64+4+ +16=85
- (89, 'M') : (NO_BUTTON, SCROLL_DOWN, ALT_CONTROL), # scroll_down Alt Control 64+ +8+16=89
- (93, 'M') : (NO_BUTTON, SCROLL_DOWN, SHIFT_ALT_CONTROL), # scroll_down Shift Alt Control 64+4+8+16=93
-}
-
-typical_mouse_events = {
- 32: (LEFT , MOUSE_DOWN , UNKNOWN_MODIFIER),
- 33: (MIDDLE , MOUSE_DOWN , UNKNOWN_MODIFIER),
- 34: (RIGHT , MOUSE_DOWN , UNKNOWN_MODIFIER),
- 35: (UNKNOWN_BUTTON , MOUSE_UP , UNKNOWN_MODIFIER),
-
- 64: (LEFT , MOUSE_MOVE , UNKNOWN_MODIFIER),
- 65: (MIDDLE , MOUSE_MOVE , UNKNOWN_MODIFIER),
- 66: (RIGHT , MOUSE_MOVE , UNKNOWN_MODIFIER),
- 67: (NO_BUTTON , MOUSE_MOVE , UNKNOWN_MODIFIER),
-
- 96: (NO_BUTTON , SCROLL_UP , UNKNOWN_MODIFIER),
- 97: (NO_BUTTON , SCROLL_DOWN, UNKNOWN_MODIFIER),
-}
-
-urxvt_mouse_events={
- 32: (UNKNOWN_BUTTON, MOUSE_DOWN , UNKNOWN_MODIFIER),
- 35: (UNKNOWN_BUTTON, MOUSE_UP , UNKNOWN_MODIFIER),
- 96: (NO_BUTTON , SCROLL_UP , UNKNOWN_MODIFIER),
- 97: (NO_BUTTON , SCROLL_DOWN, UNKNOWN_MODIFIER),
-}
-# fmt:on
-
-
-def load_mouse_bindings() -> KeyBindings:
- """
- Key bindings, required for mouse support.
- (Mouse events enter through the key binding system.)
- """
- key_bindings = KeyBindings()
-
- @key_bindings.add(Keys.Vt100MouseEvent)
- def _(event: E) -> "NotImplementedOrNone":
- """
- Handling of incoming mouse event.
- """
- # TypicaL: "eSC[MaB*"
- # Urxvt: "Esc[96;14;13M"
- # Xterm SGR: "Esc[<64;85;12M"
-
- # Parse incoming packet.
- if event.data[2] == "M":
- # Typical.
- mouse_event, x, y = map(ord, event.data[3:])
-
- # TODO: Is it possible to add modifiers here?
- mouse_button, mouse_event_type, mouse_modifiers = typical_mouse_events[
- mouse_event
- ]
-
- # Handle situations where `PosixStdinReader` used surrogateescapes.
- if x >= 0xDC00:
- x -= 0xDC00
- if y >= 0xDC00:
- y -= 0xDC00
-
- x -= 32
- y -= 32
- else:
- # Urxvt and Xterm SGR.
- # When the '<' is not present, we are not using the Xterm SGR mode,
- # but Urxvt instead.
- data = event.data[2:]
- if data[:1] == "<":
- sgr = True
- data = data[1:]
- else:
- sgr = False
-
- # Extract coordinates.
- mouse_event, x, y = map(int, data[:-1].split(";"))
- m = data[-1]
-
- # Parse event type.
- if sgr:
- try:
- (
- mouse_button,
- mouse_event_type,
- mouse_modifiers,
- ) = xterm_sgr_mouse_events[mouse_event, m]
- except KeyError:
- return NotImplemented
-
- else:
- # Some other terminals, like urxvt, Hyper terminal, ...
- (
- mouse_button,
- mouse_event_type,
- mouse_modifiers,
- ) = urxvt_mouse_events.get(
- mouse_event, (UNKNOWN_BUTTON, MOUSE_MOVE, UNKNOWN_MODIFIER)
- )
-
- x -= 1
- y -= 1
-
- # Only handle mouse events when we know the window height.
- if event.app.renderer.height_is_known and mouse_event_type is not None:
- # Take region above the layout into account. The reported
- # coordinates are absolute to the visible part of the terminal.
- from prompt_toolkit.renderer import HeightIsUnknownError
-
- try:
- y -= event.app.renderer.rows_above_layout
- except HeightIsUnknownError:
- return NotImplemented
-
- # Call the mouse handler from the renderer.
-
- # Note: This can return `NotImplemented` if no mouse handler was
- # found for this position, or if no repainting needs to
- # happen. this way, we avoid excessive repaints during mouse
- # movements.
- handler = event.app.renderer.mouse_handlers.mouse_handlers[y][x]
- return handler(
- MouseEvent(
- position=Point(x=x, y=y),
- event_type=mouse_event_type,
- button=mouse_button,
- modifiers=mouse_modifiers,
- )
- )
-
- return NotImplemented
-
- @key_bindings.add(Keys.ScrollUp)
- def _scroll_up(event: E) -> None:
- """
- Scroll up event without cursor position.
- """
- # We don't receive a cursor position, so we don't know which window to
- # scroll. Just send an 'up' key press instead.
- event.key_processor.feed(KeyPress(Keys.Up), first=True)
-
- @key_bindings.add(Keys.ScrollDown)
- def _scroll_down(event: E) -> None:
- """
- Scroll down event without cursor position.
- """
- event.key_processor.feed(KeyPress(Keys.Down), first=True)
-
- @key_bindings.add(Keys.WindowsMouseEvent)
- def _mouse(event: E) -> "NotImplementedOrNone":
- """
- Handling of mouse events for Windows.
- """
- # This key binding should only exist for Windows.
- if sys.platform == "win32":
- # Parse data.
- pieces = event.data.split(";")
-
- button = MouseButton(pieces[0])
- event_type = MouseEventType(pieces[1])
- x = int(pieces[2])
- y = int(pieces[3])
-
- # Make coordinates absolute to the visible part of the terminal.
- output = event.app.renderer.output
-
- from prompt_toolkit.output.win32 import Win32Output
- from prompt_toolkit.output.windows10 import Windows10_Output
-
- if isinstance(output, (Win32Output, Windows10_Output)):
- screen_buffer_info = output.get_win32_screen_buffer_info()
- rows_above_cursor = (
- screen_buffer_info.dwCursorPosition.Y
- - event.app.renderer._cursor_pos.y
- )
- y -= rows_above_cursor
-
- # Call the mouse event handler.
- # (Can return `NotImplemented`.)
- handler = event.app.renderer.mouse_handlers.mouse_handlers[y][x]
-
- return handler(
- MouseEvent(
- position=Point(x=x, y=y),
- event_type=event_type,
- button=button,
- modifiers=UNKNOWN_MODIFIER,
- )
- )
-
- # No mouse handler found. Return `NotImplemented` so that we don't
- # invalidate the UI.
- return NotImplemented
-
- return key_bindings
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/named_commands.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/named_commands.py
deleted file mode 100644
index e0796ef0b8e..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/named_commands.py
+++ /dev/null
@@ -1,687 +0,0 @@
-"""
-Key bindings which are also known by GNU Readline by the given names.
-
-See: http://www.delorie.com/gnu/docs/readline/rlman_13.html
-"""
-from typing import Callable, Dict, TypeVar, Union, cast
-
-from prompt_toolkit.document import Document
-from prompt_toolkit.enums import EditingMode
-from prompt_toolkit.key_binding.key_bindings import Binding, key_binding
-from prompt_toolkit.key_binding.key_processor import KeyPress, KeyPressEvent
-from prompt_toolkit.keys import Keys
-from prompt_toolkit.layout.controls import BufferControl
-from prompt_toolkit.search import SearchDirection
-from prompt_toolkit.selection import PasteMode
-
-from .completion import display_completions_like_readline, generate_completions
-
-__all__ = [
- "get_by_name",
-]
-
-
-# Typing.
-_Handler = Callable[[KeyPressEvent], None]
-_HandlerOrBinding = Union[_Handler, Binding]
-_T = TypeVar("_T", bound=_HandlerOrBinding)
-E = KeyPressEvent
-
-
-# Registry that maps the Readline command names to their handlers.
-_readline_commands: Dict[str, Binding] = {}
-
-
-def register(name: str) -> Callable[[_T], _T]:
- """
- Store handler in the `_readline_commands` dictionary.
- """
-
- def decorator(handler: _T) -> _T:
- "`handler` is a callable or Binding."
- if isinstance(handler, Binding):
- _readline_commands[name] = handler
- else:
- _readline_commands[name] = key_binding()(cast(_Handler, handler))
-
- return handler
-
- return decorator
-
-
-def get_by_name(name: str) -> Binding:
- """
- Return the handler for the (Readline) command with the given name.
- """
- try:
- return _readline_commands[name]
- except KeyError as e:
- raise KeyError("Unknown Readline command: %r" % name) from e
-
-
-#
-# Commands for moving
-# See: http://www.delorie.com/gnu/docs/readline/rlman_14.html
-#
-
-
-@register("beginning-of-buffer")
-def beginning_of_buffer(event: E) -> None:
- """
- Move to the start of the buffer.
- """
- buff = event.current_buffer
- buff.cursor_position = 0
-
-
-@register("end-of-buffer")
-def end_of_buffer(event: E) -> None:
- """
- Move to the end of the buffer.
- """
- buff = event.current_buffer
- buff.cursor_position = len(buff.text)
-
-
-@register("beginning-of-line")
-def beginning_of_line(event: E) -> None:
- """
- Move to the start of the current line.
- """
- buff = event.current_buffer
- buff.cursor_position += buff.document.get_start_of_line_position(
- after_whitespace=False
- )
-
-
-@register("end-of-line")
-def end_of_line(event: E) -> None:
- """
- Move to the end of the line.
- """
- buff = event.current_buffer
- buff.cursor_position += buff.document.get_end_of_line_position()
-
-
-@register("forward-char")
-def forward_char(event: E) -> None:
- """
- Move forward a character.
- """
- buff = event.current_buffer
- buff.cursor_position += buff.document.get_cursor_right_position(count=event.arg)
-
-
-@register("backward-char")
-def backward_char(event: E) -> None:
- "Move back a character."
- buff = event.current_buffer
- buff.cursor_position += buff.document.get_cursor_left_position(count=event.arg)
-
-
-@register("forward-word")
-def forward_word(event: E) -> None:
- """
- Move forward to the end of the next word. Words are composed of letters and
- digits.
- """
- buff = event.current_buffer
- pos = buff.document.find_next_word_ending(count=event.arg)
-
- if pos:
- buff.cursor_position += pos
-
-
-@register("backward-word")
-def backward_word(event: E) -> None:
- """
- Move back to the start of the current or previous word. Words are composed
- of letters and digits.
- """
- buff = event.current_buffer
- pos = buff.document.find_previous_word_beginning(count=event.arg)
-
- if pos:
- buff.cursor_position += pos
-
-
-@register("clear-screen")
-def clear_screen(event: E) -> None:
- """
- Clear the screen and redraw everything at the top of the screen.
- """
- event.app.renderer.clear()
-
-
-@register("redraw-current-line")
-def redraw_current_line(event: E) -> None:
- """
- Refresh the current line.
- (Readline defines this command, but prompt-toolkit doesn't have it.)
- """
- pass
-
-
-#
-# Commands for manipulating the history.
-# See: http://www.delorie.com/gnu/docs/readline/rlman_15.html
-#
-
-
-@register("accept-line")
-def accept_line(event: E) -> None:
- """
- Accept the line regardless of where the cursor is.
- """
- event.current_buffer.validate_and_handle()
-
-
-@register("previous-history")
-def previous_history(event: E) -> None:
- """
- Move `back` through the history list, fetching the previous command.
- """
- event.current_buffer.history_backward(count=event.arg)
-
-
-@register("next-history")
-def next_history(event: E) -> None:
- """
- Move `forward` through the history list, fetching the next command.
- """
- event.current_buffer.history_forward(count=event.arg)
-
-
-@register("beginning-of-history")
-def beginning_of_history(event: E) -> None:
- """
- Move to the first line in the history.
- """
- event.current_buffer.go_to_history(0)
-
-
-@register("end-of-history")
-def end_of_history(event: E) -> None:
- """
- Move to the end of the input history, i.e., the line currently being entered.
- """
- event.current_buffer.history_forward(count=10**100)
- buff = event.current_buffer
- buff.go_to_history(len(buff._working_lines) - 1)
-
-
-@register("reverse-search-history")
-def reverse_search_history(event: E) -> None:
- """
- Search backward starting at the current line and moving `up` through
- the history as necessary. This is an incremental search.
- """
- control = event.app.layout.current_control
-
- if isinstance(control, BufferControl) and control.search_buffer_control:
- event.app.current_search_state.direction = SearchDirection.BACKWARD
- event.app.layout.current_control = control.search_buffer_control
-
-
-#
-# Commands for changing text
-#
-
-
-@register("end-of-file")
-def end_of_file(event: E) -> None:
- """
- Exit.
- """
- event.app.exit()
-
-
-@register("delete-char")
-def delete_char(event: E) -> None:
- """
- Delete character before the cursor.
- """
- deleted = event.current_buffer.delete(count=event.arg)
- if not deleted:
- event.app.output.bell()
-
-
-@register("backward-delete-char")
-def backward_delete_char(event: E) -> None:
- """
- Delete the character behind the cursor.
- """
- if event.arg < 0:
- # When a negative argument has been given, this should delete in front
- # of the cursor.
- deleted = event.current_buffer.delete(count=-event.arg)
- else:
- deleted = event.current_buffer.delete_before_cursor(count=event.arg)
-
- if not deleted:
- event.app.output.bell()
-
-
-@register("self-insert")
-def self_insert(event: E) -> None:
- """
- Insert yourself.
- """
- event.current_buffer.insert_text(event.data * event.arg)
-
-
-@register("transpose-chars")
-def transpose_chars(event: E) -> None:
- """
- Emulate Emacs transpose-char behavior: at the beginning of the buffer,
- do nothing. At the end of a line or buffer, swap the characters before
- the cursor. Otherwise, move the cursor right, and then swap the
- characters before the cursor.
- """
- b = event.current_buffer
- p = b.cursor_position
- if p == 0:
- return
- elif p == len(b.text) or b.text[p] == "\n":
- b.swap_characters_before_cursor()
- else:
- b.cursor_position += b.document.get_cursor_right_position()
- b.swap_characters_before_cursor()
-
-
-@register("uppercase-word")
-def uppercase_word(event: E) -> None:
- """
- Uppercase the current (or following) word.
- """
- buff = event.current_buffer
-
- for i in range(event.arg):
- pos = buff.document.find_next_word_ending()
- words = buff.document.text_after_cursor[:pos]
- buff.insert_text(words.upper(), overwrite=True)
-
-
-@register("downcase-word")
-def downcase_word(event: E) -> None:
- """
- Lowercase the current (or following) word.
- """
- buff = event.current_buffer
-
- for i in range(event.arg): # XXX: not DRY: see meta_c and meta_u!!
- pos = buff.document.find_next_word_ending()
- words = buff.document.text_after_cursor[:pos]
- buff.insert_text(words.lower(), overwrite=True)
-
-
-@register("capitalize-word")
-def capitalize_word(event: E) -> None:
- """
- Capitalize the current (or following) word.
- """
- buff = event.current_buffer
-
- for i in range(event.arg):
- pos = buff.document.find_next_word_ending()
- words = buff.document.text_after_cursor[:pos]
- buff.insert_text(words.title(), overwrite=True)
-
-
-@register("quoted-insert")
-def quoted_insert(event: E) -> None:
- """
- Add the next character typed to the line verbatim. This is how to insert
- key sequences like C-q, for example.
- """
- event.app.quoted_insert = True
-
-
-#
-# Killing and yanking.
-#
-
-
-@register("kill-line")
-def kill_line(event: E) -> None:
- """
- Kill the text from the cursor to the end of the line.
-
- If we are at the end of the line, this should remove the newline.
- (That way, it is possible to delete multiple lines by executing this
- command multiple times.)
- """
- buff = event.current_buffer
- if event.arg < 0:
- deleted = buff.delete_before_cursor(
- count=-buff.document.get_start_of_line_position()
- )
- else:
- if buff.document.current_char == "\n":
- deleted = buff.delete(1)
- else:
- deleted = buff.delete(count=buff.document.get_end_of_line_position())
- event.app.clipboard.set_text(deleted)
-
-
-@register("kill-word")
-def kill_word(event: E) -> None:
- """
- Kill from point to the end of the current word, or if between words, to the
- end of the next word. Word boundaries are the same as forward-word.
- """
- buff = event.current_buffer
- pos = buff.document.find_next_word_ending(count=event.arg)
-
- if pos:
- deleted = buff.delete(count=pos)
-
- if event.is_repeat:
- deleted = event.app.clipboard.get_data().text + deleted
-
- event.app.clipboard.set_text(deleted)
-
-
-@register("unix-word-rubout")
-def unix_word_rubout(event: E, WORD: bool = True) -> None:
- """
- Kill the word behind point, using whitespace as a word boundary.
- Usually bound to ControlW.
- """
- buff = event.current_buffer
- pos = buff.document.find_start_of_previous_word(count=event.arg, WORD=WORD)
-
- if pos is None:
- # Nothing found? delete until the start of the document. (The
- # input starts with whitespace and no words were found before the
- # cursor.)
- pos = -buff.cursor_position
-
- if pos:
- deleted = buff.delete_before_cursor(count=-pos)
-
- # If the previous key press was also Control-W, concatenate deleted
- # text.
- if event.is_repeat:
- deleted += event.app.clipboard.get_data().text
-
- event.app.clipboard.set_text(deleted)
- else:
- # Nothing to delete. Bell.
- event.app.output.bell()
-
-
-@register("backward-kill-word")
-def backward_kill_word(event: E) -> None:
- """
- Kills the word before point, using "not a letter nor a digit" as a word boundary.
- Usually bound to M-Del or M-Backspace.
- """
- unix_word_rubout(event, WORD=False)
-
-
-@register("delete-horizontal-space")
-def delete_horizontal_space(event: E) -> None:
- """
- Delete all spaces and tabs around point.
- """
- buff = event.current_buffer
- text_before_cursor = buff.document.text_before_cursor
- text_after_cursor = buff.document.text_after_cursor
-
- delete_before = len(text_before_cursor) - len(text_before_cursor.rstrip("\t "))
- delete_after = len(text_after_cursor) - len(text_after_cursor.lstrip("\t "))
-
- buff.delete_before_cursor(count=delete_before)
- buff.delete(count=delete_after)
-
-
-@register("unix-line-discard")
-def unix_line_discard(event: E) -> None:
- """
- Kill backward from the cursor to the beginning of the current line.
- """
- buff = event.current_buffer
-
- if buff.document.cursor_position_col == 0 and buff.document.cursor_position > 0:
- buff.delete_before_cursor(count=1)
- else:
- deleted = buff.delete_before_cursor(
- count=-buff.document.get_start_of_line_position()
- )
- event.app.clipboard.set_text(deleted)
-
-
-@register("yank")
-def yank(event: E) -> None:
- """
- Paste before cursor.
- """
- event.current_buffer.paste_clipboard_data(
- event.app.clipboard.get_data(), count=event.arg, paste_mode=PasteMode.EMACS
- )
-
-
-@register("yank-nth-arg")
-def yank_nth_arg(event: E) -> None:
- """
- Insert the first argument of the previous command. With an argument, insert
- the nth word from the previous command (start counting at 0).
- """
- n = event.arg if event.arg_present else None
- event.current_buffer.yank_nth_arg(n)
-
-
-@register("yank-last-arg")
-def yank_last_arg(event: E) -> None:
- """
- Like `yank_nth_arg`, but if no argument has been given, yank the last word
- of each line.
- """
- n = event.arg if event.arg_present else None
- event.current_buffer.yank_last_arg(n)
-
-
-@register("yank-pop")
-def yank_pop(event: E) -> None:
- """
- Rotate the kill ring, and yank the new top. Only works following yank or
- yank-pop.
- """
- buff = event.current_buffer
- doc_before_paste = buff.document_before_paste
- clipboard = event.app.clipboard
-
- if doc_before_paste is not None:
- buff.document = doc_before_paste
- clipboard.rotate()
- buff.paste_clipboard_data(clipboard.get_data(), paste_mode=PasteMode.EMACS)
-
-
-#
-# Completion.
-#
-
-
-@register("complete")
-def complete(event: E) -> None:
- """
- Attempt to perform completion.
- """
- display_completions_like_readline(event)
-
-
-@register("menu-complete")
-def menu_complete(event: E) -> None:
- """
- Generate completions, or go to the next completion. (This is the default
- way of completing input in prompt_toolkit.)
- """
- generate_completions(event)
-
-
-@register("menu-complete-backward")
-def menu_complete_backward(event: E) -> None:
- """
- Move backward through the list of possible completions.
- """
- event.current_buffer.complete_previous()
-
-
-#
-# Keyboard macros.
-#
-
-
-@register("start-kbd-macro")
-def start_kbd_macro(event: E) -> None:
- """
- Begin saving the characters typed into the current keyboard macro.
- """
- event.app.emacs_state.start_macro()
-
-
-@register("end-kbd-macro")
-def end_kbd_macro(event: E) -> None:
- """
- Stop saving the characters typed into the current keyboard macro and save
- the definition.
- """
- event.app.emacs_state.end_macro()
-
-
-@register("call-last-kbd-macro")
-@key_binding(record_in_macro=False)
-def call_last_kbd_macro(event: E) -> None:
- """
- Re-execute the last keyboard macro defined, by making the characters in the
- macro appear as if typed at the keyboard.
-
- Notice that we pass `record_in_macro=False`. This ensures that the 'c-x e'
- key sequence doesn't appear in the recording itself. This function inserts
- the body of the called macro back into the KeyProcessor, so these keys will
- be added later on to the macro of their handlers have `record_in_macro=True`.
- """
- # Insert the macro.
- macro = event.app.emacs_state.macro
-
- if macro:
- event.app.key_processor.feed_multiple(macro, first=True)
-
-
-@register("print-last-kbd-macro")
-def print_last_kbd_macro(event: E) -> None:
- """
- Print the last keyboard macro.
- """
- # TODO: Make the format suitable for the inputrc file.
- def print_macro() -> None:
- macro = event.app.emacs_state.macro
- if macro:
- for k in macro:
- print(k)
-
- from prompt_toolkit.application.run_in_terminal import run_in_terminal
-
- run_in_terminal(print_macro)
-
-
-#
-# Miscellaneous Commands.
-#
-
-
-@register("undo")
-def undo(event: E) -> None:
- """
- Incremental undo.
- """
- event.current_buffer.undo()
-
-
-@register("insert-comment")
-def insert_comment(event: E) -> None:
- """
- Without numeric argument, comment all lines.
- With numeric argument, uncomment all lines.
- In any case accept the input.
- """
- buff = event.current_buffer
-
- # Transform all lines.
- if event.arg != 1:
-
- def change(line: str) -> str:
- return line[1:] if line.startswith("#") else line
-
- else:
-
- def change(line: str) -> str:
- return "#" + line
-
- buff.document = Document(
- text="\n".join(map(change, buff.text.splitlines())), cursor_position=0
- )
-
- # Accept input.
- buff.validate_and_handle()
-
-
-@register("vi-editing-mode")
-def vi_editing_mode(event: E) -> None:
- """
- Switch to Vi editing mode.
- """
- event.app.editing_mode = EditingMode.VI
-
-
-@register("emacs-editing-mode")
-def emacs_editing_mode(event: E) -> None:
- """
- Switch to Emacs editing mode.
- """
- event.app.editing_mode = EditingMode.EMACS
-
-
-@register("prefix-meta")
-def prefix_meta(event: E) -> None:
- """
- Metafy the next character typed. This is for keyboards without a meta key.
-
- Sometimes people also want to bind other keys to Meta, e.g. 'jj'::
-
- key_bindings.add_key_binding('j', 'j', filter=ViInsertMode())(prefix_meta)
- """
- # ('first' should be true, because we want to insert it at the current
- # position in the queue.)
- event.app.key_processor.feed(KeyPress(Keys.Escape), first=True)
-
-
-@register("operate-and-get-next")
-def operate_and_get_next(event: E) -> None:
- """
- Accept the current line for execution and fetch the next line relative to
- the current line from the history for editing.
- """
- buff = event.current_buffer
- new_index = buff.working_index + 1
-
- # Accept the current input. (This will also redraw the interface in the
- # 'done' state.)
- buff.validate_and_handle()
-
- # Set the new index at the start of the next run.
- def set_working_index() -> None:
- if new_index < len(buff._working_lines):
- buff.working_index = new_index
-
- event.app.pre_run_callables.append(set_working_index)
-
-
-@register("edit-and-execute-command")
-def edit_and_execute(event: E) -> None:
- """
- Invoke an editor on the current command line, and accept the result.
- """
- buff = event.current_buffer
- buff.open_in_editor(validate_and_handle=True)
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/open_in_editor.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/open_in_editor.py
deleted file mode 100644
index f8699f4a45b..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/open_in_editor.py
+++ /dev/null
@@ -1,49 +0,0 @@
-"""
-Open in editor key bindings.
-"""
-from prompt_toolkit.filters import emacs_mode, has_selection, vi_navigation_mode
-
-from ..key_bindings import KeyBindings, KeyBindingsBase, merge_key_bindings
-from .named_commands import get_by_name
-
-__all__ = [
- "load_open_in_editor_bindings",
- "load_emacs_open_in_editor_bindings",
- "load_vi_open_in_editor_bindings",
-]
-
-
-def load_open_in_editor_bindings() -> KeyBindingsBase:
- """
- Load both the Vi and emacs key bindings for handling edit-and-execute-command.
- """
- return merge_key_bindings(
- [
- load_emacs_open_in_editor_bindings(),
- load_vi_open_in_editor_bindings(),
- ]
- )
-
-
-def load_emacs_open_in_editor_bindings() -> KeyBindings:
- """
- Pressing C-X C-E will open the buffer in an external editor.
- """
- key_bindings = KeyBindings()
-
- key_bindings.add("c-x", "c-e", filter=emacs_mode & ~has_selection)(
- get_by_name("edit-and-execute-command")
- )
-
- return key_bindings
-
-
-def load_vi_open_in_editor_bindings() -> KeyBindings:
- """
- Pressing 'v' in navigation mode will open the buffer in an external editor.
- """
- key_bindings = KeyBindings()
- key_bindings.add("v", filter=vi_navigation_mode)(
- get_by_name("edit-and-execute-command")
- )
- return key_bindings
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/page_navigation.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/page_navigation.py
deleted file mode 100644
index 4d531c04377..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/page_navigation.py
+++ /dev/null
@@ -1,82 +0,0 @@
-"""
-Key bindings for extra page navigation: bindings for up/down scrolling through
-long pages, like in Emacs or Vi.
-"""
-from prompt_toolkit.filters import buffer_has_focus, emacs_mode, vi_mode
-from prompt_toolkit.key_binding.key_bindings import (
- ConditionalKeyBindings,
- KeyBindings,
- KeyBindingsBase,
- merge_key_bindings,
-)
-
-from .scroll import (
- scroll_backward,
- scroll_forward,
- scroll_half_page_down,
- scroll_half_page_up,
- scroll_one_line_down,
- scroll_one_line_up,
- scroll_page_down,
- scroll_page_up,
-)
-
-__all__ = [
- "load_page_navigation_bindings",
- "load_emacs_page_navigation_bindings",
- "load_vi_page_navigation_bindings",
-]
-
-
-def load_page_navigation_bindings() -> KeyBindingsBase:
- """
- Load both the Vi and Emacs bindings for page navigation.
- """
- # Only enable when a `Buffer` is focused, otherwise, we would catch keys
- # when another widget is focused (like for instance `c-d` in a
- # ptterm.Terminal).
- return ConditionalKeyBindings(
- merge_key_bindings(
- [
- load_emacs_page_navigation_bindings(),
- load_vi_page_navigation_bindings(),
- ]
- ),
- buffer_has_focus,
- )
-
-
-def load_emacs_page_navigation_bindings() -> KeyBindingsBase:
- """
- Key bindings, for scrolling up and down through pages.
- This are separate bindings, because GNU readline doesn't have them.
- """
- key_bindings = KeyBindings()
- handle = key_bindings.add
-
- handle("c-v")(scroll_page_down)
- handle("pagedown")(scroll_page_down)
- handle("escape", "v")(scroll_page_up)
- handle("pageup")(scroll_page_up)
-
- return ConditionalKeyBindings(key_bindings, emacs_mode)
-
-
-def load_vi_page_navigation_bindings() -> KeyBindingsBase:
- """
- Key bindings, for scrolling up and down through pages.
- This are separate bindings, because GNU readline doesn't have them.
- """
- key_bindings = KeyBindings()
- handle = key_bindings.add
-
- handle("c-f")(scroll_forward)
- handle("c-b")(scroll_backward)
- handle("c-d")(scroll_half_page_down)
- handle("c-u")(scroll_half_page_up)
- handle("c-e")(scroll_one_line_down)
- handle("c-y")(scroll_one_line_up)
- handle("pagedown")(scroll_page_down)
- handle("pageup")(scroll_page_up)
-
- return ConditionalKeyBindings(key_bindings, vi_mode)
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/scroll.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/scroll.py
deleted file mode 100644
index 4a43ff585ac..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/scroll.py
+++ /dev/null
@@ -1,187 +0,0 @@
-"""
-Key bindings, for scrolling up and down through pages.
-
-This are separate bindings, because GNU readline doesn't have them, but
-they are very useful for navigating through long multiline buffers, like in
-Vi, Emacs, etc...
-"""
-from prompt_toolkit.key_binding.key_processor import KeyPressEvent
-
-__all__ = [
- "scroll_forward",
- "scroll_backward",
- "scroll_half_page_up",
- "scroll_half_page_down",
- "scroll_one_line_up",
- "scroll_one_line_down",
-]
-
-E = KeyPressEvent
-
-
-def scroll_forward(event: E, half: bool = False) -> None:
- """
- Scroll window down.
- """
- w = event.app.layout.current_window
- b = event.app.current_buffer
-
- if w and w.render_info:
- info = w.render_info
- ui_content = info.ui_content
-
- # Height to scroll.
- scroll_height = info.window_height
- if half:
- scroll_height //= 2
-
- # Calculate how many lines is equivalent to that vertical space.
- y = b.document.cursor_position_row + 1
- height = 0
- while y < ui_content.line_count:
- line_height = info.get_height_for_line(y)
-
- if height + line_height < scroll_height:
- height += line_height
- y += 1
- else:
- break
-
- b.cursor_position = b.document.translate_row_col_to_index(y, 0)
-
-
-def scroll_backward(event: E, half: bool = False) -> None:
- """
- Scroll window up.
- """
- w = event.app.layout.current_window
- b = event.app.current_buffer
-
- if w and w.render_info:
- info = w.render_info
-
- # Height to scroll.
- scroll_height = info.window_height
- if half:
- scroll_height //= 2
-
- # Calculate how many lines is equivalent to that vertical space.
- y = max(0, b.document.cursor_position_row - 1)
- height = 0
- while y > 0:
- line_height = info.get_height_for_line(y)
-
- if height + line_height < scroll_height:
- height += line_height
- y -= 1
- else:
- break
-
- b.cursor_position = b.document.translate_row_col_to_index(y, 0)
-
-
-def scroll_half_page_down(event: E) -> None:
- """
- Same as ControlF, but only scroll half a page.
- """
- scroll_forward(event, half=True)
-
-
-def scroll_half_page_up(event: E) -> None:
- """
- Same as ControlB, but only scroll half a page.
- """
- scroll_backward(event, half=True)
-
-
-def scroll_one_line_down(event: E) -> None:
- """
- scroll_offset += 1
- """
- w = event.app.layout.current_window
- b = event.app.current_buffer
-
- if w:
- # When the cursor is at the top, move to the next line. (Otherwise, only scroll.)
- if w.render_info:
- info = w.render_info
-
- if w.vertical_scroll < info.content_height - info.window_height:
- if info.cursor_position.y <= info.configured_scroll_offsets.top:
- b.cursor_position += b.document.get_cursor_down_position()
-
- w.vertical_scroll += 1
-
-
-def scroll_one_line_up(event: E) -> None:
- """
- scroll_offset -= 1
- """
- w = event.app.layout.current_window
- b = event.app.current_buffer
-
- if w:
- # When the cursor is at the bottom, move to the previous line. (Otherwise, only scroll.)
- if w.render_info:
- info = w.render_info
-
- if w.vertical_scroll > 0:
- first_line_height = info.get_height_for_line(info.first_visible_line())
-
- cursor_up = info.cursor_position.y - (
- info.window_height
- - 1
- - first_line_height
- - info.configured_scroll_offsets.bottom
- )
-
- # Move cursor up, as many steps as the height of the first line.
- # TODO: not entirely correct yet, in case of line wrapping and many long lines.
- for _ in range(max(0, cursor_up)):
- b.cursor_position += b.document.get_cursor_up_position()
-
- # Scroll window
- w.vertical_scroll -= 1
-
-
-def scroll_page_down(event: E) -> None:
- """
- Scroll page down. (Prefer the cursor at the top of the page, after scrolling.)
- """
- w = event.app.layout.current_window
- b = event.app.current_buffer
-
- if w and w.render_info:
- # Scroll down one page.
- line_index = max(w.render_info.last_visible_line(), w.vertical_scroll + 1)
- w.vertical_scroll = line_index
-
- b.cursor_position = b.document.translate_row_col_to_index(line_index, 0)
- b.cursor_position += b.document.get_start_of_line_position(
- after_whitespace=True
- )
-
-
-def scroll_page_up(event: E) -> None:
- """
- Scroll page up. (Prefer the cursor at the bottom of the page, after scrolling.)
- """
- w = event.app.layout.current_window
- b = event.app.current_buffer
-
- if w and w.render_info:
- # Put cursor at the first visible line. (But make sure that the cursor
- # moves at least one line up.)
- line_index = max(
- 0,
- min(w.render_info.first_visible_line(), b.document.cursor_position_row - 1),
- )
-
- b.cursor_position = b.document.translate_row_col_to_index(line_index, 0)
- b.cursor_position += b.document.get_start_of_line_position(
- after_whitespace=True
- )
-
- # Set the scroll offset. We can safely set it to zero; the Window will
- # make sure that it scrolls at least until the cursor becomes visible.
- w.vertical_scroll = 0
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/search.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/search.py
deleted file mode 100644
index 06a047e4cd1..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/search.py
+++ /dev/null
@@ -1,93 +0,0 @@
-"""
-Search related key bindings.
-"""
-from prompt_toolkit import search
-from prompt_toolkit.application.current import get_app
-from prompt_toolkit.filters import Condition, control_is_searchable, is_searching
-from prompt_toolkit.key_binding.key_processor import KeyPressEvent
-
-from ..key_bindings import key_binding
-
-__all__ = [
- "abort_search",
- "accept_search",
- "start_reverse_incremental_search",
- "start_forward_incremental_search",
- "reverse_incremental_search",
- "forward_incremental_search",
- "accept_search_and_accept_input",
-]
-
-E = KeyPressEvent
-
-
-@key_binding(filter=is_searching)
-def abort_search(event: E) -> None:
- """
- Abort an incremental search and restore the original
- line.
- (Usually bound to ControlG/ControlC.)
- """
- search.stop_search()
-
-
-@key_binding(filter=is_searching)
-def accept_search(event: E) -> None:
- """
- When enter pressed in isearch, quit isearch mode. (Multiline
- isearch would be too complicated.)
- (Usually bound to Enter.)
- """
- search.accept_search()
-
-
-@key_binding(filter=control_is_searchable)
-def start_reverse_incremental_search(event: E) -> None:
- """
- Enter reverse incremental search.
- (Usually ControlR.)
- """
- search.start_search(direction=search.SearchDirection.BACKWARD)
-
-
-@key_binding(filter=control_is_searchable)
-def start_forward_incremental_search(event: E) -> None:
- """
- Enter forward incremental search.
- (Usually ControlS.)
- """
- search.start_search(direction=search.SearchDirection.FORWARD)
-
-
-@key_binding(filter=is_searching)
-def reverse_incremental_search(event: E) -> None:
- """
- Apply reverse incremental search, but keep search buffer focused.
- """
- search.do_incremental_search(search.SearchDirection.BACKWARD, count=event.arg)
-
-
-@key_binding(filter=is_searching)
-def forward_incremental_search(event: E) -> None:
- """
- Apply forward incremental search, but keep search buffer focused.
- """
- search.do_incremental_search(search.SearchDirection.FORWARD, count=event.arg)
-
-
-@Condition
-def _previous_buffer_is_returnable() -> bool:
- """
- True if the previously focused buffer has a return handler.
- """
- prev_control = get_app().layout.search_target_buffer_control
- return bool(prev_control and prev_control.buffer.is_returnable)
-
-
-@key_binding(filter=is_searching & _previous_buffer_is_returnable)
-def accept_search_and_accept_input(event: E) -> None:
- """
- Accept the search operation first, then accept the input.
- """
- search.accept_search()
- event.current_buffer.validate_and_handle()
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/vi.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/vi.py
deleted file mode 100644
index efbb107de04..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings/vi.py
+++ /dev/null
@@ -1,2221 +0,0 @@
-# pylint: disable=function-redefined
-import codecs
-import string
-from enum import Enum
-from itertools import accumulate
-from typing import Callable, Iterable, List, Optional, Tuple, TypeVar, Union
-
-from prompt_toolkit.application.current import get_app
-from prompt_toolkit.buffer import Buffer, indent, reshape_text, unindent
-from prompt_toolkit.clipboard import ClipboardData
-from prompt_toolkit.document import Document
-from prompt_toolkit.filters import (
- Always,
- Condition,
- Filter,
- has_arg,
- is_read_only,
- is_searching,
-)
-from prompt_toolkit.filters.app import (
- in_paste_mode,
- is_multiline,
- vi_digraph_mode,
- vi_insert_mode,
- vi_insert_multiple_mode,
- vi_mode,
- vi_navigation_mode,
- vi_recording_macro,
- vi_replace_mode,
- vi_replace_single_mode,
- vi_search_direction_reversed,
- vi_selection_mode,
- vi_waiting_for_text_object_mode,
-)
-from prompt_toolkit.input.vt100_parser import Vt100Parser
-from prompt_toolkit.key_binding.digraphs import DIGRAPHS
-from prompt_toolkit.key_binding.key_processor import KeyPress, KeyPressEvent
-from prompt_toolkit.key_binding.vi_state import CharacterFind, InputMode
-from prompt_toolkit.keys import Keys
-from prompt_toolkit.search import SearchDirection
-from prompt_toolkit.selection import PasteMode, SelectionState, SelectionType
-
-from ..key_bindings import ConditionalKeyBindings, KeyBindings, KeyBindingsBase
-from .named_commands import get_by_name
-
-__all__ = [
- "load_vi_bindings",
- "load_vi_search_bindings",
-]
-
-E = KeyPressEvent
-
-ascii_lowercase = string.ascii_lowercase
-
-vi_register_names = ascii_lowercase + "0123456789"
-
-
-class TextObjectType(Enum):
- EXCLUSIVE = "EXCLUSIVE"
- INCLUSIVE = "INCLUSIVE"
- LINEWISE = "LINEWISE"
- BLOCK = "BLOCK"
-
-
-class TextObject:
- """
- Return struct for functions wrapped in ``text_object``.
- Both `start` and `end` are relative to the current cursor position.
- """
-
- def __init__(
- self, start: int, end: int = 0, type: TextObjectType = TextObjectType.EXCLUSIVE
- ):
-
- self.start = start
- self.end = end
- self.type = type
-
- @property
- def selection_type(self) -> SelectionType:
- if self.type == TextObjectType.LINEWISE:
- return SelectionType.LINES
- if self.type == TextObjectType.BLOCK:
- return SelectionType.BLOCK
- else:
- return SelectionType.CHARACTERS
-
- def sorted(self) -> Tuple[int, int]:
- """
- Return a (start, end) tuple where start <= end.
- """
- if self.start < self.end:
- return self.start, self.end
- else:
- return self.end, self.start
-
- def operator_range(self, document: Document) -> Tuple[int, int]:
- """
- Return a (start, end) tuple with start <= end that indicates the range
- operators should operate on.
- `buffer` is used to get start and end of line positions.
-
- This should return something that can be used in a slice, so the `end`
- position is *not* included.
- """
- start, end = self.sorted()
- doc = document
-
- if (
- self.type == TextObjectType.EXCLUSIVE
- and doc.translate_index_to_position(end + doc.cursor_position)[1] == 0
- ):
- # If the motion is exclusive and the end of motion is on the first
- # column, the end position becomes end of previous line.
- end -= 1
- if self.type == TextObjectType.INCLUSIVE:
- end += 1
- if self.type == TextObjectType.LINEWISE:
- # Select whole lines
- row, col = doc.translate_index_to_position(start + doc.cursor_position)
- start = doc.translate_row_col_to_index(row, 0) - doc.cursor_position
- row, col = doc.translate_index_to_position(end + doc.cursor_position)
- end = (
- doc.translate_row_col_to_index(row, len(doc.lines[row]))
- - doc.cursor_position
- )
- return start, end
-
- def get_line_numbers(self, buffer: Buffer) -> Tuple[int, int]:
- """
- Return a (start_line, end_line) pair.
- """
- # Get absolute cursor positions from the text object.
- from_, to = self.operator_range(buffer.document)
- from_ += buffer.cursor_position
- to += buffer.cursor_position
-
- # Take the start of the lines.
- from_, _ = buffer.document.translate_index_to_position(from_)
- to, _ = buffer.document.translate_index_to_position(to)
-
- return from_, to
-
- def cut(self, buffer: Buffer) -> Tuple[Document, ClipboardData]:
- """
- Turn text object into `ClipboardData` instance.
- """
- from_, to = self.operator_range(buffer.document)
-
- from_ += buffer.cursor_position
- to += buffer.cursor_position
-
- # For Vi mode, the SelectionState does include the upper position,
- # while `self.operator_range` does not. So, go one to the left, unless
- # we're in the line mode, then we don't want to risk going to the
- # previous line, and missing one line in the selection.
- if self.type != TextObjectType.LINEWISE:
- to -= 1
-
- document = Document(
- buffer.text,
- to,
- SelectionState(original_cursor_position=from_, type=self.selection_type),
- )
-
- new_document, clipboard_data = document.cut_selection()
- return new_document, clipboard_data
-
-
-# Typevar for any text object function:
-TextObjectFunction = Callable[[E], TextObject]
-_TOF = TypeVar("_TOF", bound=TextObjectFunction)
-
-
-def create_text_object_decorator(
- key_bindings: KeyBindings,
-) -> Callable[..., Callable[[_TOF], _TOF]]:
- """
- Create a decorator that can be used to register Vi text object implementations.
- """
-
- def text_object_decorator(
- *keys: Union[Keys, str],
- filter: Filter = Always(),
- no_move_handler: bool = False,
- no_selection_handler: bool = False,
- eager: bool = False,
- ) -> Callable[[_TOF], _TOF]:
- """
- Register a text object function.
-
- Usage::
-
- @text_object('w', filter=..., no_move_handler=False)
- def handler(event):
- # Return a text object for this key.
- return TextObject(...)
-
- :param no_move_handler: Disable the move handler in navigation mode.
- (It's still active in selection mode.)
- """
-
- def decorator(text_object_func: _TOF) -> _TOF:
- @key_bindings.add(
- *keys, filter=vi_waiting_for_text_object_mode & filter, eager=eager
- )
- def _apply_operator_to_text_object(event: E) -> None:
- # Arguments are multiplied.
- vi_state = event.app.vi_state
- event._arg = str((vi_state.operator_arg or 1) * (event.arg or 1))
-
- # Call the text object handler.
- text_obj = text_object_func(event)
-
- # Get the operator function.
- # (Should never be None here, given the
- # `vi_waiting_for_text_object_mode` filter state.)
- operator_func = vi_state.operator_func
-
- if text_obj is not None and operator_func is not None:
- # Call the operator function with the text object.
- operator_func(event, text_obj)
-
- # Clear operator.
- event.app.vi_state.operator_func = None
- event.app.vi_state.operator_arg = None
-
- # Register a move operation. (Doesn't need an operator.)
- if not no_move_handler:
-
- @key_bindings.add(
- *keys,
- filter=~vi_waiting_for_text_object_mode
- & filter
- & vi_navigation_mode,
- eager=eager,
- )
- def _move_in_navigation_mode(event: E) -> None:
- """
- Move handler for navigation mode.
- """
- text_object = text_object_func(event)
- event.current_buffer.cursor_position += text_object.start
-
- # Register a move selection operation.
- if not no_selection_handler:
-
- @key_bindings.add(
- *keys,
- filter=~vi_waiting_for_text_object_mode
- & filter
- & vi_selection_mode,
- eager=eager,
- )
- def _move_in_selection_mode(event: E) -> None:
- """
- Move handler for selection mode.
- """
- text_object = text_object_func(event)
- buff = event.current_buffer
- selection_state = buff.selection_state
-
- if selection_state is None:
- return # Should not happen, because of the `vi_selection_mode` filter.
-
- # When the text object has both a start and end position, like 'i(' or 'iw',
- # Turn this into a selection, otherwise the cursor.
- if text_object.end:
- # Take selection positions from text object.
- start, end = text_object.operator_range(buff.document)
- start += buff.cursor_position
- end += buff.cursor_position
-
- selection_state.original_cursor_position = start
- buff.cursor_position = end
-
- # Take selection type from text object.
- if text_object.type == TextObjectType.LINEWISE:
- selection_state.type = SelectionType.LINES
- else:
- selection_state.type = SelectionType.CHARACTERS
- else:
- event.current_buffer.cursor_position += text_object.start
-
- # Make it possible to chain @text_object decorators.
- return text_object_func
-
- return decorator
-
- return text_object_decorator
-
-
-# Typevar for any operator function:
-OperatorFunction = Callable[[E, TextObject], None]
-_OF = TypeVar("_OF", bound=OperatorFunction)
-
-
-def create_operator_decorator(
- key_bindings: KeyBindings,
-) -> Callable[..., Callable[[_OF], _OF]]:
- """
- Create a decorator that can be used for registering Vi operators.
- """
-
- def operator_decorator(
- *keys: Union[Keys, str], filter: Filter = Always(), eager: bool = False
- ) -> Callable[[_OF], _OF]:
- """
- Register a Vi operator.
-
- Usage::
-
- @operator('d', filter=...)
- def handler(event, text_object):
- # Do something with the text object here.
- """
-
- def decorator(operator_func: _OF) -> _OF:
- @key_bindings.add(
- *keys,
- filter=~vi_waiting_for_text_object_mode & filter & vi_navigation_mode,
- eager=eager,
- )
- def _operator_in_navigation(event: E) -> None:
- """
- Handle operator in navigation mode.
- """
- # When this key binding is matched, only set the operator
- # function in the ViState. We should execute it after a text
- # object has been received.
- event.app.vi_state.operator_func = operator_func
- event.app.vi_state.operator_arg = event.arg
-
- @key_bindings.add(
- *keys,
- filter=~vi_waiting_for_text_object_mode & filter & vi_selection_mode,
- eager=eager,
- )
- def _operator_in_selection(event: E) -> None:
- """
- Handle operator in selection mode.
- """
- buff = event.current_buffer
- selection_state = buff.selection_state
-
- if selection_state is not None:
- # Create text object from selection.
- if selection_state.type == SelectionType.LINES:
- text_obj_type = TextObjectType.LINEWISE
- elif selection_state.type == SelectionType.BLOCK:
- text_obj_type = TextObjectType.BLOCK
- else:
- text_obj_type = TextObjectType.INCLUSIVE
-
- text_object = TextObject(
- selection_state.original_cursor_position - buff.cursor_position,
- type=text_obj_type,
- )
-
- # Execute operator.
- operator_func(event, text_object)
-
- # Quit selection mode.
- buff.selection_state = None
-
- return operator_func
-
- return decorator
-
- return operator_decorator
-
-
-def load_vi_bindings() -> KeyBindingsBase:
- """
- Vi extensions.
-
- # Overview of Readline Vi commands:
- # http://www.catonmat.net/download/bash-vi-editing-mode-cheat-sheet.pdf
- """
- # Note: Some key bindings have the "~IsReadOnly()" filter added. This
- # prevents the handler to be executed when the focus is on a
- # read-only buffer.
- # This is however only required for those that change the ViState to
- # INSERT mode. The `Buffer` class itself throws the
- # `EditReadOnlyBuffer` exception for any text operations which is
- # handled correctly. There is no need to add "~IsReadOnly" to all key
- # bindings that do text manipulation.
-
- key_bindings = KeyBindings()
- handle = key_bindings.add
-
- # (Note: Always take the navigation bindings in read-only mode, even when
- # ViState says different.)
-
- TransformFunction = Tuple[Tuple[str, ...], Filter, Callable[[str], str]]
-
- vi_transform_functions: List[TransformFunction] = [
- # Rot 13 transformation
- (
- ("g", "?"),
- Always(),
- lambda string: codecs.encode(string, "rot_13"),
- ),
- # To lowercase
- (("g", "u"), Always(), lambda string: string.lower()),
- # To uppercase.
- (("g", "U"), Always(), lambda string: string.upper()),
- # Swap case.
- (("g", "~"), Always(), lambda string: string.swapcase()),
- (
- ("~",),
- Condition(lambda: get_app().vi_state.tilde_operator),
- lambda string: string.swapcase(),
- ),
- ]
-
- # Insert a character literally (quoted insert).
- handle("c-v", filter=vi_insert_mode)(get_by_name("quoted-insert"))
-
- @handle("escape")
- def _back_to_navigation(event: E) -> None:
- """
- Escape goes to vi navigation mode.
- """
- buffer = event.current_buffer
- vi_state = event.app.vi_state
-
- if vi_state.input_mode in (InputMode.INSERT, InputMode.REPLACE):
- buffer.cursor_position += buffer.document.get_cursor_left_position()
-
- vi_state.input_mode = InputMode.NAVIGATION
-
- if bool(buffer.selection_state):
- buffer.exit_selection()
-
- @handle("k", filter=vi_selection_mode)
- def _up_in_selection(event: E) -> None:
- """
- Arrow up in selection mode.
- """
- event.current_buffer.cursor_up(count=event.arg)
-
- @handle("j", filter=vi_selection_mode)
- def _down_in_selection(event: E) -> None:
- """
- Arrow down in selection mode.
- """
- event.current_buffer.cursor_down(count=event.arg)
-
- @handle("up", filter=vi_navigation_mode)
- @handle("c-p", filter=vi_navigation_mode)
- def _up_in_navigation(event: E) -> None:
- """
- Arrow up and ControlP in navigation mode go up.
- """
- event.current_buffer.auto_up(count=event.arg)
-
- @handle("k", filter=vi_navigation_mode)
- def _go_up(event: E) -> None:
- """
- Go up, but if we enter a new history entry, move to the start of the
- line.
- """
- event.current_buffer.auto_up(
- count=event.arg, go_to_start_of_line_if_history_changes=True
- )
-
- @handle("down", filter=vi_navigation_mode)
- @handle("c-n", filter=vi_navigation_mode)
- def _go_down(event: E) -> None:
- """
- Arrow down and Control-N in navigation mode.
- """
- event.current_buffer.auto_down(count=event.arg)
-
- @handle("j", filter=vi_navigation_mode)
- def _go_down2(event: E) -> None:
- """
- Go down, but if we enter a new history entry, go to the start of the line.
- """
- event.current_buffer.auto_down(
- count=event.arg, go_to_start_of_line_if_history_changes=True
- )
-
- @handle("backspace", filter=vi_navigation_mode)
- def _go_left(event: E) -> None:
- """
- In navigation-mode, move cursor.
- """
- event.current_buffer.cursor_position += (
- event.current_buffer.document.get_cursor_left_position(count=event.arg)
- )
-
- @handle("c-n", filter=vi_insert_mode)
- def _complete_next(event: E) -> None:
- b = event.current_buffer
-
- if b.complete_state:
- b.complete_next()
- else:
- b.start_completion(select_first=True)
-
- @handle("c-p", filter=vi_insert_mode)
- def _complete_prev(event: E) -> None:
- """
- Control-P: To previous completion.
- """
- b = event.current_buffer
-
- if b.complete_state:
- b.complete_previous()
- else:
- b.start_completion(select_last=True)
-
- @handle("c-g", filter=vi_insert_mode)
- @handle("c-y", filter=vi_insert_mode)
- def _accept_completion(event: E) -> None:
- """
- Accept current completion.
- """
- event.current_buffer.complete_state = None
-
- @handle("c-e", filter=vi_insert_mode)
- def _cancel_completion(event: E) -> None:
- """
- Cancel completion. Go back to originally typed text.
- """
- event.current_buffer.cancel_completion()
-
- @Condition
- def is_returnable() -> bool:
- return get_app().current_buffer.is_returnable
-
- # In navigation mode, pressing enter will always return the input.
- handle("enter", filter=vi_navigation_mode & is_returnable)(
- get_by_name("accept-line")
- )
-
- # In insert mode, also accept input when enter is pressed, and the buffer
- # has been marked as single line.
- handle("enter", filter=is_returnable & ~is_multiline)(get_by_name("accept-line"))
-
- @handle("enter", filter=~is_returnable & vi_navigation_mode)
- def _start_of_next_line(event: E) -> None:
- """
- Go to the beginning of next line.
- """
- b = event.current_buffer
- b.cursor_down(count=event.arg)
- b.cursor_position += b.document.get_start_of_line_position(
- after_whitespace=True
- )
-
- # ** In navigation mode **
-
- # List of navigation commands: http://hea-www.harvard.edu/~fine/Tech/vi.html
-
- @handle("insert", filter=vi_navigation_mode)
- def _insert_mode(event: E) -> None:
- """
- Pressing the Insert key.
- """
- event.app.vi_state.input_mode = InputMode.INSERT
-
- @handle("insert", filter=vi_insert_mode)
- def _navigation_mode(event: E) -> None:
- """
- Pressing the Insert key.
- """
- event.app.vi_state.input_mode = InputMode.NAVIGATION
-
- @handle("a", filter=vi_navigation_mode & ~is_read_only)
- # ~IsReadOnly, because we want to stay in navigation mode for
- # read-only buffers.
- def _a(event: E) -> None:
- event.current_buffer.cursor_position += (
- event.current_buffer.document.get_cursor_right_position()
- )
- event.app.vi_state.input_mode = InputMode.INSERT
-
- @handle("A", filter=vi_navigation_mode & ~is_read_only)
- def _A(event: E) -> None:
- event.current_buffer.cursor_position += (
- event.current_buffer.document.get_end_of_line_position()
- )
- event.app.vi_state.input_mode = InputMode.INSERT
-
- @handle("C", filter=vi_navigation_mode & ~is_read_only)
- def _change_until_end_of_line(event: E) -> None:
- """
- Change to end of line.
- Same as 'c$' (which is implemented elsewhere.)
- """
- buffer = event.current_buffer
-
- deleted = buffer.delete(count=buffer.document.get_end_of_line_position())
- event.app.clipboard.set_text(deleted)
- event.app.vi_state.input_mode = InputMode.INSERT
-
- @handle("c", "c", filter=vi_navigation_mode & ~is_read_only)
- @handle("S", filter=vi_navigation_mode & ~is_read_only)
- def _change_current_line(event: E) -> None: # TODO: implement 'arg'
- """
- Change current line
- """
- buffer = event.current_buffer
-
- # We copy the whole line.
- data = ClipboardData(buffer.document.current_line, SelectionType.LINES)
- event.app.clipboard.set_data(data)
-
- # But we delete after the whitespace
- buffer.cursor_position += buffer.document.get_start_of_line_position(
- after_whitespace=True
- )
- buffer.delete(count=buffer.document.get_end_of_line_position())
- event.app.vi_state.input_mode = InputMode.INSERT
-
- @handle("D", filter=vi_navigation_mode)
- def _delete_until_end_of_line(event: E) -> None:
- """
- Delete from cursor position until the end of the line.
- """
- buffer = event.current_buffer
- deleted = buffer.delete(count=buffer.document.get_end_of_line_position())
- event.app.clipboard.set_text(deleted)
-
- @handle("d", "d", filter=vi_navigation_mode)
- def _delete_line(event: E) -> None:
- """
- Delete line. (Or the following 'n' lines.)
- """
- buffer = event.current_buffer
-
- # Split string in before/deleted/after text.
- lines = buffer.document.lines
-
- before = "\n".join(lines[: buffer.document.cursor_position_row])
- deleted = "\n".join(
- lines[
- buffer.document.cursor_position_row : buffer.document.cursor_position_row
- + event.arg
- ]
- )
- after = "\n".join(lines[buffer.document.cursor_position_row + event.arg :])
-
- # Set new text.
- if before and after:
- before = before + "\n"
-
- # Set text and cursor position.
- buffer.document = Document(
- text=before + after,
- # Cursor At the start of the first 'after' line, after the leading whitespace.
- cursor_position=len(before) + len(after) - len(after.lstrip(" ")),
- )
-
- # Set clipboard data
- event.app.clipboard.set_data(ClipboardData(deleted, SelectionType.LINES))
-
- @handle("x", filter=vi_selection_mode)
- def _cut(event: E) -> None:
- """
- Cut selection.
- ('x' is not an operator.)
- """
- clipboard_data = event.current_buffer.cut_selection()
- event.app.clipboard.set_data(clipboard_data)
-
- @handle("i", filter=vi_navigation_mode & ~is_read_only)
- def _i(event: E) -> None:
- event.app.vi_state.input_mode = InputMode.INSERT
-
- @handle("I", filter=vi_navigation_mode & ~is_read_only)
- def _I(event: E) -> None:
- event.app.vi_state.input_mode = InputMode.INSERT
- event.current_buffer.cursor_position += (
- event.current_buffer.document.get_start_of_line_position(
- after_whitespace=True
- )
- )
-
- @Condition
- def in_block_selection() -> bool:
- buff = get_app().current_buffer
- return bool(
- buff.selection_state and buff.selection_state.type == SelectionType.BLOCK
- )
-
- @handle("I", filter=in_block_selection & ~is_read_only)
- def insert_in_block_selection(event: E, after: bool = False) -> None:
- """
- Insert in block selection mode.
- """
- buff = event.current_buffer
-
- # Store all cursor positions.
- positions = []
-
- if after:
-
- def get_pos(from_to: Tuple[int, int]) -> int:
- return from_to[1]
-
- else:
-
- def get_pos(from_to: Tuple[int, int]) -> int:
- return from_to[0]
-
- for i, from_to in enumerate(buff.document.selection_ranges()):
- positions.append(get_pos(from_to))
- if i == 0:
- buff.cursor_position = get_pos(from_to)
-
- buff.multiple_cursor_positions = positions
-
- # Go to 'INSERT_MULTIPLE' mode.
- event.app.vi_state.input_mode = InputMode.INSERT_MULTIPLE
- buff.exit_selection()
-
- @handle("A", filter=in_block_selection & ~is_read_only)
- def _append_after_block(event: E) -> None:
- insert_in_block_selection(event, after=True)
-
- @handle("J", filter=vi_navigation_mode & ~is_read_only)
- def _join(event: E) -> None:
- """
- Join lines.
- """
- for i in range(event.arg):
- event.current_buffer.join_next_line()
-
- @handle("g", "J", filter=vi_navigation_mode & ~is_read_only)
- def _join_nospace(event: E) -> None:
- """
- Join lines without space.
- """
- for i in range(event.arg):
- event.current_buffer.join_next_line(separator="")
-
- @handle("J", filter=vi_selection_mode & ~is_read_only)
- def _join_selection(event: E) -> None:
- """
- Join selected lines.
- """
- event.current_buffer.join_selected_lines()
-
- @handle("g", "J", filter=vi_selection_mode & ~is_read_only)
- def _join_selection_nospace(event: E) -> None:
- """
- Join selected lines without space.
- """
- event.current_buffer.join_selected_lines(separator="")
-
- @handle("p", filter=vi_navigation_mode)
- def _paste(event: E) -> None:
- """
- Paste after
- """
- event.current_buffer.paste_clipboard_data(
- event.app.clipboard.get_data(),
- count=event.arg,
- paste_mode=PasteMode.VI_AFTER,
- )
-
- @handle("P", filter=vi_navigation_mode)
- def _paste_before(event: E) -> None:
- """
- Paste before
- """
- event.current_buffer.paste_clipboard_data(
- event.app.clipboard.get_data(),
- count=event.arg,
- paste_mode=PasteMode.VI_BEFORE,
- )
-
- @handle('"', Keys.Any, "p", filter=vi_navigation_mode)
- def _paste_register(event: E) -> None:
- """
- Paste from named register.
- """
- c = event.key_sequence[1].data
- if c in vi_register_names:
- data = event.app.vi_state.named_registers.get(c)
- if data:
- event.current_buffer.paste_clipboard_data(
- data, count=event.arg, paste_mode=PasteMode.VI_AFTER
- )
-
- @handle('"', Keys.Any, "P", filter=vi_navigation_mode)
- def _paste_register_before(event: E) -> None:
- """
- Paste (before) from named register.
- """
- c = event.key_sequence[1].data
- if c in vi_register_names:
- data = event.app.vi_state.named_registers.get(c)
- if data:
- event.current_buffer.paste_clipboard_data(
- data, count=event.arg, paste_mode=PasteMode.VI_BEFORE
- )
-
- @handle("r", filter=vi_navigation_mode)
- def _replace(event: E) -> None:
- """
- Go to 'replace-single'-mode.
- """
- event.app.vi_state.input_mode = InputMode.REPLACE_SINGLE
-
- @handle("R", filter=vi_navigation_mode)
- def _replace_mode(event: E) -> None:
- """
- Go to 'replace'-mode.
- """
- event.app.vi_state.input_mode = InputMode.REPLACE
-
- @handle("s", filter=vi_navigation_mode & ~is_read_only)
- def _substitute(event: E) -> None:
- """
- Substitute with new text
- (Delete character(s) and go to insert mode.)
- """
- text = event.current_buffer.delete(count=event.arg)
- event.app.clipboard.set_text(text)
- event.app.vi_state.input_mode = InputMode.INSERT
-
- @handle("u", filter=vi_navigation_mode, save_before=(lambda e: False))
- def _undo(event: E) -> None:
- for i in range(event.arg):
- event.current_buffer.undo()
-
- @handle("V", filter=vi_navigation_mode)
- def _visual_line(event: E) -> None:
- """
- Start lines selection.
- """
- event.current_buffer.start_selection(selection_type=SelectionType.LINES)
-
- @handle("c-v", filter=vi_navigation_mode)
- def _visual_block(event: E) -> None:
- """
- Enter block selection mode.
- """
- event.current_buffer.start_selection(selection_type=SelectionType.BLOCK)
-
- @handle("V", filter=vi_selection_mode)
- def _visual_line2(event: E) -> None:
- """
- Exit line selection mode, or go from non line selection mode to line
- selection mode.
- """
- selection_state = event.current_buffer.selection_state
-
- if selection_state is not None:
- if selection_state.type != SelectionType.LINES:
- selection_state.type = SelectionType.LINES
- else:
- event.current_buffer.exit_selection()
-
- @handle("v", filter=vi_navigation_mode)
- def _visual(event: E) -> None:
- """
- Enter character selection mode.
- """
- event.current_buffer.start_selection(selection_type=SelectionType.CHARACTERS)
-
- @handle("v", filter=vi_selection_mode)
- def _visual2(event: E) -> None:
- """
- Exit character selection mode, or go from non-character-selection mode
- to character selection mode.
- """
- selection_state = event.current_buffer.selection_state
-
- if selection_state is not None:
- if selection_state.type != SelectionType.CHARACTERS:
- selection_state.type = SelectionType.CHARACTERS
- else:
- event.current_buffer.exit_selection()
-
- @handle("c-v", filter=vi_selection_mode)
- def _visual_block2(event: E) -> None:
- """
- Exit block selection mode, or go from non block selection mode to block
- selection mode.
- """
- selection_state = event.current_buffer.selection_state
-
- if selection_state is not None:
- if selection_state.type != SelectionType.BLOCK:
- selection_state.type = SelectionType.BLOCK
- else:
- event.current_buffer.exit_selection()
-
- @handle("a", "w", filter=vi_selection_mode)
- @handle("a", "W", filter=vi_selection_mode)
- def _visual_auto_word(event: E) -> None:
- """
- Switch from visual linewise mode to visual characterwise mode.
- """
- buffer = event.current_buffer
-
- if (
- buffer.selection_state
- and buffer.selection_state.type == SelectionType.LINES
- ):
- buffer.selection_state.type = SelectionType.CHARACTERS
-
- @handle("x", filter=vi_navigation_mode)
- def _delete(event: E) -> None:
- """
- Delete character.
- """
- buff = event.current_buffer
- count = min(event.arg, len(buff.document.current_line_after_cursor))
- if count:
- text = event.current_buffer.delete(count=count)
- event.app.clipboard.set_text(text)
-
- @handle("X", filter=vi_navigation_mode)
- def _delete_before_cursor(event: E) -> None:
- buff = event.current_buffer
- count = min(event.arg, len(buff.document.current_line_before_cursor))
- if count:
- text = event.current_buffer.delete_before_cursor(count=count)
- event.app.clipboard.set_text(text)
-
- @handle("y", "y", filter=vi_navigation_mode)
- @handle("Y", filter=vi_navigation_mode)
- def _yank_line(event: E) -> None:
- """
- Yank the whole line.
- """
- text = "\n".join(event.current_buffer.document.lines_from_current[: event.arg])
- event.app.clipboard.set_data(ClipboardData(text, SelectionType.LINES))
-
- @handle("+", filter=vi_navigation_mode)
- def _next_line(event: E) -> None:
- """
- Move to first non whitespace of next line
- """
- buffer = event.current_buffer
- buffer.cursor_position += buffer.document.get_cursor_down_position(
- count=event.arg
- )
- buffer.cursor_position += buffer.document.get_start_of_line_position(
- after_whitespace=True
- )
-
- @handle("-", filter=vi_navigation_mode)
- def _prev_line(event: E) -> None:
- """
- Move to first non whitespace of previous line
- """
- buffer = event.current_buffer
- buffer.cursor_position += buffer.document.get_cursor_up_position(
- count=event.arg
- )
- buffer.cursor_position += buffer.document.get_start_of_line_position(
- after_whitespace=True
- )
-
- @handle(">", ">", filter=vi_navigation_mode)
- def _indent(event: E) -> None:
- """
- Indent lines.
- """
- buffer = event.current_buffer
- current_row = buffer.document.cursor_position_row
- indent(buffer, current_row, current_row + event.arg)
-
- @handle("<", "<", filter=vi_navigation_mode)
- def _unindent(event: E) -> None:
- """
- Unindent lines.
- """
- current_row = event.current_buffer.document.cursor_position_row
- unindent(event.current_buffer, current_row, current_row + event.arg)
-
- @handle("O", filter=vi_navigation_mode & ~is_read_only)
- def _open_above(event: E) -> None:
- """
- Open line above and enter insertion mode
- """
- event.current_buffer.insert_line_above(copy_margin=not in_paste_mode())
- event.app.vi_state.input_mode = InputMode.INSERT
-
- @handle("o", filter=vi_navigation_mode & ~is_read_only)
- def _open_below(event: E) -> None:
- """
- Open line below and enter insertion mode
- """
- event.current_buffer.insert_line_below(copy_margin=not in_paste_mode())
- event.app.vi_state.input_mode = InputMode.INSERT
-
- @handle("~", filter=vi_navigation_mode)
- def _reverse_case(event: E) -> None:
- """
- Reverse case of current character and move cursor forward.
- """
- buffer = event.current_buffer
- c = buffer.document.current_char
-
- if c is not None and c != "\n":
- buffer.insert_text(c.swapcase(), overwrite=True)
-
- @handle("g", "u", "u", filter=vi_navigation_mode & ~is_read_only)
- def _lowercase_line(event: E) -> None:
- """
- Lowercase current line.
- """
- buff = event.current_buffer
- buff.transform_current_line(lambda s: s.lower())
-
- @handle("g", "U", "U", filter=vi_navigation_mode & ~is_read_only)
- def _uppercase_line(event: E) -> None:
- """
- Uppercase current line.
- """
- buff = event.current_buffer
- buff.transform_current_line(lambda s: s.upper())
-
- @handle("g", "~", "~", filter=vi_navigation_mode & ~is_read_only)
- def _swapcase_line(event: E) -> None:
- """
- Swap case of the current line.
- """
- buff = event.current_buffer
- buff.transform_current_line(lambda s: s.swapcase())
-
- @handle("#", filter=vi_navigation_mode)
- def _prev_occurence(event: E) -> None:
- """
- Go to previous occurrence of this word.
- """
- b = event.current_buffer
- search_state = event.app.current_search_state
-
- search_state.text = b.document.get_word_under_cursor()
- search_state.direction = SearchDirection.BACKWARD
-
- b.apply_search(search_state, count=event.arg, include_current_position=False)
-
- @handle("*", filter=vi_navigation_mode)
- def _next_occurance(event: E) -> None:
- """
- Go to next occurrence of this word.
- """
- b = event.current_buffer
- search_state = event.app.current_search_state
-
- search_state.text = b.document.get_word_under_cursor()
- search_state.direction = SearchDirection.FORWARD
-
- b.apply_search(search_state, count=event.arg, include_current_position=False)
-
- @handle("(", filter=vi_navigation_mode)
- def _begin_of_sentence(event: E) -> None:
- # TODO: go to begin of sentence.
- # XXX: should become text_object.
- pass
-
- @handle(")", filter=vi_navigation_mode)
- def _end_of_sentence(event: E) -> None:
- # TODO: go to end of sentence.
- # XXX: should become text_object.
- pass
-
- operator = create_operator_decorator(key_bindings)
- text_object = create_text_object_decorator(key_bindings)
-
- @handle(Keys.Any, filter=vi_waiting_for_text_object_mode)
- def _unknown_text_object(event: E) -> None:
- """
- Unknown key binding while waiting for a text object.
- """
- event.app.output.bell()
-
- #
- # *** Operators ***
- #
-
- def create_delete_and_change_operators(
- delete_only: bool, with_register: bool = False
- ) -> None:
- """
- Delete and change operators.
-
- :param delete_only: Create an operator that deletes, but doesn't go to insert mode.
- :param with_register: Copy the deleted text to this named register instead of the clipboard.
- """
- handler_keys: Iterable[str]
- if with_register:
- handler_keys = ('"', Keys.Any, "cd"[delete_only])
- else:
- handler_keys = "cd"[delete_only]
-
- @operator(*handler_keys, filter=~is_read_only)
- def delete_or_change_operator(event: E, text_object: TextObject) -> None:
- clipboard_data = None
- buff = event.current_buffer
-
- if text_object:
- new_document, clipboard_data = text_object.cut(buff)
- buff.document = new_document
-
- # Set deleted/changed text to clipboard or named register.
- if clipboard_data and clipboard_data.text:
- if with_register:
- reg_name = event.key_sequence[1].data
- if reg_name in vi_register_names:
- event.app.vi_state.named_registers[reg_name] = clipboard_data
- else:
- event.app.clipboard.set_data(clipboard_data)
-
- # Only go back to insert mode in case of 'change'.
- if not delete_only:
- event.app.vi_state.input_mode = InputMode.INSERT
-
- create_delete_and_change_operators(False, False)
- create_delete_and_change_operators(False, True)
- create_delete_and_change_operators(True, False)
- create_delete_and_change_operators(True, True)
-
- def create_transform_handler(
- filter: Filter, transform_func: Callable[[str], str], *a: str
- ) -> None:
- @operator(*a, filter=filter & ~is_read_only)
- def _(event: E, text_object: TextObject) -> None:
- """
- Apply transformation (uppercase, lowercase, rot13, swap case).
- """
- buff = event.current_buffer
- start, end = text_object.operator_range(buff.document)
-
- if start < end:
- # Transform.
- buff.transform_region(
- buff.cursor_position + start,
- buff.cursor_position + end,
- transform_func,
- )
-
- # Move cursor
- buff.cursor_position += text_object.end or text_object.start
-
- for k, f, func in vi_transform_functions:
- create_transform_handler(f, func, *k)
-
- @operator("y")
- def _yank(event: E, text_object: TextObject) -> None:
- """
- Yank operator. (Copy text.)
- """
- _, clipboard_data = text_object.cut(event.current_buffer)
- if clipboard_data.text:
- event.app.clipboard.set_data(clipboard_data)
-
- @operator('"', Keys.Any, "y")
- def _yank_to_register(event: E, text_object: TextObject) -> None:
- """
- Yank selection to named register.
- """
- c = event.key_sequence[1].data
- if c in vi_register_names:
- _, clipboard_data = text_object.cut(event.current_buffer)
- event.app.vi_state.named_registers[c] = clipboard_data
-
- @operator(">")
- def _indent_text_object(event: E, text_object: TextObject) -> None:
- """
- Indent.
- """
- buff = event.current_buffer
- from_, to = text_object.get_line_numbers(buff)
- indent(buff, from_, to + 1, count=event.arg)
-
- @operator("<")
- def _unindent_text_object(event: E, text_object: TextObject) -> None:
- """
- Unindent.
- """
- buff = event.current_buffer
- from_, to = text_object.get_line_numbers(buff)
- unindent(buff, from_, to + 1, count=event.arg)
-
- @operator("g", "q")
- def _reshape(event: E, text_object: TextObject) -> None:
- """
- Reshape text.
- """
- buff = event.current_buffer
- from_, to = text_object.get_line_numbers(buff)
- reshape_text(buff, from_, to)
-
- #
- # *** Text objects ***
- #
-
- @text_object("b")
- def _b(event: E) -> TextObject:
- """
- Move one word or token left.
- """
- return TextObject(
- event.current_buffer.document.find_start_of_previous_word(count=event.arg)
- or 0
- )
-
- @text_object("B")
- def _B(event: E) -> TextObject:
- """
- Move one non-blank word left
- """
- return TextObject(
- event.current_buffer.document.find_start_of_previous_word(
- count=event.arg, WORD=True
- )
- or 0
- )
-
- @text_object("$")
- def _dollar(event: E) -> TextObject:
- """
- 'c$', 'd$' and '$': Delete/change/move until end of line.
- """
- return TextObject(event.current_buffer.document.get_end_of_line_position())
-
- @text_object("w")
- def _word_forward(event: E) -> TextObject:
- """
- 'word' forward. 'cw', 'dw', 'w': Delete/change/move one word.
- """
- return TextObject(
- event.current_buffer.document.find_next_word_beginning(count=event.arg)
- or event.current_buffer.document.get_end_of_document_position()
- )
-
- @text_object("W")
- def _WORD_forward(event: E) -> TextObject:
- """
- 'WORD' forward. 'cW', 'dW', 'W': Delete/change/move one WORD.
- """
- return TextObject(
- event.current_buffer.document.find_next_word_beginning(
- count=event.arg, WORD=True
- )
- or event.current_buffer.document.get_end_of_document_position()
- )
-
- @text_object("e")
- def _end_of_word(event: E) -> TextObject:
- """
- End of 'word': 'ce', 'de', 'e'
- """
- end = event.current_buffer.document.find_next_word_ending(count=event.arg)
- return TextObject(end - 1 if end else 0, type=TextObjectType.INCLUSIVE)
-
- @text_object("E")
- def _end_of_WORD(event: E) -> TextObject:
- """
- End of 'WORD': 'cE', 'dE', 'E'
- """
- end = event.current_buffer.document.find_next_word_ending(
- count=event.arg, WORD=True
- )
- return TextObject(end - 1 if end else 0, type=TextObjectType.INCLUSIVE)
-
- @text_object("i", "w", no_move_handler=True)
- def _inner_word(event: E) -> TextObject:
- """
- Inner 'word': ciw and diw
- """
- start, end = event.current_buffer.document.find_boundaries_of_current_word()
- return TextObject(start, end)
-
- @text_object("a", "w", no_move_handler=True)
- def _a_word(event: E) -> TextObject:
- """
- A 'word': caw and daw
- """
- start, end = event.current_buffer.document.find_boundaries_of_current_word(
- include_trailing_whitespace=True
- )
- return TextObject(start, end)
-
- @text_object("i", "W", no_move_handler=True)
- def _inner_WORD(event: E) -> TextObject:
- """
- Inner 'WORD': ciW and diW
- """
- start, end = event.current_buffer.document.find_boundaries_of_current_word(
- WORD=True
- )
- return TextObject(start, end)
-
- @text_object("a", "W", no_move_handler=True)
- def _a_WORD(event: E) -> TextObject:
- """
- A 'WORD': caw and daw
- """
- start, end = event.current_buffer.document.find_boundaries_of_current_word(
- WORD=True, include_trailing_whitespace=True
- )
- return TextObject(start, end)
-
- @text_object("a", "p", no_move_handler=True)
- def _paragraph(event: E) -> TextObject:
- """
- Auto paragraph.
- """
- start = event.current_buffer.document.start_of_paragraph()
- end = event.current_buffer.document.end_of_paragraph(count=event.arg)
- return TextObject(start, end)
-
- @text_object("^")
- def _start_of_line(event: E) -> TextObject:
- """'c^', 'd^' and '^': Soft start of line, after whitespace."""
- return TextObject(
- event.current_buffer.document.get_start_of_line_position(
- after_whitespace=True
- )
- )
-
- @text_object("0")
- def _hard_start_of_line(event: E) -> TextObject:
- """
- 'c0', 'd0': Hard start of line, before whitespace.
- (The move '0' key is implemented elsewhere, because a '0' could also change the `arg`.)
- """
- return TextObject(
- event.current_buffer.document.get_start_of_line_position(
- after_whitespace=False
- )
- )
-
- def create_ci_ca_handles(
- ci_start: str, ci_end: str, inner: bool, key: Optional[str] = None
- ) -> None:
- # TODO: 'dat', 'dit', (tags (like xml)
- """
- Delete/Change string between this start and stop character. But keep these characters.
- This implements all the ci", ci<, ci{, ci(, di", di<, ca", ca<, ... combinations.
- """
-
- def handler(event: E) -> TextObject:
- if ci_start == ci_end:
- # Quotes
- start = event.current_buffer.document.find_backwards(
- ci_start, in_current_line=False
- )
- end = event.current_buffer.document.find(ci_end, in_current_line=False)
- else:
- # Brackets
- start = event.current_buffer.document.find_enclosing_bracket_left(
- ci_start, ci_end
- )
- end = event.current_buffer.document.find_enclosing_bracket_right(
- ci_start, ci_end
- )
-
- if start is not None and end is not None:
- offset = 0 if inner else 1
- return TextObject(start + 1 - offset, end + offset)
- else:
- # Nothing found.
- return TextObject(0)
-
- if key is None:
- text_object("ai"[inner], ci_start, no_move_handler=True)(handler)
- text_object("ai"[inner], ci_end, no_move_handler=True)(handler)
- else:
- text_object("ai"[inner], key, no_move_handler=True)(handler)
-
- for inner in (False, True):
- for ci_start, ci_end in [
- ('"', '"'),
- ("'", "'"),
- ("`", "`"),
- ("[", "]"),
- ("<", ">"),
- ("{", "}"),
- ("(", ")"),
- ]:
- create_ci_ca_handles(ci_start, ci_end, inner)
-
- create_ci_ca_handles("(", ")", inner, "b") # 'dab', 'dib'
- create_ci_ca_handles("{", "}", inner, "B") # 'daB', 'diB'
-
- @text_object("{")
- def _previous_section(event: E) -> TextObject:
- """
- Move to previous blank-line separated section.
- Implements '{', 'c{', 'd{', 'y{'
- """
- index = event.current_buffer.document.start_of_paragraph(
- count=event.arg, before=True
- )
- return TextObject(index)
-
- @text_object("}")
- def _next_section(event: E) -> TextObject:
- """
- Move to next blank-line separated section.
- Implements '}', 'c}', 'd}', 'y}'
- """
- index = event.current_buffer.document.end_of_paragraph(
- count=event.arg, after=True
- )
- return TextObject(index)
-
- @text_object("f", Keys.Any)
- def _next_occurence(event: E) -> TextObject:
- """
- Go to next occurrence of character. Typing 'fx' will move the
- cursor to the next occurrence of character. 'x'.
- """
- event.app.vi_state.last_character_find = CharacterFind(event.data, False)
- match = event.current_buffer.document.find(
- event.data, in_current_line=True, count=event.arg
- )
- if match:
- return TextObject(match, type=TextObjectType.INCLUSIVE)
- else:
- return TextObject(0)
-
- @text_object("F", Keys.Any)
- def _previous_occurance(event: E) -> TextObject:
- """
- Go to previous occurrence of character. Typing 'Fx' will move the
- cursor to the previous occurrence of character. 'x'.
- """
- event.app.vi_state.last_character_find = CharacterFind(event.data, True)
- return TextObject(
- event.current_buffer.document.find_backwards(
- event.data, in_current_line=True, count=event.arg
- )
- or 0
- )
-
- @text_object("t", Keys.Any)
- def _t(event: E) -> TextObject:
- """
- Move right to the next occurrence of c, then one char backward.
- """
- event.app.vi_state.last_character_find = CharacterFind(event.data, False)
- match = event.current_buffer.document.find(
- event.data, in_current_line=True, count=event.arg
- )
- if match:
- return TextObject(match - 1, type=TextObjectType.INCLUSIVE)
- else:
- return TextObject(0)
-
- @text_object("T", Keys.Any)
- def _T(event: E) -> TextObject:
- """
- Move left to the previous occurrence of c, then one char forward.
- """
- event.app.vi_state.last_character_find = CharacterFind(event.data, True)
- match = event.current_buffer.document.find_backwards(
- event.data, in_current_line=True, count=event.arg
- )
- return TextObject(match + 1 if match else 0)
-
- def repeat(reverse: bool) -> None:
- """
- Create ',' and ';' commands.
- """
-
- @text_object("," if reverse else ";")
- def _(event: E) -> TextObject:
- """
- Repeat the last 'f'/'F'/'t'/'T' command.
- """
- pos: Optional[int] = 0
- vi_state = event.app.vi_state
-
- type = TextObjectType.EXCLUSIVE
-
- if vi_state.last_character_find:
- char = vi_state.last_character_find.character
- backwards = vi_state.last_character_find.backwards
-
- if reverse:
- backwards = not backwards
-
- if backwards:
- pos = event.current_buffer.document.find_backwards(
- char, in_current_line=True, count=event.arg
- )
- else:
- pos = event.current_buffer.document.find(
- char, in_current_line=True, count=event.arg
- )
- type = TextObjectType.INCLUSIVE
- if pos:
- return TextObject(pos, type=type)
- else:
- return TextObject(0)
-
- repeat(True)
- repeat(False)
-
- @text_object("h")
- @text_object("left")
- def _left(event: E) -> TextObject:
- """
- Implements 'ch', 'dh', 'h': Cursor left.
- """
- return TextObject(
- event.current_buffer.document.get_cursor_left_position(count=event.arg)
- )
-
- @text_object("j", no_move_handler=True, no_selection_handler=True)
- # Note: We also need `no_selection_handler`, because we in
- # selection mode, we prefer the other 'j' binding that keeps
- # `buffer.preferred_column`.
- def _down(event: E) -> TextObject:
- """
- Implements 'cj', 'dj', 'j', ... Cursor up.
- """
- return TextObject(
- event.current_buffer.document.get_cursor_down_position(count=event.arg),
- type=TextObjectType.LINEWISE,
- )
-
- @text_object("k", no_move_handler=True, no_selection_handler=True)
- def _up(event: E) -> TextObject:
- """
- Implements 'ck', 'dk', 'k', ... Cursor up.
- """
- return TextObject(
- event.current_buffer.document.get_cursor_up_position(count=event.arg),
- type=TextObjectType.LINEWISE,
- )
-
- @text_object("l")
- @text_object(" ")
- @text_object("right")
- def _right(event: E) -> TextObject:
- """
- Implements 'cl', 'dl', 'l', 'c ', 'd ', ' '. Cursor right.
- """
- return TextObject(
- event.current_buffer.document.get_cursor_right_position(count=event.arg)
- )
-
- @text_object("H")
- def _top_of_screen(event: E) -> TextObject:
- """
- Moves to the start of the visible region. (Below the scroll offset.)
- Implements 'cH', 'dH', 'H'.
- """
- w = event.app.layout.current_window
- b = event.current_buffer
-
- if w and w.render_info:
- # When we find a Window that has BufferControl showing this window,
- # move to the start of the visible area.
- pos = (
- b.document.translate_row_col_to_index(
- w.render_info.first_visible_line(after_scroll_offset=True), 0
- )
- - b.cursor_position
- )
-
- else:
- # Otherwise, move to the start of the input.
- pos = -len(b.document.text_before_cursor)
- return TextObject(pos, type=TextObjectType.LINEWISE)
-
- @text_object("M")
- def _middle_of_screen(event: E) -> TextObject:
- """
- Moves cursor to the vertical center of the visible region.
- Implements 'cM', 'dM', 'M'.
- """
- w = event.app.layout.current_window
- b = event.current_buffer
-
- if w and w.render_info:
- # When we find a Window that has BufferControl showing this window,
- # move to the center of the visible area.
- pos = (
- b.document.translate_row_col_to_index(
- w.render_info.center_visible_line(), 0
- )
- - b.cursor_position
- )
-
- else:
- # Otherwise, move to the start of the input.
- pos = -len(b.document.text_before_cursor)
- return TextObject(pos, type=TextObjectType.LINEWISE)
-
- @text_object("L")
- def _end_of_screen(event: E) -> TextObject:
- """
- Moves to the end of the visible region. (Above the scroll offset.)
- """
- w = event.app.layout.current_window
- b = event.current_buffer
-
- if w and w.render_info:
- # When we find a Window that has BufferControl showing this window,
- # move to the end of the visible area.
- pos = (
- b.document.translate_row_col_to_index(
- w.render_info.last_visible_line(before_scroll_offset=True), 0
- )
- - b.cursor_position
- )
-
- else:
- # Otherwise, move to the end of the input.
- pos = len(b.document.text_after_cursor)
- return TextObject(pos, type=TextObjectType.LINEWISE)
-
- @text_object("n", no_move_handler=True)
- def _search_next(event: E) -> TextObject:
- """
- Search next.
- """
- buff = event.current_buffer
- search_state = event.app.current_search_state
-
- cursor_position = buff.get_search_position(
- search_state, include_current_position=False, count=event.arg
- )
- return TextObject(cursor_position - buff.cursor_position)
-
- @handle("n", filter=vi_navigation_mode)
- def _search_next2(event: E) -> None:
- """
- Search next in navigation mode. (This goes through the history.)
- """
- search_state = event.app.current_search_state
-
- event.current_buffer.apply_search(
- search_state, include_current_position=False, count=event.arg
- )
-
- @text_object("N", no_move_handler=True)
- def _search_previous(event: E) -> TextObject:
- """
- Search previous.
- """
- buff = event.current_buffer
- search_state = event.app.current_search_state
-
- cursor_position = buff.get_search_position(
- ~search_state, include_current_position=False, count=event.arg
- )
- return TextObject(cursor_position - buff.cursor_position)
-
- @handle("N", filter=vi_navigation_mode)
- def _search_previous2(event: E) -> None:
- """
- Search previous in navigation mode. (This goes through the history.)
- """
- search_state = event.app.current_search_state
-
- event.current_buffer.apply_search(
- ~search_state, include_current_position=False, count=event.arg
- )
-
- @handle("z", "+", filter=vi_navigation_mode | vi_selection_mode)
- @handle("z", "t", filter=vi_navigation_mode | vi_selection_mode)
- @handle("z", "enter", filter=vi_navigation_mode | vi_selection_mode)
- def _scroll_top(event: E) -> None:
- """
- Scrolls the window to makes the current line the first line in the visible region.
- """
- b = event.current_buffer
- event.app.layout.current_window.vertical_scroll = b.document.cursor_position_row
-
- @handle("z", "-", filter=vi_navigation_mode | vi_selection_mode)
- @handle("z", "b", filter=vi_navigation_mode | vi_selection_mode)
- def _scroll_bottom(event: E) -> None:
- """
- Scrolls the window to makes the current line the last line in the visible region.
- """
- # We can safely set the scroll offset to zero; the Window will make
- # sure that it scrolls at least enough to make the cursor visible
- # again.
- event.app.layout.current_window.vertical_scroll = 0
-
- @handle("z", "z", filter=vi_navigation_mode | vi_selection_mode)
- def _scroll_center(event: E) -> None:
- """
- Center Window vertically around cursor.
- """
- w = event.app.layout.current_window
- b = event.current_buffer
-
- if w and w.render_info:
- info = w.render_info
-
- # Calculate the offset that we need in order to position the row
- # containing the cursor in the center.
- scroll_height = info.window_height // 2
-
- y = max(0, b.document.cursor_position_row - 1)
- height = 0
- while y > 0:
- line_height = info.get_height_for_line(y)
-
- if height + line_height < scroll_height:
- height += line_height
- y -= 1
- else:
- break
-
- w.vertical_scroll = y
-
- @text_object("%")
- def _goto_corresponding_bracket(event: E) -> TextObject:
- """
- Implements 'c%', 'd%', '%, 'y%' (Move to corresponding bracket.)
- If an 'arg' has been given, go this this % position in the file.
- """
- buffer = event.current_buffer
-
- if event._arg:
- # If 'arg' has been given, the meaning of % is to go to the 'x%'
- # row in the file.
- if 0 < event.arg <= 100:
- absolute_index = buffer.document.translate_row_col_to_index(
- int((event.arg * buffer.document.line_count - 1) / 100), 0
- )
- return TextObject(
- absolute_index - buffer.document.cursor_position,
- type=TextObjectType.LINEWISE,
- )
- else:
- return TextObject(0) # Do nothing.
-
- else:
- # Move to the corresponding opening/closing bracket (()'s, []'s and {}'s).
- match = buffer.document.find_matching_bracket_position()
- if match:
- return TextObject(match, type=TextObjectType.INCLUSIVE)
- else:
- return TextObject(0)
-
- @text_object("|")
- def _to_column(event: E) -> TextObject:
- """
- Move to the n-th column (you may specify the argument n by typing it on
- number keys, for example, 20|).
- """
- return TextObject(
- event.current_buffer.document.get_column_cursor_position(event.arg - 1)
- )
-
- @text_object("g", "g")
- def _goto_first_line(event: E) -> TextObject:
- """
- Go to the start of the very first line.
- Implements 'gg', 'cgg', 'ygg'
- """
- d = event.current_buffer.document
-
- if event._arg:
- # Move to the given line.
- return TextObject(
- d.translate_row_col_to_index(event.arg - 1, 0) - d.cursor_position,
- type=TextObjectType.LINEWISE,
- )
- else:
- # Move to the top of the input.
- return TextObject(
- d.get_start_of_document_position(), type=TextObjectType.LINEWISE
- )
-
- @text_object("g", "_")
- def _goto_last_line(event: E) -> TextObject:
- """
- Go to last non-blank of line.
- 'g_', 'cg_', 'yg_', etc..
- """
- return TextObject(
- event.current_buffer.document.last_non_blank_of_current_line_position(),
- type=TextObjectType.INCLUSIVE,
- )
-
- @text_object("g", "e")
- def _ge(event: E) -> TextObject:
- """
- Go to last character of previous word.
- 'ge', 'cge', 'yge', etc..
- """
- prev_end = event.current_buffer.document.find_previous_word_ending(
- count=event.arg
- )
- return TextObject(
- prev_end - 1 if prev_end is not None else 0, type=TextObjectType.INCLUSIVE
- )
-
- @text_object("g", "E")
- def _gE(event: E) -> TextObject:
- """
- Go to last character of previous WORD.
- 'gE', 'cgE', 'ygE', etc..
- """
- prev_end = event.current_buffer.document.find_previous_word_ending(
- count=event.arg, WORD=True
- )
- return TextObject(
- prev_end - 1 if prev_end is not None else 0, type=TextObjectType.INCLUSIVE
- )
-
- @text_object("g", "m")
- def _gm(event: E) -> TextObject:
- """
- Like g0, but half a screenwidth to the right. (Or as much as possible.)
- """
- w = event.app.layout.current_window
- buff = event.current_buffer
-
- if w and w.render_info:
- width = w.render_info.window_width
- start = buff.document.get_start_of_line_position(after_whitespace=False)
- start += int(min(width / 2, len(buff.document.current_line)))
-
- return TextObject(start, type=TextObjectType.INCLUSIVE)
- return TextObject(0)
-
- @text_object("G")
- def _last_line(event: E) -> TextObject:
- """
- Go to the end of the document. (If no arg has been given.)
- """
- buf = event.current_buffer
- return TextObject(
- buf.document.translate_row_col_to_index(buf.document.line_count - 1, 0)
- - buf.cursor_position,
- type=TextObjectType.LINEWISE,
- )
-
- #
- # *** Other ***
- #
-
- @handle("G", filter=has_arg)
- def _to_nth_history_line(event: E) -> None:
- """
- If an argument is given, move to this line in the history. (for
- example, 15G)
- """
- event.current_buffer.go_to_history(event.arg - 1)
-
- for n in "123456789":
-
- @handle(
- n,
- filter=vi_navigation_mode
- | vi_selection_mode
- | vi_waiting_for_text_object_mode,
- )
- def _arg(event: E) -> None:
- """
- Always handle numberics in navigation mode as arg.
- """
- event.append_to_arg_count(event.data)
-
- @handle(
- "0",
- filter=(
- vi_navigation_mode | vi_selection_mode | vi_waiting_for_text_object_mode
- )
- & has_arg,
- )
- def _0_arg(event: E) -> None:
- """
- Zero when an argument was already give.
- """
- event.append_to_arg_count(event.data)
-
- @handle(Keys.Any, filter=vi_replace_mode)
- def _insert_text(event: E) -> None:
- """
- Insert data at cursor position.
- """
- event.current_buffer.insert_text(event.data, overwrite=True)
-
- @handle(Keys.Any, filter=vi_replace_single_mode)
- def _replace_single(event: E) -> None:
- """
- Replace single character at cursor position.
- """
- event.current_buffer.insert_text(event.data, overwrite=True)
- event.current_buffer.cursor_position -= 1
- event.app.vi_state.input_mode = InputMode.NAVIGATION
-
- @handle(
- Keys.Any,
- filter=vi_insert_multiple_mode,
- save_before=(lambda e: not e.is_repeat),
- )
- def _insert_text_multiple_cursors(event: E) -> None:
- """
- Insert data at multiple cursor positions at once.
- (Usually a result of pressing 'I' or 'A' in block-selection mode.)
- """
- buff = event.current_buffer
- original_text = buff.text
-
- # Construct new text.
- text = []
- p = 0
-
- for p2 in buff.multiple_cursor_positions:
- text.append(original_text[p:p2])
- text.append(event.data)
- p = p2
-
- text.append(original_text[p:])
-
- # Shift all cursor positions.
- new_cursor_positions = [
- pos + i + 1 for i, pos in enumerate(buff.multiple_cursor_positions)
- ]
-
- # Set result.
- buff.text = "".join(text)
- buff.multiple_cursor_positions = new_cursor_positions
- buff.cursor_position += 1
-
- @handle("backspace", filter=vi_insert_multiple_mode)
- def _delete_before_multiple_cursors(event: E) -> None:
- """
- Backspace, using multiple cursors.
- """
- buff = event.current_buffer
- original_text = buff.text
-
- # Construct new text.
- deleted_something = False
- text = []
- p = 0
-
- for p2 in buff.multiple_cursor_positions:
- if p2 > 0 and original_text[p2 - 1] != "\n": # Don't delete across lines.
- text.append(original_text[p : p2 - 1])
- deleted_something = True
- else:
- text.append(original_text[p:p2])
- p = p2
-
- text.append(original_text[p:])
-
- if deleted_something:
- # Shift all cursor positions.
- lengths = [len(part) for part in text[:-1]]
- new_cursor_positions = list(accumulate(lengths))
-
- # Set result.
- buff.text = "".join(text)
- buff.multiple_cursor_positions = new_cursor_positions
- buff.cursor_position -= 1
- else:
- event.app.output.bell()
-
- @handle("delete", filter=vi_insert_multiple_mode)
- def _delete_after_multiple_cursors(event: E) -> None:
- """
- Delete, using multiple cursors.
- """
- buff = event.current_buffer
- original_text = buff.text
-
- # Construct new text.
- deleted_something = False
- text = []
- new_cursor_positions = []
- p = 0
-
- for p2 in buff.multiple_cursor_positions:
- text.append(original_text[p:p2])
- if p2 >= len(original_text) or original_text[p2] == "\n":
- # Don't delete across lines.
- p = p2
- else:
- p = p2 + 1
- deleted_something = True
-
- text.append(original_text[p:])
-
- if deleted_something:
- # Shift all cursor positions.
- lengths = [len(part) for part in text[:-1]]
- new_cursor_positions = list(accumulate(lengths))
-
- # Set result.
- buff.text = "".join(text)
- buff.multiple_cursor_positions = new_cursor_positions
- else:
- event.app.output.bell()
-
- @handle("left", filter=vi_insert_multiple_mode)
- def _left_multiple(event: E) -> None:
- """
- Move all cursors to the left.
- (But keep all cursors on the same line.)
- """
- buff = event.current_buffer
- new_positions = []
-
- for p in buff.multiple_cursor_positions:
- if buff.document.translate_index_to_position(p)[1] > 0:
- p -= 1
- new_positions.append(p)
-
- buff.multiple_cursor_positions = new_positions
-
- if buff.document.cursor_position_col > 0:
- buff.cursor_position -= 1
-
- @handle("right", filter=vi_insert_multiple_mode)
- def _right_multiple(event: E) -> None:
- """
- Move all cursors to the right.
- (But keep all cursors on the same line.)
- """
- buff = event.current_buffer
- new_positions = []
-
- for p in buff.multiple_cursor_positions:
- row, column = buff.document.translate_index_to_position(p)
- if column < len(buff.document.lines[row]):
- p += 1
- new_positions.append(p)
-
- buff.multiple_cursor_positions = new_positions
-
- if not buff.document.is_cursor_at_the_end_of_line:
- buff.cursor_position += 1
-
- @handle("up", filter=vi_insert_multiple_mode)
- @handle("down", filter=vi_insert_multiple_mode)
- def _updown_multiple(event: E) -> None:
- """
- Ignore all up/down key presses when in multiple cursor mode.
- """
-
- @handle("c-x", "c-l", filter=vi_insert_mode)
- def _complete_line(event: E) -> None:
- """
- Pressing the ControlX - ControlL sequence in Vi mode does line
- completion based on the other lines in the document and the history.
- """
- event.current_buffer.start_history_lines_completion()
-
- @handle("c-x", "c-f", filter=vi_insert_mode)
- def _complete_filename(event: E) -> None:
- """
- Complete file names.
- """
- # TODO
- pass
-
- @handle("c-k", filter=vi_insert_mode | vi_replace_mode)
- def _digraph(event: E) -> None:
- """
- Go into digraph mode.
- """
- event.app.vi_state.waiting_for_digraph = True
-
- @Condition
- def digraph_symbol_1_given() -> bool:
- return get_app().vi_state.digraph_symbol1 is not None
-
- @handle(Keys.Any, filter=vi_digraph_mode & ~digraph_symbol_1_given)
- def _digraph1(event: E) -> None:
- """
- First digraph symbol.
- """
- event.app.vi_state.digraph_symbol1 = event.data
-
- @handle(Keys.Any, filter=vi_digraph_mode & digraph_symbol_1_given)
- def _create_digraph(event: E) -> None:
- """
- Insert digraph.
- """
- try:
- # Lookup.
- code: Tuple[str, str] = (
- event.app.vi_state.digraph_symbol1 or "",
- event.data,
- )
- if code not in DIGRAPHS:
- code = code[::-1] # Try reversing.
- symbol = DIGRAPHS[code]
- except KeyError:
- # Unknown digraph.
- event.app.output.bell()
- else:
- # Insert digraph.
- overwrite = event.app.vi_state.input_mode == InputMode.REPLACE
- event.current_buffer.insert_text(chr(symbol), overwrite=overwrite)
- event.app.vi_state.waiting_for_digraph = False
- finally:
- event.app.vi_state.waiting_for_digraph = False
- event.app.vi_state.digraph_symbol1 = None
-
- @handle("c-o", filter=vi_insert_mode | vi_replace_mode)
- def _quick_normal_mode(event: E) -> None:
- """
- Go into normal mode for one single action.
- """
- event.app.vi_state.temporary_navigation_mode = True
-
- @handle("q", Keys.Any, filter=vi_navigation_mode & ~vi_recording_macro)
- def _start_macro(event: E) -> None:
- """
- Start recording macro.
- """
- c = event.key_sequence[1].data
- if c in vi_register_names:
- vi_state = event.app.vi_state
-
- vi_state.recording_register = c
- vi_state.current_recording = ""
-
- @handle("q", filter=vi_navigation_mode & vi_recording_macro)
- def _stop_macro(event: E) -> None:
- """
- Stop recording macro.
- """
- vi_state = event.app.vi_state
-
- # Store and stop recording.
- if vi_state.recording_register:
- vi_state.named_registers[vi_state.recording_register] = ClipboardData(
- vi_state.current_recording
- )
- vi_state.recording_register = None
- vi_state.current_recording = ""
-
- @handle("@", Keys.Any, filter=vi_navigation_mode, record_in_macro=False)
- def _execute_macro(event: E) -> None:
- """
- Execute macro.
-
- Notice that we pass `record_in_macro=False`. This ensures that the `@x`
- keys don't appear in the recording itself. This function inserts the
- body of the called macro back into the KeyProcessor, so these keys will
- be added later on to the macro of their handlers have
- `record_in_macro=True`.
- """
- # Retrieve macro.
- c = event.key_sequence[1].data
- try:
- macro = event.app.vi_state.named_registers[c]
- except KeyError:
- return
-
- # Expand macro (which is a string in the register), in individual keys.
- # Use vt100 parser for this.
- keys: List[KeyPress] = []
-
- parser = Vt100Parser(keys.append)
- parser.feed(macro.text)
- parser.flush()
-
- # Now feed keys back to the input processor.
- for _ in range(event.arg):
- event.app.key_processor.feed_multiple(keys, first=True)
-
- return ConditionalKeyBindings(key_bindings, vi_mode)
-
-
-def load_vi_search_bindings() -> KeyBindingsBase:
- key_bindings = KeyBindings()
- handle = key_bindings.add
- from . import search
-
- @Condition
- def search_buffer_is_empty() -> bool:
- "Returns True when the search buffer is empty."
- return get_app().current_buffer.text == ""
-
- # Vi-style forward search.
- handle(
- "/",
- filter=(vi_navigation_mode | vi_selection_mode) & ~vi_search_direction_reversed,
- )(search.start_forward_incremental_search)
- handle(
- "?",
- filter=(vi_navigation_mode | vi_selection_mode) & vi_search_direction_reversed,
- )(search.start_forward_incremental_search)
- handle("c-s")(search.start_forward_incremental_search)
-
- # Vi-style backward search.
- handle(
- "?",
- filter=(vi_navigation_mode | vi_selection_mode) & ~vi_search_direction_reversed,
- )(search.start_reverse_incremental_search)
- handle(
- "/",
- filter=(vi_navigation_mode | vi_selection_mode) & vi_search_direction_reversed,
- )(search.start_reverse_incremental_search)
- handle("c-r")(search.start_reverse_incremental_search)
-
- # Apply the search. (At the / or ? prompt.)
- handle("enter", filter=is_searching)(search.accept_search)
-
- handle("c-r", filter=is_searching)(search.reverse_incremental_search)
- handle("c-s", filter=is_searching)(search.forward_incremental_search)
-
- handle("c-c")(search.abort_search)
- handle("c-g")(search.abort_search)
- handle("backspace", filter=search_buffer_is_empty)(search.abort_search)
-
- # Handle escape. This should accept the search, just like readline.
- # `abort_search` would be a meaningful alternative.
- handle("escape")(search.accept_search)
-
- return ConditionalKeyBindings(key_bindings, vi_mode)
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/defaults.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/defaults.py
deleted file mode 100644
index baa5974333b..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/defaults.py
+++ /dev/null
@@ -1,60 +0,0 @@
-"""
-Default key bindings.::
-
- key_bindings = load_key_bindings()
- app = Application(key_bindings=key_bindings)
-"""
-from prompt_toolkit.filters import buffer_has_focus
-from prompt_toolkit.key_binding.bindings.basic import load_basic_bindings
-from prompt_toolkit.key_binding.bindings.cpr import load_cpr_bindings
-from prompt_toolkit.key_binding.bindings.emacs import (
- load_emacs_bindings,
- load_emacs_search_bindings,
- load_emacs_shift_selection_bindings,
-)
-from prompt_toolkit.key_binding.bindings.mouse import load_mouse_bindings
-from prompt_toolkit.key_binding.bindings.vi import (
- load_vi_bindings,
- load_vi_search_bindings,
-)
-from prompt_toolkit.key_binding.key_bindings import (
- ConditionalKeyBindings,
- KeyBindingsBase,
- merge_key_bindings,
-)
-
-__all__ = [
- "load_key_bindings",
-]
-
-
-def load_key_bindings() -> KeyBindingsBase:
- """
- Create a KeyBindings object that contains the default key bindings.
- """
- all_bindings = merge_key_bindings(
- [
- # Load basic bindings.
- load_basic_bindings(),
- # Load emacs bindings.
- load_emacs_bindings(),
- load_emacs_search_bindings(),
- load_emacs_shift_selection_bindings(),
- # Load Vi bindings.
- load_vi_bindings(),
- load_vi_search_bindings(),
- ]
- )
-
- return merge_key_bindings(
- [
- # Make sure that the above key bindings are only active if the
- # currently focused control is a `BufferControl`. For other controls, we
- # don't want these key bindings to intervene. (This would break "ptterm"
- # for instance, which handles 'Keys.Any' in the user control itself.)
- ConditionalKeyBindings(all_bindings, buffer_has_focus),
- # Active, even when no buffer has been focused.
- load_mouse_bindings(),
- load_cpr_bindings(),
- ]
- )
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/digraphs.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/digraphs.py
deleted file mode 100644
index ad3d288a8a3..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/digraphs.py
+++ /dev/null
@@ -1,1377 +0,0 @@
-"""
-Vi Digraphs.
-This is a list of special characters that can be inserted in Vi insert mode by
-pressing Control-K followed by to normal characters.
-
-Taken from Neovim and translated to Python:
-https://raw.githubusercontent.com/neovim/neovim/master/src/nvim/digraph.c
-"""
-from typing import Dict, Tuple
-
-__all__ = [
- "DIGRAPHS",
-]
-
-# digraphs for Unicode from RFC1345
-# (also work for ISO-8859-1 aka latin1)
-DIGRAPHS: Dict[Tuple[str, str], int] = {
- ("N", "U"): 0x00,
- ("S", "H"): 0x01,
- ("S", "X"): 0x02,
- ("E", "X"): 0x03,
- ("E", "T"): 0x04,
- ("E", "Q"): 0x05,
- ("A", "K"): 0x06,
- ("B", "L"): 0x07,
- ("B", "S"): 0x08,
- ("H", "T"): 0x09,
- ("L", "F"): 0x0A,
- ("V", "T"): 0x0B,
- ("F", "F"): 0x0C,
- ("C", "R"): 0x0D,
- ("S", "O"): 0x0E,
- ("S", "I"): 0x0F,
- ("D", "L"): 0x10,
- ("D", "1"): 0x11,
- ("D", "2"): 0x12,
- ("D", "3"): 0x13,
- ("D", "4"): 0x14,
- ("N", "K"): 0x15,
- ("S", "Y"): 0x16,
- ("E", "B"): 0x17,
- ("C", "N"): 0x18,
- ("E", "M"): 0x19,
- ("S", "B"): 0x1A,
- ("E", "C"): 0x1B,
- ("F", "S"): 0x1C,
- ("G", "S"): 0x1D,
- ("R", "S"): 0x1E,
- ("U", "S"): 0x1F,
- ("S", "P"): 0x20,
- ("N", "b"): 0x23,
- ("D", "O"): 0x24,
- ("A", "t"): 0x40,
- ("<", "("): 0x5B,
- ("/", "/"): 0x5C,
- (")", ">"): 0x5D,
- ("'", ">"): 0x5E,
- ("'", "!"): 0x60,
- ("(", "!"): 0x7B,
- ("!", "!"): 0x7C,
- ("!", ")"): 0x7D,
- ("'", "?"): 0x7E,
- ("D", "T"): 0x7F,
- ("P", "A"): 0x80,
- ("H", "O"): 0x81,
- ("B", "H"): 0x82,
- ("N", "H"): 0x83,
- ("I", "N"): 0x84,
- ("N", "L"): 0x85,
- ("S", "A"): 0x86,
- ("E", "S"): 0x87,
- ("H", "S"): 0x88,
- ("H", "J"): 0x89,
- ("V", "S"): 0x8A,
- ("P", "D"): 0x8B,
- ("P", "U"): 0x8C,
- ("R", "I"): 0x8D,
- ("S", "2"): 0x8E,
- ("S", "3"): 0x8F,
- ("D", "C"): 0x90,
- ("P", "1"): 0x91,
- ("P", "2"): 0x92,
- ("T", "S"): 0x93,
- ("C", "C"): 0x94,
- ("M", "W"): 0x95,
- ("S", "G"): 0x96,
- ("E", "G"): 0x97,
- ("S", "S"): 0x98,
- ("G", "C"): 0x99,
- ("S", "C"): 0x9A,
- ("C", "I"): 0x9B,
- ("S", "T"): 0x9C,
- ("O", "C"): 0x9D,
- ("P", "M"): 0x9E,
- ("A", "C"): 0x9F,
- ("N", "S"): 0xA0,
- ("!", "I"): 0xA1,
- ("C", "t"): 0xA2,
- ("P", "d"): 0xA3,
- ("C", "u"): 0xA4,
- ("Y", "e"): 0xA5,
- ("B", "B"): 0xA6,
- ("S", "E"): 0xA7,
- ("'", ":"): 0xA8,
- ("C", "o"): 0xA9,
- ("-", "a"): 0xAA,
- ("<", "<"): 0xAB,
- ("N", "O"): 0xAC,
- ("-", "-"): 0xAD,
- ("R", "g"): 0xAE,
- ("'", "m"): 0xAF,
- ("D", "G"): 0xB0,
- ("+", "-"): 0xB1,
- ("2", "S"): 0xB2,
- ("3", "S"): 0xB3,
- ("'", "'"): 0xB4,
- ("M", "y"): 0xB5,
- ("P", "I"): 0xB6,
- (".", "M"): 0xB7,
- ("'", ","): 0xB8,
- ("1", "S"): 0xB9,
- ("-", "o"): 0xBA,
- (">", ">"): 0xBB,
- ("1", "4"): 0xBC,
- ("1", "2"): 0xBD,
- ("3", "4"): 0xBE,
- ("?", "I"): 0xBF,
- ("A", "!"): 0xC0,
- ("A", "'"): 0xC1,
- ("A", ">"): 0xC2,
- ("A", "?"): 0xC3,
- ("A", ":"): 0xC4,
- ("A", "A"): 0xC5,
- ("A", "E"): 0xC6,
- ("C", ","): 0xC7,
- ("E", "!"): 0xC8,
- ("E", "'"): 0xC9,
- ("E", ">"): 0xCA,
- ("E", ":"): 0xCB,
- ("I", "!"): 0xCC,
- ("I", "'"): 0xCD,
- ("I", ">"): 0xCE,
- ("I", ":"): 0xCF,
- ("D", "-"): 0xD0,
- ("N", "?"): 0xD1,
- ("O", "!"): 0xD2,
- ("O", "'"): 0xD3,
- ("O", ">"): 0xD4,
- ("O", "?"): 0xD5,
- ("O", ":"): 0xD6,
- ("*", "X"): 0xD7,
- ("O", "/"): 0xD8,
- ("U", "!"): 0xD9,
- ("U", "'"): 0xDA,
- ("U", ">"): 0xDB,
- ("U", ":"): 0xDC,
- ("Y", "'"): 0xDD,
- ("T", "H"): 0xDE,
- ("s", "s"): 0xDF,
- ("a", "!"): 0xE0,
- ("a", "'"): 0xE1,
- ("a", ">"): 0xE2,
- ("a", "?"): 0xE3,
- ("a", ":"): 0xE4,
- ("a", "a"): 0xE5,
- ("a", "e"): 0xE6,
- ("c", ","): 0xE7,
- ("e", "!"): 0xE8,
- ("e", "'"): 0xE9,
- ("e", ">"): 0xEA,
- ("e", ":"): 0xEB,
- ("i", "!"): 0xEC,
- ("i", "'"): 0xED,
- ("i", ">"): 0xEE,
- ("i", ":"): 0xEF,
- ("d", "-"): 0xF0,
- ("n", "?"): 0xF1,
- ("o", "!"): 0xF2,
- ("o", "'"): 0xF3,
- ("o", ">"): 0xF4,
- ("o", "?"): 0xF5,
- ("o", ":"): 0xF6,
- ("-", ":"): 0xF7,
- ("o", "/"): 0xF8,
- ("u", "!"): 0xF9,
- ("u", "'"): 0xFA,
- ("u", ">"): 0xFB,
- ("u", ":"): 0xFC,
- ("y", "'"): 0xFD,
- ("t", "h"): 0xFE,
- ("y", ":"): 0xFF,
- ("A", "-"): 0x0100,
- ("a", "-"): 0x0101,
- ("A", "("): 0x0102,
- ("a", "("): 0x0103,
- ("A", ";"): 0x0104,
- ("a", ";"): 0x0105,
- ("C", "'"): 0x0106,
- ("c", "'"): 0x0107,
- ("C", ">"): 0x0108,
- ("c", ">"): 0x0109,
- ("C", "."): 0x010A,
- ("c", "."): 0x010B,
- ("C", "<"): 0x010C,
- ("c", "<"): 0x010D,
- ("D", "<"): 0x010E,
- ("d", "<"): 0x010F,
- ("D", "/"): 0x0110,
- ("d", "/"): 0x0111,
- ("E", "-"): 0x0112,
- ("e", "-"): 0x0113,
- ("E", "("): 0x0114,
- ("e", "("): 0x0115,
- ("E", "."): 0x0116,
- ("e", "."): 0x0117,
- ("E", ";"): 0x0118,
- ("e", ";"): 0x0119,
- ("E", "<"): 0x011A,
- ("e", "<"): 0x011B,
- ("G", ">"): 0x011C,
- ("g", ">"): 0x011D,
- ("G", "("): 0x011E,
- ("g", "("): 0x011F,
- ("G", "."): 0x0120,
- ("g", "."): 0x0121,
- ("G", ","): 0x0122,
- ("g", ","): 0x0123,
- ("H", ">"): 0x0124,
- ("h", ">"): 0x0125,
- ("H", "/"): 0x0126,
- ("h", "/"): 0x0127,
- ("I", "?"): 0x0128,
- ("i", "?"): 0x0129,
- ("I", "-"): 0x012A,
- ("i", "-"): 0x012B,
- ("I", "("): 0x012C,
- ("i", "("): 0x012D,
- ("I", ";"): 0x012E,
- ("i", ";"): 0x012F,
- ("I", "."): 0x0130,
- ("i", "."): 0x0131,
- ("I", "J"): 0x0132,
- ("i", "j"): 0x0133,
- ("J", ">"): 0x0134,
- ("j", ">"): 0x0135,
- ("K", ","): 0x0136,
- ("k", ","): 0x0137,
- ("k", "k"): 0x0138,
- ("L", "'"): 0x0139,
- ("l", "'"): 0x013A,
- ("L", ","): 0x013B,
- ("l", ","): 0x013C,
- ("L", "<"): 0x013D,
- ("l", "<"): 0x013E,
- ("L", "."): 0x013F,
- ("l", "."): 0x0140,
- ("L", "/"): 0x0141,
- ("l", "/"): 0x0142,
- ("N", "'"): 0x0143,
- ("n", "'"): 0x0144,
- ("N", ","): 0x0145,
- ("n", ","): 0x0146,
- ("N", "<"): 0x0147,
- ("n", "<"): 0x0148,
- ("'", "n"): 0x0149,
- ("N", "G"): 0x014A,
- ("n", "g"): 0x014B,
- ("O", "-"): 0x014C,
- ("o", "-"): 0x014D,
- ("O", "("): 0x014E,
- ("o", "("): 0x014F,
- ("O", '"'): 0x0150,
- ("o", '"'): 0x0151,
- ("O", "E"): 0x0152,
- ("o", "e"): 0x0153,
- ("R", "'"): 0x0154,
- ("r", "'"): 0x0155,
- ("R", ","): 0x0156,
- ("r", ","): 0x0157,
- ("R", "<"): 0x0158,
- ("r", "<"): 0x0159,
- ("S", "'"): 0x015A,
- ("s", "'"): 0x015B,
- ("S", ">"): 0x015C,
- ("s", ">"): 0x015D,
- ("S", ","): 0x015E,
- ("s", ","): 0x015F,
- ("S", "<"): 0x0160,
- ("s", "<"): 0x0161,
- ("T", ","): 0x0162,
- ("t", ","): 0x0163,
- ("T", "<"): 0x0164,
- ("t", "<"): 0x0165,
- ("T", "/"): 0x0166,
- ("t", "/"): 0x0167,
- ("U", "?"): 0x0168,
- ("u", "?"): 0x0169,
- ("U", "-"): 0x016A,
- ("u", "-"): 0x016B,
- ("U", "("): 0x016C,
- ("u", "("): 0x016D,
- ("U", "0"): 0x016E,
- ("u", "0"): 0x016F,
- ("U", '"'): 0x0170,
- ("u", '"'): 0x0171,
- ("U", ";"): 0x0172,
- ("u", ";"): 0x0173,
- ("W", ">"): 0x0174,
- ("w", ">"): 0x0175,
- ("Y", ">"): 0x0176,
- ("y", ">"): 0x0177,
- ("Y", ":"): 0x0178,
- ("Z", "'"): 0x0179,
- ("z", "'"): 0x017A,
- ("Z", "."): 0x017B,
- ("z", "."): 0x017C,
- ("Z", "<"): 0x017D,
- ("z", "<"): 0x017E,
- ("O", "9"): 0x01A0,
- ("o", "9"): 0x01A1,
- ("O", "I"): 0x01A2,
- ("o", "i"): 0x01A3,
- ("y", "r"): 0x01A6,
- ("U", "9"): 0x01AF,
- ("u", "9"): 0x01B0,
- ("Z", "/"): 0x01B5,
- ("z", "/"): 0x01B6,
- ("E", "D"): 0x01B7,
- ("A", "<"): 0x01CD,
- ("a", "<"): 0x01CE,
- ("I", "<"): 0x01CF,
- ("i", "<"): 0x01D0,
- ("O", "<"): 0x01D1,
- ("o", "<"): 0x01D2,
- ("U", "<"): 0x01D3,
- ("u", "<"): 0x01D4,
- ("A", "1"): 0x01DE,
- ("a", "1"): 0x01DF,
- ("A", "7"): 0x01E0,
- ("a", "7"): 0x01E1,
- ("A", "3"): 0x01E2,
- ("a", "3"): 0x01E3,
- ("G", "/"): 0x01E4,
- ("g", "/"): 0x01E5,
- ("G", "<"): 0x01E6,
- ("g", "<"): 0x01E7,
- ("K", "<"): 0x01E8,
- ("k", "<"): 0x01E9,
- ("O", ";"): 0x01EA,
- ("o", ";"): 0x01EB,
- ("O", "1"): 0x01EC,
- ("o", "1"): 0x01ED,
- ("E", "Z"): 0x01EE,
- ("e", "z"): 0x01EF,
- ("j", "<"): 0x01F0,
- ("G", "'"): 0x01F4,
- ("g", "'"): 0x01F5,
- (";", "S"): 0x02BF,
- ("'", "<"): 0x02C7,
- ("'", "("): 0x02D8,
- ("'", "."): 0x02D9,
- ("'", "0"): 0x02DA,
- ("'", ";"): 0x02DB,
- ("'", '"'): 0x02DD,
- ("A", "%"): 0x0386,
- ("E", "%"): 0x0388,
- ("Y", "%"): 0x0389,
- ("I", "%"): 0x038A,
- ("O", "%"): 0x038C,
- ("U", "%"): 0x038E,
- ("W", "%"): 0x038F,
- ("i", "3"): 0x0390,
- ("A", "*"): 0x0391,
- ("B", "*"): 0x0392,
- ("G", "*"): 0x0393,
- ("D", "*"): 0x0394,
- ("E", "*"): 0x0395,
- ("Z", "*"): 0x0396,
- ("Y", "*"): 0x0397,
- ("H", "*"): 0x0398,
- ("I", "*"): 0x0399,
- ("K", "*"): 0x039A,
- ("L", "*"): 0x039B,
- ("M", "*"): 0x039C,
- ("N", "*"): 0x039D,
- ("C", "*"): 0x039E,
- ("O", "*"): 0x039F,
- ("P", "*"): 0x03A0,
- ("R", "*"): 0x03A1,
- ("S", "*"): 0x03A3,
- ("T", "*"): 0x03A4,
- ("U", "*"): 0x03A5,
- ("F", "*"): 0x03A6,
- ("X", "*"): 0x03A7,
- ("Q", "*"): 0x03A8,
- ("W", "*"): 0x03A9,
- ("J", "*"): 0x03AA,
- ("V", "*"): 0x03AB,
- ("a", "%"): 0x03AC,
- ("e", "%"): 0x03AD,
- ("y", "%"): 0x03AE,
- ("i", "%"): 0x03AF,
- ("u", "3"): 0x03B0,
- ("a", "*"): 0x03B1,
- ("b", "*"): 0x03B2,
- ("g", "*"): 0x03B3,
- ("d", "*"): 0x03B4,
- ("e", "*"): 0x03B5,
- ("z", "*"): 0x03B6,
- ("y", "*"): 0x03B7,
- ("h", "*"): 0x03B8,
- ("i", "*"): 0x03B9,
- ("k", "*"): 0x03BA,
- ("l", "*"): 0x03BB,
- ("m", "*"): 0x03BC,
- ("n", "*"): 0x03BD,
- ("c", "*"): 0x03BE,
- ("o", "*"): 0x03BF,
- ("p", "*"): 0x03C0,
- ("r", "*"): 0x03C1,
- ("*", "s"): 0x03C2,
- ("s", "*"): 0x03C3,
- ("t", "*"): 0x03C4,
- ("u", "*"): 0x03C5,
- ("f", "*"): 0x03C6,
- ("x", "*"): 0x03C7,
- ("q", "*"): 0x03C8,
- ("w", "*"): 0x03C9,
- ("j", "*"): 0x03CA,
- ("v", "*"): 0x03CB,
- ("o", "%"): 0x03CC,
- ("u", "%"): 0x03CD,
- ("w", "%"): 0x03CE,
- ("'", "G"): 0x03D8,
- (",", "G"): 0x03D9,
- ("T", "3"): 0x03DA,
- ("t", "3"): 0x03DB,
- ("M", "3"): 0x03DC,
- ("m", "3"): 0x03DD,
- ("K", "3"): 0x03DE,
- ("k", "3"): 0x03DF,
- ("P", "3"): 0x03E0,
- ("p", "3"): 0x03E1,
- ("'", "%"): 0x03F4,
- ("j", "3"): 0x03F5,
- ("I", "O"): 0x0401,
- ("D", "%"): 0x0402,
- ("G", "%"): 0x0403,
- ("I", "E"): 0x0404,
- ("D", "S"): 0x0405,
- ("I", "I"): 0x0406,
- ("Y", "I"): 0x0407,
- ("J", "%"): 0x0408,
- ("L", "J"): 0x0409,
- ("N", "J"): 0x040A,
- ("T", "s"): 0x040B,
- ("K", "J"): 0x040C,
- ("V", "%"): 0x040E,
- ("D", "Z"): 0x040F,
- ("A", "="): 0x0410,
- ("B", "="): 0x0411,
- ("V", "="): 0x0412,
- ("G", "="): 0x0413,
- ("D", "="): 0x0414,
- ("E", "="): 0x0415,
- ("Z", "%"): 0x0416,
- ("Z", "="): 0x0417,
- ("I", "="): 0x0418,
- ("J", "="): 0x0419,
- ("K", "="): 0x041A,
- ("L", "="): 0x041B,
- ("M", "="): 0x041C,
- ("N", "="): 0x041D,
- ("O", "="): 0x041E,
- ("P", "="): 0x041F,
- ("R", "="): 0x0420,
- ("S", "="): 0x0421,
- ("T", "="): 0x0422,
- ("U", "="): 0x0423,
- ("F", "="): 0x0424,
- ("H", "="): 0x0425,
- ("C", "="): 0x0426,
- ("C", "%"): 0x0427,
- ("S", "%"): 0x0428,
- ("S", "c"): 0x0429,
- ("=", '"'): 0x042A,
- ("Y", "="): 0x042B,
- ("%", '"'): 0x042C,
- ("J", "E"): 0x042D,
- ("J", "U"): 0x042E,
- ("J", "A"): 0x042F,
- ("a", "="): 0x0430,
- ("b", "="): 0x0431,
- ("v", "="): 0x0432,
- ("g", "="): 0x0433,
- ("d", "="): 0x0434,
- ("e", "="): 0x0435,
- ("z", "%"): 0x0436,
- ("z", "="): 0x0437,
- ("i", "="): 0x0438,
- ("j", "="): 0x0439,
- ("k", "="): 0x043A,
- ("l", "="): 0x043B,
- ("m", "="): 0x043C,
- ("n", "="): 0x043D,
- ("o", "="): 0x043E,
- ("p", "="): 0x043F,
- ("r", "="): 0x0440,
- ("s", "="): 0x0441,
- ("t", "="): 0x0442,
- ("u", "="): 0x0443,
- ("f", "="): 0x0444,
- ("h", "="): 0x0445,
- ("c", "="): 0x0446,
- ("c", "%"): 0x0447,
- ("s", "%"): 0x0448,
- ("s", "c"): 0x0449,
- ("=", "'"): 0x044A,
- ("y", "="): 0x044B,
- ("%", "'"): 0x044C,
- ("j", "e"): 0x044D,
- ("j", "u"): 0x044E,
- ("j", "a"): 0x044F,
- ("i", "o"): 0x0451,
- ("d", "%"): 0x0452,
- ("g", "%"): 0x0453,
- ("i", "e"): 0x0454,
- ("d", "s"): 0x0455,
- ("i", "i"): 0x0456,
- ("y", "i"): 0x0457,
- ("j", "%"): 0x0458,
- ("l", "j"): 0x0459,
- ("n", "j"): 0x045A,
- ("t", "s"): 0x045B,
- ("k", "j"): 0x045C,
- ("v", "%"): 0x045E,
- ("d", "z"): 0x045F,
- ("Y", "3"): 0x0462,
- ("y", "3"): 0x0463,
- ("O", "3"): 0x046A,
- ("o", "3"): 0x046B,
- ("F", "3"): 0x0472,
- ("f", "3"): 0x0473,
- ("V", "3"): 0x0474,
- ("v", "3"): 0x0475,
- ("C", "3"): 0x0480,
- ("c", "3"): 0x0481,
- ("G", "3"): 0x0490,
- ("g", "3"): 0x0491,
- ("A", "+"): 0x05D0,
- ("B", "+"): 0x05D1,
- ("G", "+"): 0x05D2,
- ("D", "+"): 0x05D3,
- ("H", "+"): 0x05D4,
- ("W", "+"): 0x05D5,
- ("Z", "+"): 0x05D6,
- ("X", "+"): 0x05D7,
- ("T", "j"): 0x05D8,
- ("J", "+"): 0x05D9,
- ("K", "%"): 0x05DA,
- ("K", "+"): 0x05DB,
- ("L", "+"): 0x05DC,
- ("M", "%"): 0x05DD,
- ("M", "+"): 0x05DE,
- ("N", "%"): 0x05DF,
- ("N", "+"): 0x05E0,
- ("S", "+"): 0x05E1,
- ("E", "+"): 0x05E2,
- ("P", "%"): 0x05E3,
- ("P", "+"): 0x05E4,
- ("Z", "j"): 0x05E5,
- ("Z", "J"): 0x05E6,
- ("Q", "+"): 0x05E7,
- ("R", "+"): 0x05E8,
- ("S", "h"): 0x05E9,
- ("T", "+"): 0x05EA,
- (",", "+"): 0x060C,
- (";", "+"): 0x061B,
- ("?", "+"): 0x061F,
- ("H", "'"): 0x0621,
- ("a", "M"): 0x0622,
- ("a", "H"): 0x0623,
- ("w", "H"): 0x0624,
- ("a", "h"): 0x0625,
- ("y", "H"): 0x0626,
- ("a", "+"): 0x0627,
- ("b", "+"): 0x0628,
- ("t", "m"): 0x0629,
- ("t", "+"): 0x062A,
- ("t", "k"): 0x062B,
- ("g", "+"): 0x062C,
- ("h", "k"): 0x062D,
- ("x", "+"): 0x062E,
- ("d", "+"): 0x062F,
- ("d", "k"): 0x0630,
- ("r", "+"): 0x0631,
- ("z", "+"): 0x0632,
- ("s", "+"): 0x0633,
- ("s", "n"): 0x0634,
- ("c", "+"): 0x0635,
- ("d", "d"): 0x0636,
- ("t", "j"): 0x0637,
- ("z", "H"): 0x0638,
- ("e", "+"): 0x0639,
- ("i", "+"): 0x063A,
- ("+", "+"): 0x0640,
- ("f", "+"): 0x0641,
- ("q", "+"): 0x0642,
- ("k", "+"): 0x0643,
- ("l", "+"): 0x0644,
- ("m", "+"): 0x0645,
- ("n", "+"): 0x0646,
- ("h", "+"): 0x0647,
- ("w", "+"): 0x0648,
- ("j", "+"): 0x0649,
- ("y", "+"): 0x064A,
- (":", "+"): 0x064B,
- ('"', "+"): 0x064C,
- ("=", "+"): 0x064D,
- ("/", "+"): 0x064E,
- ("'", "+"): 0x064F,
- ("1", "+"): 0x0650,
- ("3", "+"): 0x0651,
- ("0", "+"): 0x0652,
- ("a", "S"): 0x0670,
- ("p", "+"): 0x067E,
- ("v", "+"): 0x06A4,
- ("g", "f"): 0x06AF,
- ("0", "a"): 0x06F0,
- ("1", "a"): 0x06F1,
- ("2", "a"): 0x06F2,
- ("3", "a"): 0x06F3,
- ("4", "a"): 0x06F4,
- ("5", "a"): 0x06F5,
- ("6", "a"): 0x06F6,
- ("7", "a"): 0x06F7,
- ("8", "a"): 0x06F8,
- ("9", "a"): 0x06F9,
- ("B", "."): 0x1E02,
- ("b", "."): 0x1E03,
- ("B", "_"): 0x1E06,
- ("b", "_"): 0x1E07,
- ("D", "."): 0x1E0A,
- ("d", "."): 0x1E0B,
- ("D", "_"): 0x1E0E,
- ("d", "_"): 0x1E0F,
- ("D", ","): 0x1E10,
- ("d", ","): 0x1E11,
- ("F", "."): 0x1E1E,
- ("f", "."): 0x1E1F,
- ("G", "-"): 0x1E20,
- ("g", "-"): 0x1E21,
- ("H", "."): 0x1E22,
- ("h", "."): 0x1E23,
- ("H", ":"): 0x1E26,
- ("h", ":"): 0x1E27,
- ("H", ","): 0x1E28,
- ("h", ","): 0x1E29,
- ("K", "'"): 0x1E30,
- ("k", "'"): 0x1E31,
- ("K", "_"): 0x1E34,
- ("k", "_"): 0x1E35,
- ("L", "_"): 0x1E3A,
- ("l", "_"): 0x1E3B,
- ("M", "'"): 0x1E3E,
- ("m", "'"): 0x1E3F,
- ("M", "."): 0x1E40,
- ("m", "."): 0x1E41,
- ("N", "."): 0x1E44,
- ("n", "."): 0x1E45,
- ("N", "_"): 0x1E48,
- ("n", "_"): 0x1E49,
- ("P", "'"): 0x1E54,
- ("p", "'"): 0x1E55,
- ("P", "."): 0x1E56,
- ("p", "."): 0x1E57,
- ("R", "."): 0x1E58,
- ("r", "."): 0x1E59,
- ("R", "_"): 0x1E5E,
- ("r", "_"): 0x1E5F,
- ("S", "."): 0x1E60,
- ("s", "."): 0x1E61,
- ("T", "."): 0x1E6A,
- ("t", "."): 0x1E6B,
- ("T", "_"): 0x1E6E,
- ("t", "_"): 0x1E6F,
- ("V", "?"): 0x1E7C,
- ("v", "?"): 0x1E7D,
- ("W", "!"): 0x1E80,
- ("w", "!"): 0x1E81,
- ("W", "'"): 0x1E82,
- ("w", "'"): 0x1E83,
- ("W", ":"): 0x1E84,
- ("w", ":"): 0x1E85,
- ("W", "."): 0x1E86,
- ("w", "."): 0x1E87,
- ("X", "."): 0x1E8A,
- ("x", "."): 0x1E8B,
- ("X", ":"): 0x1E8C,
- ("x", ":"): 0x1E8D,
- ("Y", "."): 0x1E8E,
- ("y", "."): 0x1E8F,
- ("Z", ">"): 0x1E90,
- ("z", ">"): 0x1E91,
- ("Z", "_"): 0x1E94,
- ("z", "_"): 0x1E95,
- ("h", "_"): 0x1E96,
- ("t", ":"): 0x1E97,
- ("w", "0"): 0x1E98,
- ("y", "0"): 0x1E99,
- ("A", "2"): 0x1EA2,
- ("a", "2"): 0x1EA3,
- ("E", "2"): 0x1EBA,
- ("e", "2"): 0x1EBB,
- ("E", "?"): 0x1EBC,
- ("e", "?"): 0x1EBD,
- ("I", "2"): 0x1EC8,
- ("i", "2"): 0x1EC9,
- ("O", "2"): 0x1ECE,
- ("o", "2"): 0x1ECF,
- ("U", "2"): 0x1EE6,
- ("u", "2"): 0x1EE7,
- ("Y", "!"): 0x1EF2,
- ("y", "!"): 0x1EF3,
- ("Y", "2"): 0x1EF6,
- ("y", "2"): 0x1EF7,
- ("Y", "?"): 0x1EF8,
- ("y", "?"): 0x1EF9,
- (";", "'"): 0x1F00,
- (",", "'"): 0x1F01,
- (";", "!"): 0x1F02,
- (",", "!"): 0x1F03,
- ("?", ";"): 0x1F04,
- ("?", ","): 0x1F05,
- ("!", ":"): 0x1F06,
- ("?", ":"): 0x1F07,
- ("1", "N"): 0x2002,
- ("1", "M"): 0x2003,
- ("3", "M"): 0x2004,
- ("4", "M"): 0x2005,
- ("6", "M"): 0x2006,
- ("1", "T"): 0x2009,
- ("1", "H"): 0x200A,
- ("-", "1"): 0x2010,
- ("-", "N"): 0x2013,
- ("-", "M"): 0x2014,
- ("-", "3"): 0x2015,
- ("!", "2"): 0x2016,
- ("=", "2"): 0x2017,
- ("'", "6"): 0x2018,
- ("'", "9"): 0x2019,
- (".", "9"): 0x201A,
- ("9", "'"): 0x201B,
- ('"', "6"): 0x201C,
- ('"', "9"): 0x201D,
- (":", "9"): 0x201E,
- ("9", '"'): 0x201F,
- ("/", "-"): 0x2020,
- ("/", "="): 0x2021,
- (".", "."): 0x2025,
- ("%", "0"): 0x2030,
- ("1", "'"): 0x2032,
- ("2", "'"): 0x2033,
- ("3", "'"): 0x2034,
- ("1", '"'): 0x2035,
- ("2", '"'): 0x2036,
- ("3", '"'): 0x2037,
- ("C", "a"): 0x2038,
- ("<", "1"): 0x2039,
- (">", "1"): 0x203A,
- (":", "X"): 0x203B,
- ("'", "-"): 0x203E,
- ("/", "f"): 0x2044,
- ("0", "S"): 0x2070,
- ("4", "S"): 0x2074,
- ("5", "S"): 0x2075,
- ("6", "S"): 0x2076,
- ("7", "S"): 0x2077,
- ("8", "S"): 0x2078,
- ("9", "S"): 0x2079,
- ("+", "S"): 0x207A,
- ("-", "S"): 0x207B,
- ("=", "S"): 0x207C,
- ("(", "S"): 0x207D,
- (")", "S"): 0x207E,
- ("n", "S"): 0x207F,
- ("0", "s"): 0x2080,
- ("1", "s"): 0x2081,
- ("2", "s"): 0x2082,
- ("3", "s"): 0x2083,
- ("4", "s"): 0x2084,
- ("5", "s"): 0x2085,
- ("6", "s"): 0x2086,
- ("7", "s"): 0x2087,
- ("8", "s"): 0x2088,
- ("9", "s"): 0x2089,
- ("+", "s"): 0x208A,
- ("-", "s"): 0x208B,
- ("=", "s"): 0x208C,
- ("(", "s"): 0x208D,
- (")", "s"): 0x208E,
- ("L", "i"): 0x20A4,
- ("P", "t"): 0x20A7,
- ("W", "="): 0x20A9,
- ("=", "e"): 0x20AC, # euro
- ("E", "u"): 0x20AC, # euro
- ("=", "R"): 0x20BD, # rouble
- ("=", "P"): 0x20BD, # rouble
- ("o", "C"): 0x2103,
- ("c", "o"): 0x2105,
- ("o", "F"): 0x2109,
- ("N", "0"): 0x2116,
- ("P", "O"): 0x2117,
- ("R", "x"): 0x211E,
- ("S", "M"): 0x2120,
- ("T", "M"): 0x2122,
- ("O", "m"): 0x2126,
- ("A", "O"): 0x212B,
- ("1", "3"): 0x2153,
- ("2", "3"): 0x2154,
- ("1", "5"): 0x2155,
- ("2", "5"): 0x2156,
- ("3", "5"): 0x2157,
- ("4", "5"): 0x2158,
- ("1", "6"): 0x2159,
- ("5", "6"): 0x215A,
- ("1", "8"): 0x215B,
- ("3", "8"): 0x215C,
- ("5", "8"): 0x215D,
- ("7", "8"): 0x215E,
- ("1", "R"): 0x2160,
- ("2", "R"): 0x2161,
- ("3", "R"): 0x2162,
- ("4", "R"): 0x2163,
- ("5", "R"): 0x2164,
- ("6", "R"): 0x2165,
- ("7", "R"): 0x2166,
- ("8", "R"): 0x2167,
- ("9", "R"): 0x2168,
- ("a", "R"): 0x2169,
- ("b", "R"): 0x216A,
- ("c", "R"): 0x216B,
- ("1", "r"): 0x2170,
- ("2", "r"): 0x2171,
- ("3", "r"): 0x2172,
- ("4", "r"): 0x2173,
- ("5", "r"): 0x2174,
- ("6", "r"): 0x2175,
- ("7", "r"): 0x2176,
- ("8", "r"): 0x2177,
- ("9", "r"): 0x2178,
- ("a", "r"): 0x2179,
- ("b", "r"): 0x217A,
- ("c", "r"): 0x217B,
- ("<", "-"): 0x2190,
- ("-", "!"): 0x2191,
- ("-", ">"): 0x2192,
- ("-", "v"): 0x2193,
- ("<", ">"): 0x2194,
- ("U", "D"): 0x2195,
- ("<", "="): 0x21D0,
- ("=", ">"): 0x21D2,
- ("=", "="): 0x21D4,
- ("F", "A"): 0x2200,
- ("d", "P"): 0x2202,
- ("T", "E"): 0x2203,
- ("/", "0"): 0x2205,
- ("D", "E"): 0x2206,
- ("N", "B"): 0x2207,
- ("(", "-"): 0x2208,
- ("-", ")"): 0x220B,
- ("*", "P"): 0x220F,
- ("+", "Z"): 0x2211,
- ("-", "2"): 0x2212,
- ("-", "+"): 0x2213,
- ("*", "-"): 0x2217,
- ("O", "b"): 0x2218,
- ("S", "b"): 0x2219,
- ("R", "T"): 0x221A,
- ("0", "("): 0x221D,
- ("0", "0"): 0x221E,
- ("-", "L"): 0x221F,
- ("-", "V"): 0x2220,
- ("P", "P"): 0x2225,
- ("A", "N"): 0x2227,
- ("O", "R"): 0x2228,
- ("(", "U"): 0x2229,
- (")", "U"): 0x222A,
- ("I", "n"): 0x222B,
- ("D", "I"): 0x222C,
- ("I", "o"): 0x222E,
- (".", ":"): 0x2234,
- (":", "."): 0x2235,
- (":", "R"): 0x2236,
- (":", ":"): 0x2237,
- ("?", "1"): 0x223C,
- ("C", "G"): 0x223E,
- ("?", "-"): 0x2243,
- ("?", "="): 0x2245,
- ("?", "2"): 0x2248,
- ("=", "?"): 0x224C,
- ("H", "I"): 0x2253,
- ("!", "="): 0x2260,
- ("=", "3"): 0x2261,
- ("=", "<"): 0x2264,
- (">", "="): 0x2265,
- ("<", "*"): 0x226A,
- ("*", ">"): 0x226B,
- ("!", "<"): 0x226E,
- ("!", ">"): 0x226F,
- ("(", "C"): 0x2282,
- (")", "C"): 0x2283,
- ("(", "_"): 0x2286,
- (")", "_"): 0x2287,
- ("0", "."): 0x2299,
- ("0", "2"): 0x229A,
- ("-", "T"): 0x22A5,
- (".", "P"): 0x22C5,
- (":", "3"): 0x22EE,
- (".", "3"): 0x22EF,
- ("E", "h"): 0x2302,
- ("<", "7"): 0x2308,
- (">", "7"): 0x2309,
- ("7", "<"): 0x230A,
- ("7", ">"): 0x230B,
- ("N", "I"): 0x2310,
- ("(", "A"): 0x2312,
- ("T", "R"): 0x2315,
- ("I", "u"): 0x2320,
- ("I", "l"): 0x2321,
- ("<", "/"): 0x2329,
- ("/", ">"): 0x232A,
- ("V", "s"): 0x2423,
- ("1", "h"): 0x2440,
- ("3", "h"): 0x2441,
- ("2", "h"): 0x2442,
- ("4", "h"): 0x2443,
- ("1", "j"): 0x2446,
- ("2", "j"): 0x2447,
- ("3", "j"): 0x2448,
- ("4", "j"): 0x2449,
- ("1", "."): 0x2488,
- ("2", "."): 0x2489,
- ("3", "."): 0x248A,
- ("4", "."): 0x248B,
- ("5", "."): 0x248C,
- ("6", "."): 0x248D,
- ("7", "."): 0x248E,
- ("8", "."): 0x248F,
- ("9", "."): 0x2490,
- ("h", "h"): 0x2500,
- ("H", "H"): 0x2501,
- ("v", "v"): 0x2502,
- ("V", "V"): 0x2503,
- ("3", "-"): 0x2504,
- ("3", "_"): 0x2505,
- ("3", "!"): 0x2506,
- ("3", "/"): 0x2507,
- ("4", "-"): 0x2508,
- ("4", "_"): 0x2509,
- ("4", "!"): 0x250A,
- ("4", "/"): 0x250B,
- ("d", "r"): 0x250C,
- ("d", "R"): 0x250D,
- ("D", "r"): 0x250E,
- ("D", "R"): 0x250F,
- ("d", "l"): 0x2510,
- ("d", "L"): 0x2511,
- ("D", "l"): 0x2512,
- ("L", "D"): 0x2513,
- ("u", "r"): 0x2514,
- ("u", "R"): 0x2515,
- ("U", "r"): 0x2516,
- ("U", "R"): 0x2517,
- ("u", "l"): 0x2518,
- ("u", "L"): 0x2519,
- ("U", "l"): 0x251A,
- ("U", "L"): 0x251B,
- ("v", "r"): 0x251C,
- ("v", "R"): 0x251D,
- ("V", "r"): 0x2520,
- ("V", "R"): 0x2523,
- ("v", "l"): 0x2524,
- ("v", "L"): 0x2525,
- ("V", "l"): 0x2528,
- ("V", "L"): 0x252B,
- ("d", "h"): 0x252C,
- ("d", "H"): 0x252F,
- ("D", "h"): 0x2530,
- ("D", "H"): 0x2533,
- ("u", "h"): 0x2534,
- ("u", "H"): 0x2537,
- ("U", "h"): 0x2538,
- ("U", "H"): 0x253B,
- ("v", "h"): 0x253C,
- ("v", "H"): 0x253F,
- ("V", "h"): 0x2542,
- ("V", "H"): 0x254B,
- ("F", "D"): 0x2571,
- ("B", "D"): 0x2572,
- ("T", "B"): 0x2580,
- ("L", "B"): 0x2584,
- ("F", "B"): 0x2588,
- ("l", "B"): 0x258C,
- ("R", "B"): 0x2590,
- (".", "S"): 0x2591,
- (":", "S"): 0x2592,
- ("?", "S"): 0x2593,
- ("f", "S"): 0x25A0,
- ("O", "S"): 0x25A1,
- ("R", "O"): 0x25A2,
- ("R", "r"): 0x25A3,
- ("R", "F"): 0x25A4,
- ("R", "Y"): 0x25A5,
- ("R", "H"): 0x25A6,
- ("R", "Z"): 0x25A7,
- ("R", "K"): 0x25A8,
- ("R", "X"): 0x25A9,
- ("s", "B"): 0x25AA,
- ("S", "R"): 0x25AC,
- ("O", "r"): 0x25AD,
- ("U", "T"): 0x25B2,
- ("u", "T"): 0x25B3,
- ("P", "R"): 0x25B6,
- ("T", "r"): 0x25B7,
- ("D", "t"): 0x25BC,
- ("d", "T"): 0x25BD,
- ("P", "L"): 0x25C0,
- ("T", "l"): 0x25C1,
- ("D", "b"): 0x25C6,
- ("D", "w"): 0x25C7,
- ("L", "Z"): 0x25CA,
- ("0", "m"): 0x25CB,
- ("0", "o"): 0x25CE,
- ("0", "M"): 0x25CF,
- ("0", "L"): 0x25D0,
- ("0", "R"): 0x25D1,
- ("S", "n"): 0x25D8,
- ("I", "c"): 0x25D9,
- ("F", "d"): 0x25E2,
- ("B", "d"): 0x25E3,
- ("*", "2"): 0x2605,
- ("*", "1"): 0x2606,
- ("<", "H"): 0x261C,
- (">", "H"): 0x261E,
- ("0", "u"): 0x263A,
- ("0", "U"): 0x263B,
- ("S", "U"): 0x263C,
- ("F", "m"): 0x2640,
- ("M", "l"): 0x2642,
- ("c", "S"): 0x2660,
- ("c", "H"): 0x2661,
- ("c", "D"): 0x2662,
- ("c", "C"): 0x2663,
- ("M", "d"): 0x2669,
- ("M", "8"): 0x266A,
- ("M", "2"): 0x266B,
- ("M", "b"): 0x266D,
- ("M", "x"): 0x266E,
- ("M", "X"): 0x266F,
- ("O", "K"): 0x2713,
- ("X", "X"): 0x2717,
- ("-", "X"): 0x2720,
- ("I", "S"): 0x3000,
- (",", "_"): 0x3001,
- (".", "_"): 0x3002,
- ("+", '"'): 0x3003,
- ("+", "_"): 0x3004,
- ("*", "_"): 0x3005,
- (";", "_"): 0x3006,
- ("0", "_"): 0x3007,
- ("<", "+"): 0x300A,
- (">", "+"): 0x300B,
- ("<", "'"): 0x300C,
- (">", "'"): 0x300D,
- ("<", '"'): 0x300E,
- (">", '"'): 0x300F,
- ("(", '"'): 0x3010,
- (")", '"'): 0x3011,
- ("=", "T"): 0x3012,
- ("=", "_"): 0x3013,
- ("(", "'"): 0x3014,
- (")", "'"): 0x3015,
- ("(", "I"): 0x3016,
- (")", "I"): 0x3017,
- ("-", "?"): 0x301C,
- ("A", "5"): 0x3041,
- ("a", "5"): 0x3042,
- ("I", "5"): 0x3043,
- ("i", "5"): 0x3044,
- ("U", "5"): 0x3045,
- ("u", "5"): 0x3046,
- ("E", "5"): 0x3047,
- ("e", "5"): 0x3048,
- ("O", "5"): 0x3049,
- ("o", "5"): 0x304A,
- ("k", "a"): 0x304B,
- ("g", "a"): 0x304C,
- ("k", "i"): 0x304D,
- ("g", "i"): 0x304E,
- ("k", "u"): 0x304F,
- ("g", "u"): 0x3050,
- ("k", "e"): 0x3051,
- ("g", "e"): 0x3052,
- ("k", "o"): 0x3053,
- ("g", "o"): 0x3054,
- ("s", "a"): 0x3055,
- ("z", "a"): 0x3056,
- ("s", "i"): 0x3057,
- ("z", "i"): 0x3058,
- ("s", "u"): 0x3059,
- ("z", "u"): 0x305A,
- ("s", "e"): 0x305B,
- ("z", "e"): 0x305C,
- ("s", "o"): 0x305D,
- ("z", "o"): 0x305E,
- ("t", "a"): 0x305F,
- ("d", "a"): 0x3060,
- ("t", "i"): 0x3061,
- ("d", "i"): 0x3062,
- ("t", "U"): 0x3063,
- ("t", "u"): 0x3064,
- ("d", "u"): 0x3065,
- ("t", "e"): 0x3066,
- ("d", "e"): 0x3067,
- ("t", "o"): 0x3068,
- ("d", "o"): 0x3069,
- ("n", "a"): 0x306A,
- ("n", "i"): 0x306B,
- ("n", "u"): 0x306C,
- ("n", "e"): 0x306D,
- ("n", "o"): 0x306E,
- ("h", "a"): 0x306F,
- ("b", "a"): 0x3070,
- ("p", "a"): 0x3071,
- ("h", "i"): 0x3072,
- ("b", "i"): 0x3073,
- ("p", "i"): 0x3074,
- ("h", "u"): 0x3075,
- ("b", "u"): 0x3076,
- ("p", "u"): 0x3077,
- ("h", "e"): 0x3078,
- ("b", "e"): 0x3079,
- ("p", "e"): 0x307A,
- ("h", "o"): 0x307B,
- ("b", "o"): 0x307C,
- ("p", "o"): 0x307D,
- ("m", "a"): 0x307E,
- ("m", "i"): 0x307F,
- ("m", "u"): 0x3080,
- ("m", "e"): 0x3081,
- ("m", "o"): 0x3082,
- ("y", "A"): 0x3083,
- ("y", "a"): 0x3084,
- ("y", "U"): 0x3085,
- ("y", "u"): 0x3086,
- ("y", "O"): 0x3087,
- ("y", "o"): 0x3088,
- ("r", "a"): 0x3089,
- ("r", "i"): 0x308A,
- ("r", "u"): 0x308B,
- ("r", "e"): 0x308C,
- ("r", "o"): 0x308D,
- ("w", "A"): 0x308E,
- ("w", "a"): 0x308F,
- ("w", "i"): 0x3090,
- ("w", "e"): 0x3091,
- ("w", "o"): 0x3092,
- ("n", "5"): 0x3093,
- ("v", "u"): 0x3094,
- ('"', "5"): 0x309B,
- ("0", "5"): 0x309C,
- ("*", "5"): 0x309D,
- ("+", "5"): 0x309E,
- ("a", "6"): 0x30A1,
- ("A", "6"): 0x30A2,
- ("i", "6"): 0x30A3,
- ("I", "6"): 0x30A4,
- ("u", "6"): 0x30A5,
- ("U", "6"): 0x30A6,
- ("e", "6"): 0x30A7,
- ("E", "6"): 0x30A8,
- ("o", "6"): 0x30A9,
- ("O", "6"): 0x30AA,
- ("K", "a"): 0x30AB,
- ("G", "a"): 0x30AC,
- ("K", "i"): 0x30AD,
- ("G", "i"): 0x30AE,
- ("K", "u"): 0x30AF,
- ("G", "u"): 0x30B0,
- ("K", "e"): 0x30B1,
- ("G", "e"): 0x30B2,
- ("K", "o"): 0x30B3,
- ("G", "o"): 0x30B4,
- ("S", "a"): 0x30B5,
- ("Z", "a"): 0x30B6,
- ("S", "i"): 0x30B7,
- ("Z", "i"): 0x30B8,
- ("S", "u"): 0x30B9,
- ("Z", "u"): 0x30BA,
- ("S", "e"): 0x30BB,
- ("Z", "e"): 0x30BC,
- ("S", "o"): 0x30BD,
- ("Z", "o"): 0x30BE,
- ("T", "a"): 0x30BF,
- ("D", "a"): 0x30C0,
- ("T", "i"): 0x30C1,
- ("D", "i"): 0x30C2,
- ("T", "U"): 0x30C3,
- ("T", "u"): 0x30C4,
- ("D", "u"): 0x30C5,
- ("T", "e"): 0x30C6,
- ("D", "e"): 0x30C7,
- ("T", "o"): 0x30C8,
- ("D", "o"): 0x30C9,
- ("N", "a"): 0x30CA,
- ("N", "i"): 0x30CB,
- ("N", "u"): 0x30CC,
- ("N", "e"): 0x30CD,
- ("N", "o"): 0x30CE,
- ("H", "a"): 0x30CF,
- ("B", "a"): 0x30D0,
- ("P", "a"): 0x30D1,
- ("H", "i"): 0x30D2,
- ("B", "i"): 0x30D3,
- ("P", "i"): 0x30D4,
- ("H", "u"): 0x30D5,
- ("B", "u"): 0x30D6,
- ("P", "u"): 0x30D7,
- ("H", "e"): 0x30D8,
- ("B", "e"): 0x30D9,
- ("P", "e"): 0x30DA,
- ("H", "o"): 0x30DB,
- ("B", "o"): 0x30DC,
- ("P", "o"): 0x30DD,
- ("M", "a"): 0x30DE,
- ("M", "i"): 0x30DF,
- ("M", "u"): 0x30E0,
- ("M", "e"): 0x30E1,
- ("M", "o"): 0x30E2,
- ("Y", "A"): 0x30E3,
- ("Y", "a"): 0x30E4,
- ("Y", "U"): 0x30E5,
- ("Y", "u"): 0x30E6,
- ("Y", "O"): 0x30E7,
- ("Y", "o"): 0x30E8,
- ("R", "a"): 0x30E9,
- ("R", "i"): 0x30EA,
- ("R", "u"): 0x30EB,
- ("R", "e"): 0x30EC,
- ("R", "o"): 0x30ED,
- ("W", "A"): 0x30EE,
- ("W", "a"): 0x30EF,
- ("W", "i"): 0x30F0,
- ("W", "e"): 0x30F1,
- ("W", "o"): 0x30F2,
- ("N", "6"): 0x30F3,
- ("V", "u"): 0x30F4,
- ("K", "A"): 0x30F5,
- ("K", "E"): 0x30F6,
- ("V", "a"): 0x30F7,
- ("V", "i"): 0x30F8,
- ("V", "e"): 0x30F9,
- ("V", "o"): 0x30FA,
- (".", "6"): 0x30FB,
- ("-", "6"): 0x30FC,
- ("*", "6"): 0x30FD,
- ("+", "6"): 0x30FE,
- ("b", "4"): 0x3105,
- ("p", "4"): 0x3106,
- ("m", "4"): 0x3107,
- ("f", "4"): 0x3108,
- ("d", "4"): 0x3109,
- ("t", "4"): 0x310A,
- ("n", "4"): 0x310B,
- ("l", "4"): 0x310C,
- ("g", "4"): 0x310D,
- ("k", "4"): 0x310E,
- ("h", "4"): 0x310F,
- ("j", "4"): 0x3110,
- ("q", "4"): 0x3111,
- ("x", "4"): 0x3112,
- ("z", "h"): 0x3113,
- ("c", "h"): 0x3114,
- ("s", "h"): 0x3115,
- ("r", "4"): 0x3116,
- ("z", "4"): 0x3117,
- ("c", "4"): 0x3118,
- ("s", "4"): 0x3119,
- ("a", "4"): 0x311A,
- ("o", "4"): 0x311B,
- ("e", "4"): 0x311C,
- ("a", "i"): 0x311E,
- ("e", "i"): 0x311F,
- ("a", "u"): 0x3120,
- ("o", "u"): 0x3121,
- ("a", "n"): 0x3122,
- ("e", "n"): 0x3123,
- ("a", "N"): 0x3124,
- ("e", "N"): 0x3125,
- ("e", "r"): 0x3126,
- ("i", "4"): 0x3127,
- ("u", "4"): 0x3128,
- ("i", "u"): 0x3129,
- ("v", "4"): 0x312A,
- ("n", "G"): 0x312B,
- ("g", "n"): 0x312C,
- ("1", "c"): 0x3220,
- ("2", "c"): 0x3221,
- ("3", "c"): 0x3222,
- ("4", "c"): 0x3223,
- ("5", "c"): 0x3224,
- ("6", "c"): 0x3225,
- ("7", "c"): 0x3226,
- ("8", "c"): 0x3227,
- ("9", "c"): 0x3228,
- # code points 0xe000 - 0xefff excluded, they have no assigned
- # characters, only used in proposals.
- ("f", "f"): 0xFB00,
- ("f", "i"): 0xFB01,
- ("f", "l"): 0xFB02,
- ("f", "t"): 0xFB05,
- ("s", "t"): 0xFB06,
- # Vim 5.x compatible digraphs that don't conflict with the above
- ("~", "!"): 161,
- ("c", "|"): 162,
- ("$", "$"): 163,
- ("o", "x"): 164, # currency symbol in ISO 8859-1
- ("Y", "-"): 165,
- ("|", "|"): 166,
- ("c", "O"): 169,
- ("-", ","): 172,
- ("-", "="): 175,
- ("~", "o"): 176,
- ("2", "2"): 178,
- ("3", "3"): 179,
- ("p", "p"): 182,
- ("~", "."): 183,
- ("1", "1"): 185,
- ("~", "?"): 191,
- ("A", "`"): 192,
- ("A", "^"): 194,
- ("A", "~"): 195,
- ("A", '"'): 196,
- ("A", "@"): 197,
- ("E", "`"): 200,
- ("E", "^"): 202,
- ("E", '"'): 203,
- ("I", "`"): 204,
- ("I", "^"): 206,
- ("I", '"'): 207,
- ("N", "~"): 209,
- ("O", "`"): 210,
- ("O", "^"): 212,
- ("O", "~"): 213,
- ("/", "\\"): 215, # multiplication symbol in ISO 8859-1
- ("U", "`"): 217,
- ("U", "^"): 219,
- ("I", "p"): 222,
- ("a", "`"): 224,
- ("a", "^"): 226,
- ("a", "~"): 227,
- ("a", '"'): 228,
- ("a", "@"): 229,
- ("e", "`"): 232,
- ("e", "^"): 234,
- ("e", '"'): 235,
- ("i", "`"): 236,
- ("i", "^"): 238,
- ("n", "~"): 241,
- ("o", "`"): 242,
- ("o", "^"): 244,
- ("o", "~"): 245,
- ("u", "`"): 249,
- ("u", "^"): 251,
- ("y", '"'): 255,
-}
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/emacs_state.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/emacs_state.py
deleted file mode 100644
index 4c996224a07..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/emacs_state.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from typing import List, Optional
-
-from .key_processor import KeyPress
-
-__all__ = [
- "EmacsState",
-]
-
-
-class EmacsState:
- """
- Mutable class to hold Emacs specific state.
- """
-
- def __init__(self) -> None:
- # Simple macro recording. (Like Readline does.)
- # (For Emacs mode.)
- self.macro: Optional[List[KeyPress]] = []
- self.current_recording: Optional[List[KeyPress]] = None
-
- def reset(self) -> None:
- self.current_recording = None
-
- @property
- def is_recording(self) -> bool:
- "Tell whether we are recording a macro."
- return self.current_recording is not None
-
- def start_macro(self) -> None:
- "Start recording macro."
- self.current_recording = []
-
- def end_macro(self) -> None:
- "End recording macro."
- self.macro = self.current_recording
- self.current_recording = None
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/key_bindings.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/key_bindings.py
deleted file mode 100644
index 03bc79ef01d..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/key_bindings.py
+++ /dev/null
@@ -1,672 +0,0 @@
-"""
-Key bindings registry.
-
-A `KeyBindings` object is a container that holds a list of key bindings. It has a
-very efficient internal data structure for checking which key bindings apply
-for a pressed key.
-
-Typical usage::
-
- kb = KeyBindings()
-
- @kb.add(Keys.ControlX, Keys.ControlC, filter=INSERT)
- def handler(event):
- # Handle ControlX-ControlC key sequence.
- pass
-
-It is also possible to combine multiple KeyBindings objects. We do this in the
-default key bindings. There are some KeyBindings objects that contain the Emacs
-bindings, while others contain the Vi bindings. They are merged together using
-`merge_key_bindings`.
-
-We also have a `ConditionalKeyBindings` object that can enable/disable a group of
-key bindings at once.
-
-
-It is also possible to add a filter to a function, before a key binding has
-been assigned, through the `key_binding` decorator.::
-
- # First define a key handler with the `filter`.
- @key_binding(filter=condition)
- def my_key_binding(event):
- ...
-
- # Later, add it to the key bindings.
- kb.add(Keys.A, my_key_binding)
-"""
-from abc import ABCMeta, abstractmethod, abstractproperty
-from inspect import isawaitable
-from typing import (
- TYPE_CHECKING,
- Awaitable,
- Callable,
- Hashable,
- List,
- Optional,
- Sequence,
- Tuple,
- TypeVar,
- Union,
- cast,
-)
-
-from prompt_toolkit.cache import SimpleCache
-from prompt_toolkit.filters import FilterOrBool, Never, to_filter
-from prompt_toolkit.keys import KEY_ALIASES, Keys
-
-if TYPE_CHECKING:
- # Avoid circular imports.
- from .key_processor import KeyPressEvent
-
- # The only two return values for a mouse hander (and key bindings) are
- # `None` and `NotImplemented`. For the type checker it's best to annotate
- # this as `object`. (The consumer never expects a more specific instance:
- # checking for NotImplemented can be done using `is NotImplemented`.)
- NotImplementedOrNone = object
- # Other non-working options are:
- # * Optional[Literal[NotImplemented]]
- # --> Doesn't work, Literal can't take an Any.
- # * None
- # --> Doesn't work. We can't assign the result of a function that
- # returns `None` to a variable.
- # * Any
- # --> Works, but too broad.
-
-
-__all__ = [
- "NotImplementedOrNone",
- "Binding",
- "KeyBindingsBase",
- "KeyBindings",
- "ConditionalKeyBindings",
- "merge_key_bindings",
- "DynamicKeyBindings",
- "GlobalOnlyKeyBindings",
-]
-
-# Key bindings can be regular functions or coroutines.
-# In both cases, if they return `NotImplemented`, the UI won't be invalidated.
-# This is mainly used in case of mouse move events, to prevent excessive
-# repainting during mouse move events.
-KeyHandlerCallable = Callable[
- ["KeyPressEvent"], Union["NotImplementedOrNone", Awaitable["NotImplementedOrNone"]]
-]
-
-
-class Binding:
- """
- Key binding: (key sequence + handler + filter).
- (Immutable binding class.)
-
- :param record_in_macro: When True, don't record this key binding when a
- macro is recorded.
- """
-
- def __init__(
- self,
- keys: Tuple[Union[Keys, str], ...],
- handler: KeyHandlerCallable,
- filter: FilterOrBool = True,
- eager: FilterOrBool = False,
- is_global: FilterOrBool = False,
- save_before: Callable[["KeyPressEvent"], bool] = (lambda e: True),
- record_in_macro: FilterOrBool = True,
- ) -> None:
- self.keys = keys
- self.handler = handler
- self.filter = to_filter(filter)
- self.eager = to_filter(eager)
- self.is_global = to_filter(is_global)
- self.save_before = save_before
- self.record_in_macro = to_filter(record_in_macro)
-
- def call(self, event: "KeyPressEvent") -> None:
- result = self.handler(event)
-
- # If the handler is a coroutine, create an asyncio task.
- if isawaitable(result):
- awaitable = cast(Awaitable["NotImplementedOrNone"], result)
-
- async def bg_task() -> None:
- result = await awaitable
- if result != NotImplemented:
- event.app.invalidate()
-
- event.app.create_background_task(bg_task())
-
- elif result != NotImplemented:
- event.app.invalidate()
-
- def __repr__(self) -> str:
- return "{}(keys={!r}, handler={!r})".format(
- self.__class__.__name__,
- self.keys,
- self.handler,
- )
-
-
-# Sequence of keys presses.
-KeysTuple = Tuple[Union[Keys, str], ...]
-
-
-class KeyBindingsBase(metaclass=ABCMeta):
- """
- Interface for a KeyBindings.
- """
-
- @abstractproperty
- def _version(self) -> Hashable:
- """
- For cache invalidation. - This should increase every time that
- something changes.
- """
- return 0
-
- @abstractmethod
- def get_bindings_for_keys(self, keys: KeysTuple) -> List[Binding]:
- """
- Return a list of key bindings that can handle these keys.
- (This return also inactive bindings, so the `filter` still has to be
- called, for checking it.)
-
- :param keys: tuple of keys.
- """
- return []
-
- @abstractmethod
- def get_bindings_starting_with_keys(self, keys: KeysTuple) -> List[Binding]:
- """
- Return a list of key bindings that handle a key sequence starting with
- `keys`. (It does only return bindings for which the sequences are
- longer than `keys`. And like `get_bindings_for_keys`, it also includes
- inactive bindings.)
-
- :param keys: tuple of keys.
- """
- return []
-
- @abstractproperty
- def bindings(self) -> List[Binding]:
- """
- List of `Binding` objects.
- (These need to be exposed, so that `KeyBindings` objects can be merged
- together.)
- """
- return []
-
- # `add` and `remove` don't have to be part of this interface.
-
-
-T = TypeVar("T", bound=Union[KeyHandlerCallable, Binding])
-
-
-class KeyBindings(KeyBindingsBase):
- """
- A container for a set of key bindings.
-
- Example usage::
-
- kb = KeyBindings()
-
- @kb.add('c-t')
- def _(event):
- print('Control-T pressed')
-
- @kb.add('c-a', 'c-b')
- def _(event):
- print('Control-A pressed, followed by Control-B')
-
- @kb.add('c-x', filter=is_searching)
- def _(event):
- print('Control-X pressed') # Works only if we are searching.
-
- """
-
- def __init__(self) -> None:
- self._bindings: List[Binding] = []
- self._get_bindings_for_keys_cache: SimpleCache[
- KeysTuple, List[Binding]
- ] = SimpleCache(maxsize=10000)
- self._get_bindings_starting_with_keys_cache: SimpleCache[
- KeysTuple, List[Binding]
- ] = SimpleCache(maxsize=1000)
- self.__version = 0 # For cache invalidation.
-
- def _clear_cache(self) -> None:
- self.__version += 1
- self._get_bindings_for_keys_cache.clear()
- self._get_bindings_starting_with_keys_cache.clear()
-
- @property
- def bindings(self) -> List[Binding]:
- return self._bindings
-
- @property
- def _version(self) -> Hashable:
- return self.__version
-
- def add(
- self,
- *keys: Union[Keys, str],
- filter: FilterOrBool = True,
- eager: FilterOrBool = False,
- is_global: FilterOrBool = False,
- save_before: Callable[["KeyPressEvent"], bool] = (lambda e: True),
- record_in_macro: FilterOrBool = True,
- ) -> Callable[[T], T]:
- """
- Decorator for adding a key bindings.
-
- :param filter: :class:`~prompt_toolkit.filters.Filter` to determine
- when this key binding is active.
- :param eager: :class:`~prompt_toolkit.filters.Filter` or `bool`.
- When True, ignore potential longer matches when this key binding is
- hit. E.g. when there is an active eager key binding for Ctrl-X,
- execute the handler immediately and ignore the key binding for
- Ctrl-X Ctrl-E of which it is a prefix.
- :param is_global: When this key bindings is added to a `Container` or
- `Control`, make it a global (always active) binding.
- :param save_before: Callable that takes an `Event` and returns True if
- we should save the current buffer, before handling the event.
- (That's the default.)
- :param record_in_macro: Record these key bindings when a macro is
- being recorded. (True by default.)
- """
- assert keys
-
- keys = tuple(_parse_key(k) for k in keys)
-
- if isinstance(filter, Never):
- # When a filter is Never, it will always stay disabled, so in that
- # case don't bother putting it in the key bindings. It will slow
- # down every key press otherwise.
- def decorator(func: T) -> T:
- return func
-
- else:
-
- def decorator(func: T) -> T:
- if isinstance(func, Binding):
- # We're adding an existing Binding object.
- self.bindings.append(
- Binding(
- keys,
- func.handler,
- filter=func.filter & to_filter(filter),
- eager=to_filter(eager) | func.eager,
- is_global=to_filter(is_global) | func.is_global,
- save_before=func.save_before,
- record_in_macro=func.record_in_macro,
- )
- )
- else:
- self.bindings.append(
- Binding(
- keys,
- cast(KeyHandlerCallable, func),
- filter=filter,
- eager=eager,
- is_global=is_global,
- save_before=save_before,
- record_in_macro=record_in_macro,
- )
- )
- self._clear_cache()
-
- return func
-
- return decorator
-
- def remove(self, *args: Union[Keys, str, KeyHandlerCallable]) -> None:
- """
- Remove a key binding.
-
- This expects either a function that was given to `add` method as
- parameter or a sequence of key bindings.
-
- Raises `ValueError` when no bindings was found.
-
- Usage::
-
- remove(handler) # Pass handler.
- remove('c-x', 'c-a') # Or pass the key bindings.
- """
- found = False
-
- if callable(args[0]):
- assert len(args) == 1
- function = args[0]
-
- # Remove the given function.
- for b in self.bindings:
- if b.handler == function:
- self.bindings.remove(b)
- found = True
-
- else:
- assert len(args) > 0
- args = cast(Tuple[Union[Keys, str]], args)
-
- # Remove this sequence of key bindings.
- keys = tuple(_parse_key(k) for k in args)
-
- for b in self.bindings:
- if b.keys == keys:
- self.bindings.remove(b)
- found = True
-
- if found:
- self._clear_cache()
- else:
- # No key binding found for this function. Raise ValueError.
- raise ValueError(f"Binding not found: {function!r}")
-
- # For backwards-compatibility.
- add_binding = add
- remove_binding = remove
-
- def get_bindings_for_keys(self, keys: KeysTuple) -> List[Binding]:
- """
- Return a list of key bindings that can handle this key.
- (This return also inactive bindings, so the `filter` still has to be
- called, for checking it.)
-
- :param keys: tuple of keys.
- """
-
- def get() -> List[Binding]:
- result: List[Tuple[int, Binding]] = []
-
- for b in self.bindings:
- if len(keys) == len(b.keys):
- match = True
- any_count = 0
-
- for i, j in zip(b.keys, keys):
- if i != j and i != Keys.Any:
- match = False
- break
-
- if i == Keys.Any:
- any_count += 1
-
- if match:
- result.append((any_count, b))
-
- # Place bindings that have more 'Any' occurrences in them at the end.
- result = sorted(result, key=lambda item: -item[0])
-
- return [item[1] for item in result]
-
- return self._get_bindings_for_keys_cache.get(keys, get)
-
- def get_bindings_starting_with_keys(self, keys: KeysTuple) -> List[Binding]:
- """
- Return a list of key bindings that handle a key sequence starting with
- `keys`. (It does only return bindings for which the sequences are
- longer than `keys`. And like `get_bindings_for_keys`, it also includes
- inactive bindings.)
-
- :param keys: tuple of keys.
- """
-
- def get() -> List[Binding]:
- result = []
- for b in self.bindings:
- if len(keys) < len(b.keys):
- match = True
- for i, j in zip(b.keys, keys):
- if i != j and i != Keys.Any:
- match = False
- break
- if match:
- result.append(b)
- return result
-
- return self._get_bindings_starting_with_keys_cache.get(keys, get)
-
-
-def _parse_key(key: Union[Keys, str]) -> Union[str, Keys]:
- """
- Replace key by alias and verify whether it's a valid one.
- """
- # Already a parse key? -> Return it.
- if isinstance(key, Keys):
- return key
-
- # Lookup aliases.
- key = KEY_ALIASES.get(key, key)
-
- # Replace 'space' by ' '
- if key == "space":
- key = " "
-
- # Return as `Key` object when it's a special key.
- try:
- return Keys(key)
- except ValueError:
- pass
-
- # Final validation.
- if len(key) != 1:
- raise ValueError(f"Invalid key: {key}")
-
- return key
-
-
-def key_binding(
- filter: FilterOrBool = True,
- eager: FilterOrBool = False,
- is_global: FilterOrBool = False,
- save_before: Callable[["KeyPressEvent"], bool] = (lambda event: True),
- record_in_macro: FilterOrBool = True,
-) -> Callable[[KeyHandlerCallable], Binding]:
- """
- Decorator that turn a function into a `Binding` object. This can be added
- to a `KeyBindings` object when a key binding is assigned.
- """
- assert save_before is None or callable(save_before)
-
- filter = to_filter(filter)
- eager = to_filter(eager)
- is_global = to_filter(is_global)
- save_before = save_before
- record_in_macro = to_filter(record_in_macro)
- keys = ()
-
- def decorator(function: KeyHandlerCallable) -> Binding:
- return Binding(
- keys,
- function,
- filter=filter,
- eager=eager,
- is_global=is_global,
- save_before=save_before,
- record_in_macro=record_in_macro,
- )
-
- return decorator
-
-
-class _Proxy(KeyBindingsBase):
- """
- Common part for ConditionalKeyBindings and _MergedKeyBindings.
- """
-
- def __init__(self) -> None:
- # `KeyBindings` to be synchronized with all the others.
- self._bindings2: KeyBindingsBase = KeyBindings()
- self._last_version: Hashable = ()
-
- def _update_cache(self) -> None:
- """
- If `self._last_version` is outdated, then this should update
- the version and `self._bindings2`.
- """
- raise NotImplementedError
-
- # Proxy methods to self._bindings2.
-
- @property
- def bindings(self) -> List[Binding]:
- self._update_cache()
- return self._bindings2.bindings
-
- @property
- def _version(self) -> Hashable:
- self._update_cache()
- return self._last_version
-
- def get_bindings_for_keys(self, keys: KeysTuple) -> List[Binding]:
- self._update_cache()
- return self._bindings2.get_bindings_for_keys(keys)
-
- def get_bindings_starting_with_keys(self, keys: KeysTuple) -> List[Binding]:
- self._update_cache()
- return self._bindings2.get_bindings_starting_with_keys(keys)
-
-
-class ConditionalKeyBindings(_Proxy):
- """
- Wraps around a `KeyBindings`. Disable/enable all the key bindings according to
- the given (additional) filter.::
-
- @Condition
- def setting_is_true():
- return True # or False
-
- registry = ConditionalKeyBindings(key_bindings, setting_is_true)
-
- When new key bindings are added to this object. They are also
- enable/disabled according to the given `filter`.
-
- :param registries: List of :class:`.KeyBindings` objects.
- :param filter: :class:`~prompt_toolkit.filters.Filter` object.
- """
-
- def __init__(
- self, key_bindings: KeyBindingsBase, filter: FilterOrBool = True
- ) -> None:
-
- _Proxy.__init__(self)
-
- self.key_bindings = key_bindings
- self.filter = to_filter(filter)
-
- def _update_cache(self) -> None:
- "If the original key bindings was changed. Update our copy version."
- expected_version = self.key_bindings._version
-
- if self._last_version != expected_version:
- bindings2 = KeyBindings()
-
- # Copy all bindings from `self.key_bindings`, adding our condition.
- for b in self.key_bindings.bindings:
- bindings2.bindings.append(
- Binding(
- keys=b.keys,
- handler=b.handler,
- filter=self.filter & b.filter,
- eager=b.eager,
- is_global=b.is_global,
- save_before=b.save_before,
- record_in_macro=b.record_in_macro,
- )
- )
-
- self._bindings2 = bindings2
- self._last_version = expected_version
-
-
-class _MergedKeyBindings(_Proxy):
- """
- Merge multiple registries of key bindings into one.
-
- This class acts as a proxy to multiple :class:`.KeyBindings` objects, but
- behaves as if this is just one bigger :class:`.KeyBindings`.
-
- :param registries: List of :class:`.KeyBindings` objects.
- """
-
- def __init__(self, registries: Sequence[KeyBindingsBase]) -> None:
- _Proxy.__init__(self)
- self.registries = registries
-
- def _update_cache(self) -> None:
- """
- If one of the original registries was changed. Update our merged
- version.
- """
- expected_version = tuple(r._version for r in self.registries)
-
- if self._last_version != expected_version:
- bindings2 = KeyBindings()
-
- for reg in self.registries:
- bindings2.bindings.extend(reg.bindings)
-
- self._bindings2 = bindings2
- self._last_version = expected_version
-
-
-def merge_key_bindings(bindings: Sequence[KeyBindingsBase]) -> _MergedKeyBindings:
- """
- Merge multiple :class:`.Keybinding` objects together.
-
- Usage::
-
- bindings = merge_key_bindings([bindings1, bindings2, ...])
- """
- return _MergedKeyBindings(bindings)
-
-
-class DynamicKeyBindings(_Proxy):
- """
- KeyBindings class that can dynamically returns any KeyBindings.
-
- :param get_key_bindings: Callable that returns a :class:`.KeyBindings` instance.
- """
-
- def __init__(
- self, get_key_bindings: Callable[[], Optional[KeyBindingsBase]]
- ) -> None:
- self.get_key_bindings = get_key_bindings
- self.__version = 0
- self._last_child_version = None
- self._dummy = KeyBindings() # Empty key bindings.
-
- def _update_cache(self) -> None:
- key_bindings = self.get_key_bindings() or self._dummy
- assert isinstance(key_bindings, KeyBindingsBase)
- version = id(key_bindings), key_bindings._version
-
- self._bindings2 = key_bindings
- self._last_version = version
-
-
-class GlobalOnlyKeyBindings(_Proxy):
- """
- Wrapper around a :class:`.KeyBindings` object that only exposes the global
- key bindings.
- """
-
- def __init__(self, key_bindings: KeyBindingsBase) -> None:
- _Proxy.__init__(self)
- self.key_bindings = key_bindings
-
- def _update_cache(self) -> None:
- """
- If one of the original registries was changed. Update our merged
- version.
- """
- expected_version = self.key_bindings._version
-
- if self._last_version != expected_version:
- bindings2 = KeyBindings()
-
- for b in self.key_bindings.bindings:
- if b.is_global():
- bindings2.bindings.append(b)
-
- self._bindings2 = bindings2
- self._last_version = expected_version
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/key_processor.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/key_processor.py
deleted file mode 100644
index 6fdd5191791..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/key_processor.py
+++ /dev/null
@@ -1,528 +0,0 @@
-"""
-An :class:`~.KeyProcessor` receives callbacks for the keystrokes parsed from
-the input in the :class:`~prompt_toolkit.inputstream.InputStream` instance.
-
-The `KeyProcessor` will according to the implemented keybindings call the
-correct callbacks when new key presses are feed through `feed`.
-"""
-import weakref
-from asyncio import Task, sleep
-from collections import deque
-from typing import TYPE_CHECKING, Any, Deque, Generator, List, Optional, Union
-
-from prompt_toolkit.application.current import get_app
-from prompt_toolkit.enums import EditingMode
-from prompt_toolkit.filters.app import vi_navigation_mode
-from prompt_toolkit.keys import Keys
-from prompt_toolkit.utils import Event
-
-from .key_bindings import Binding, KeyBindingsBase
-
-if TYPE_CHECKING:
- from prompt_toolkit.application import Application
- from prompt_toolkit.buffer import Buffer
-
-
-__all__ = [
- "KeyProcessor",
- "KeyPress",
- "KeyPressEvent",
-]
-
-
-class KeyPress:
- """
- :param key: A `Keys` instance or text (one character).
- :param data: The received string on stdin. (Often vt100 escape codes.)
- """
-
- def __init__(self, key: Union[Keys, str], data: Optional[str] = None) -> None:
- assert isinstance(key, Keys) or len(key) == 1
-
- if data is None:
- if isinstance(key, Keys):
- data = key.value
- else:
- data = key # 'key' is a one character string.
-
- self.key = key
- self.data = data
-
- def __repr__(self) -> str:
- return f"{self.__class__.__name__}(key={self.key!r}, data={self.data!r})"
-
- def __eq__(self, other: object) -> bool:
- if not isinstance(other, KeyPress):
- return False
- return self.key == other.key and self.data == other.data
-
-
-"""
-Helper object to indicate flush operation in the KeyProcessor.
-NOTE: the implementation is very similar to the VT100 parser.
-"""
-_Flush = KeyPress("?", data="_Flush")
-
-
-class KeyProcessor:
- """
- Statemachine that receives :class:`KeyPress` instances and according to the
- key bindings in the given :class:`KeyBindings`, calls the matching handlers.
-
- ::
-
- p = KeyProcessor(key_bindings)
-
- # Send keys into the processor.
- p.feed(KeyPress(Keys.ControlX, '\x18'))
- p.feed(KeyPress(Keys.ControlC, '\x03')
-
- # Process all the keys in the queue.
- p.process_keys()
-
- # Now the ControlX-ControlC callback will be called if this sequence is
- # registered in the key bindings.
-
- :param key_bindings: `KeyBindingsBase` instance.
- """
-
- def __init__(self, key_bindings: KeyBindingsBase) -> None:
- self._bindings = key_bindings
-
- self.before_key_press = Event(self)
- self.after_key_press = Event(self)
-
- self._flush_wait_task: Optional[Task[None]] = None
-
- self.reset()
-
- def reset(self) -> None:
- self._previous_key_sequence: List[KeyPress] = []
- self._previous_handler: Optional[Binding] = None
-
- # The queue of keys not yet send to our _process generator/state machine.
- self.input_queue: Deque[KeyPress] = deque()
-
- # The key buffer that is matched in the generator state machine.
- # (This is at at most the amount of keys that make up for one key binding.)
- self.key_buffer: List[KeyPress] = []
-
- #: Readline argument (for repetition of commands.)
- #: https://www.gnu.org/software/bash/manual/html_node/Readline-Arguments.html
- self.arg: Optional[str] = None
-
- # Start the processor coroutine.
- self._process_coroutine = self._process()
- self._process_coroutine.send(None) # type: ignore
-
- def _get_matches(self, key_presses: List[KeyPress]) -> List[Binding]:
- """
- For a list of :class:`KeyPress` instances. Give the matching handlers
- that would handle this.
- """
- keys = tuple(k.key for k in key_presses)
-
- # Try match, with mode flag
- return [b for b in self._bindings.get_bindings_for_keys(keys) if b.filter()]
-
- def _is_prefix_of_longer_match(self, key_presses: List[KeyPress]) -> bool:
- """
- For a list of :class:`KeyPress` instances. Return True if there is any
- handler that is bound to a suffix of this keys.
- """
- keys = tuple(k.key for k in key_presses)
-
- # Get the filters for all the key bindings that have a longer match.
- # Note that we transform it into a `set`, because we don't care about
- # the actual bindings and executing it more than once doesn't make
- # sense. (Many key bindings share the same filter.)
- filters = {
- b.filter for b in self._bindings.get_bindings_starting_with_keys(keys)
- }
-
- # When any key binding is active, return True.
- return any(f() for f in filters)
-
- def _process(self) -> Generator[None, KeyPress, None]:
- """
- Coroutine implementing the key match algorithm. Key strokes are sent
- into this generator, and it calls the appropriate handlers.
- """
- buffer = self.key_buffer
- retry = False
-
- while True:
- flush = False
-
- if retry:
- retry = False
- else:
- key = yield
- if key is _Flush:
- flush = True
- else:
- buffer.append(key)
-
- # If we have some key presses, check for matches.
- if buffer:
- matches = self._get_matches(buffer)
-
- if flush:
- is_prefix_of_longer_match = False
- else:
- is_prefix_of_longer_match = self._is_prefix_of_longer_match(buffer)
-
- # When eager matches were found, give priority to them and also
- # ignore all the longer matches.
- eager_matches = [m for m in matches if m.eager()]
-
- if eager_matches:
- matches = eager_matches
- is_prefix_of_longer_match = False
-
- # Exact matches found, call handler.
- if not is_prefix_of_longer_match and matches:
- self._call_handler(matches[-1], key_sequence=buffer[:])
- del buffer[:] # Keep reference.
-
- # No match found.
- elif not is_prefix_of_longer_match and not matches:
- retry = True
- found = False
-
- # Loop over the input, try longest match first and shift.
- for i in range(len(buffer), 0, -1):
- matches = self._get_matches(buffer[:i])
- if matches:
- self._call_handler(matches[-1], key_sequence=buffer[:i])
- del buffer[:i]
- found = True
- break
-
- if not found:
- del buffer[:1]
-
- def feed(self, key_press: KeyPress, first: bool = False) -> None:
- """
- Add a new :class:`KeyPress` to the input queue.
- (Don't forget to call `process_keys` in order to process the queue.)
-
- :param first: If true, insert before everything else.
- """
- if first:
- self.input_queue.appendleft(key_press)
- else:
- self.input_queue.append(key_press)
-
- def feed_multiple(self, key_presses: List[KeyPress], first: bool = False) -> None:
- """
- :param first: If true, insert before everything else.
- """
- if first:
- self.input_queue.extendleft(reversed(key_presses))
- else:
- self.input_queue.extend(key_presses)
-
- def process_keys(self) -> None:
- """
- Process all the keys in the `input_queue`.
- (To be called after `feed`.)
-
- Note: because of the `feed`/`process_keys` separation, it is
- possible to call `feed` from inside a key binding.
- This function keeps looping until the queue is empty.
- """
- app = get_app()
-
- def not_empty() -> bool:
- # When the application result is set, stop processing keys. (E.g.
- # if ENTER was received, followed by a few additional key strokes,
- # leave the other keys in the queue.)
- if app.is_done:
- # But if there are still CPRResponse keys in the queue, these
- # need to be processed.
- return any(k for k in self.input_queue if k.key == Keys.CPRResponse)
- else:
- return bool(self.input_queue)
-
- def get_next() -> KeyPress:
- if app.is_done:
- # Only process CPR responses. Everything else is typeahead.
- cpr = [k for k in self.input_queue if k.key == Keys.CPRResponse][0]
- self.input_queue.remove(cpr)
- return cpr
- else:
- return self.input_queue.popleft()
-
- is_flush = False
-
- while not_empty():
- # Process next key.
- key_press = get_next()
-
- is_flush = key_press is _Flush
- is_cpr = key_press.key == Keys.CPRResponse
-
- if not is_flush and not is_cpr:
- self.before_key_press.fire()
-
- try:
- self._process_coroutine.send(key_press)
- except Exception:
- # If for some reason something goes wrong in the parser, (maybe
- # an exception was raised) restart the processor for next time.
- self.reset()
- self.empty_queue()
- raise
-
- if not is_flush and not is_cpr:
- self.after_key_press.fire()
-
- # Skip timeout if the last key was flush.
- if not is_flush:
- self._start_timeout()
-
- def empty_queue(self) -> List[KeyPress]:
- """
- Empty the input queue. Return the unprocessed input.
- """
- key_presses = list(self.input_queue)
- self.input_queue.clear()
-
- # Filter out CPRs. We don't want to return these.
- key_presses = [k for k in key_presses if k.key != Keys.CPRResponse]
- return key_presses
-
- def _call_handler(self, handler: Binding, key_sequence: List[KeyPress]) -> None:
- app = get_app()
- was_recording_emacs = app.emacs_state.is_recording
- was_recording_vi = bool(app.vi_state.recording_register)
- was_temporary_navigation_mode = app.vi_state.temporary_navigation_mode
- arg = self.arg
- self.arg = None
-
- event = KeyPressEvent(
- weakref.ref(self),
- arg=arg,
- key_sequence=key_sequence,
- previous_key_sequence=self._previous_key_sequence,
- is_repeat=(handler == self._previous_handler),
- )
-
- # Save the state of the current buffer.
- if handler.save_before(event):
- event.app.current_buffer.save_to_undo_stack()
-
- # Call handler.
- from prompt_toolkit.buffer import EditReadOnlyBuffer
-
- try:
- handler.call(event)
- self._fix_vi_cursor_position(event)
-
- except EditReadOnlyBuffer:
- # When a key binding does an attempt to change a buffer which is
- # read-only, we can ignore that. We sound a bell and go on.
- app.output.bell()
-
- if was_temporary_navigation_mode:
- self._leave_vi_temp_navigation_mode(event)
-
- self._previous_key_sequence = key_sequence
- self._previous_handler = handler
-
- # Record the key sequence in our macro. (Only if we're in macro mode
- # before and after executing the key.)
- if handler.record_in_macro():
- if app.emacs_state.is_recording and was_recording_emacs:
- recording = app.emacs_state.current_recording
- if recording is not None: # Should always be true, given that
- # `was_recording_emacs` is set.
- recording.extend(key_sequence)
-
- if app.vi_state.recording_register and was_recording_vi:
- for k in key_sequence:
- app.vi_state.current_recording += k.data
-
- def _fix_vi_cursor_position(self, event: "KeyPressEvent") -> None:
- """
- After every command, make sure that if we are in Vi navigation mode, we
- never put the cursor after the last character of a line. (Unless it's
- an empty line.)
- """
- app = event.app
- buff = app.current_buffer
- preferred_column = buff.preferred_column
-
- if (
- vi_navigation_mode()
- and buff.document.is_cursor_at_the_end_of_line
- and len(buff.document.current_line) > 0
- ):
- buff.cursor_position -= 1
-
- # Set the preferred_column for arrow up/down again.
- # (This was cleared after changing the cursor position.)
- buff.preferred_column = preferred_column
-
- def _leave_vi_temp_navigation_mode(self, event: "KeyPressEvent") -> None:
- """
- If we're in Vi temporary navigation (normal) mode, return to
- insert/replace mode after executing one action.
- """
- app = event.app
-
- if app.editing_mode == EditingMode.VI:
- # Not waiting for a text object and no argument has been given.
- if app.vi_state.operator_func is None and self.arg is None:
- app.vi_state.temporary_navigation_mode = False
-
- def _start_timeout(self) -> None:
- """
- Start auto flush timeout. Similar to Vim's `timeoutlen` option.
-
- Start a background coroutine with a timer. When this timeout expires
- and no key was pressed in the meantime, we flush all data in the queue
- and call the appropriate key binding handlers.
- """
- app = get_app()
- timeout = app.timeoutlen
-
- if timeout is None:
- return
-
- async def wait() -> None:
- "Wait for timeout."
- # This sleep can be cancelled. In that case we don't flush.
- await sleep(timeout)
-
- if len(self.key_buffer) > 0:
- # (No keys pressed in the meantime.)
- flush_keys()
-
- def flush_keys() -> None:
- "Flush keys."
- self.feed(_Flush)
- self.process_keys()
-
- # Automatically flush keys.
- if self._flush_wait_task:
- self._flush_wait_task.cancel()
- self._flush_wait_task = app.create_background_task(wait())
-
- def send_sigint(self) -> None:
- """
- Send SIGINT. Immediately call the SIGINT key handler.
- """
- self.feed(KeyPress(key=Keys.SIGINT), first=True)
- self.process_keys()
-
-
-class KeyPressEvent:
- """
- Key press event, delivered to key bindings.
-
- :param key_processor_ref: Weak reference to the `KeyProcessor`.
- :param arg: Repetition argument.
- :param key_sequence: List of `KeyPress` instances.
- :param previouskey_sequence: Previous list of `KeyPress` instances.
- :param is_repeat: True when the previous event was delivered to the same handler.
- """
-
- def __init__(
- self,
- key_processor_ref: "weakref.ReferenceType[KeyProcessor]",
- arg: Optional[str],
- key_sequence: List[KeyPress],
- previous_key_sequence: List[KeyPress],
- is_repeat: bool,
- ) -> None:
-
- self._key_processor_ref = key_processor_ref
- self.key_sequence = key_sequence
- self.previous_key_sequence = previous_key_sequence
-
- #: True when the previous key sequence was handled by the same handler.
- self.is_repeat = is_repeat
-
- self._arg = arg
- self._app = get_app()
-
- def __repr__(self) -> str:
- return "KeyPressEvent(arg={!r}, key_sequence={!r}, is_repeat={!r})".format(
- self.arg,
- self.key_sequence,
- self.is_repeat,
- )
-
- @property
- def data(self) -> str:
- return self.key_sequence[-1].data
-
- @property
- def key_processor(self) -> KeyProcessor:
- processor = self._key_processor_ref()
- if processor is None:
- raise Exception("KeyProcessor was lost. This should not happen.")
- return processor
-
- @property
- def app(self) -> "Application[Any]":
- """
- The current `Application` object.
- """
- return self._app
-
- @property
- def current_buffer(self) -> "Buffer":
- """
- The current buffer.
- """
- return self.app.current_buffer
-
- @property
- def arg(self) -> int:
- """
- Repetition argument.
- """
- if self._arg == "-":
- return -1
-
- result = int(self._arg or 1)
-
- # Don't exceed a million.
- if int(result) >= 1000000:
- result = 1
-
- return result
-
- @property
- def arg_present(self) -> bool:
- """
- True if repetition argument was explicitly provided.
- """
- return self._arg is not None
-
- def append_to_arg_count(self, data: str) -> None:
- """
- Add digit to the input argument.
-
- :param data: the typed digit as string
- """
- assert data in "-0123456789"
- current = self._arg
-
- if data == "-":
- assert current is None or current == "-"
- result = data
- elif current is None:
- result = data
- else:
- result = f"{current}{data}"
-
- self.key_processor.arg = result
-
- @property
- def cli(self) -> "Application[Any]":
- "For backward-compatibility."
- return self.app
diff --git a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/vi_state.py b/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/vi_state.py
deleted file mode 100644
index 10593a82e62..00000000000
--- a/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/vi_state.py
+++ /dev/null
@@ -1,107 +0,0 @@
-from enum import Enum
-from typing import TYPE_CHECKING, Callable, Dict, Optional
-
-from prompt_toolkit.clipboard import ClipboardData
-
-if TYPE_CHECKING:
- from .key_bindings.vi import TextObject
- from .key_processor import KeyPressEvent
-
-__all__ = [
- "InputMode",
- "CharacterFind",
- "ViState",
-]
-
-
-class InputMode(str, Enum):
- value: str
-
- INSERT = "vi-insert"
- INSERT_MULTIPLE = "vi-insert-multiple"
- NAVIGATION = "vi-navigation" # Normal mode.
- REPLACE = "vi-replace"
- REPLACE_SINGLE = "vi-replace-single"
-
-
-class CharacterFind:
- def __init__(self, character: str, backwards: bool = False) -> None:
- self.character = character
- self.backwards = backwards
-
-
-class ViState:
- """
- Mutable class to hold the state of the Vi navigation.
- """
-
- def __init__(self) -> None:
- #: None or CharacterFind instance. (This is used to repeat the last
- #: search in Vi mode, by pressing the 'n' or 'N' in navigation mode.)
- self.last_character_find: Optional[CharacterFind] = None
-
- # When an operator is given and we are waiting for text object,
- # -- e.g. in the case of 'dw', after the 'd' --, an operator callback
- # is set here.
- self.operator_func: Optional[
- Callable[["KeyPressEvent", "TextObject"], None]
- ] = None
- self.operator_arg: Optional[int] = None
-
- #: Named registers. Maps register name (e.g. 'a') to
- #: :class:`ClipboardData` instances.
- self.named_registers: Dict[str, ClipboardData] = {}
-
- #: The Vi mode we're currently in to.
- self.__input_mode = InputMode.INSERT
-
- #: Waiting for digraph.
- self.waiting_for_digraph = False
- self.digraph_symbol1: Optional[str] = None # (None or a symbol.)
-
- #: When true, make ~ act as an operator.
- self.tilde_operator = False
-
- #: Register in which we are recording a macro.
- #: `None` when not recording anything.
- # Note that the recording is only stored in the register after the
- # recording is stopped. So we record in a separate `current_recording`
- # variable.
- self.recording_register: Optional[str] = None
- self.current_recording: str = ""
-
- # Temporary navigation (normal) mode.
- # This happens when control-o has been pressed in insert or replace
- # mode. The user can now do one navigation action and we'll return back
- # to insert/replace.
- self.temporary_navigation_mode = False
-
- @property
- def input_mode(self) -> InputMode:
- "Get `InputMode`."
- return self.__input_mode
-
- @input_mode.setter
- def input_mode(self, value: InputMode) -> None:
- "Set `InputMode`."
- if value == InputMode.NAVIGATION:
- self.waiting_for_digraph = False
- self.operator_func = None
- self.operator_arg = None
-
- self.__input_mode = value
-
- def reset(self) -> None:
- """
- Reset state, go back to the given mode. INSERT by default.
- """
- # Go back to insert mode.
- self.input_mode = InputMode.INSERT
-
- self.waiting_for_digraph = False
- self.operator_func = None
- self.operator_arg = None
-
- # Reset recording state.
- self.recording_register = None
- self.current_recording = ""