summaryrefslogtreecommitdiffstats
path: root/contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings
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/bindings
parent03f024c4412e3aa613bb543cf1660176320ba8f4 (diff)
fix ya.make
Diffstat (limited to 'contrib/python/prompt-toolkit/py3/prompt_toolkit/key_binding/bindings')
-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
14 files changed, 0 insertions, 4794 deletions
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)