diff --git a/docs/basic.rst b/docs/basic.rst index 1ad34c8dd..37382909c 100644 --- a/docs/basic.rst +++ b/docs/basic.rst @@ -14,12 +14,14 @@ Scrolling ======================== ======================= Action Shortcut ======================== ======================= -Scroll line up :sc:`scroll_line_up` (also :kbd:`⌥+⌘+⇞` and :kbd:`⌘+↑` on macOS) -Scroll line down :sc:`scroll_line_down` (also :kbd:`⌥+⌘+⇟` and :kbd:`⌘+↓` on macOS) -Scroll page up :sc:`scroll_page_up` (also :kbd:`⌘+⇞` on macOS) -Scroll page down :sc:`scroll_page_down` (also :kbd:`⌘+⇟` on macOS) -Scroll to top :sc:`scroll_home` (also :kbd:`⌘+↖` on macOS) -Scroll to bottom :sc:`scroll_end` (also :kbd:`⌘+↘` on macOS) +Line up :sc:`scroll_line_up` (also :kbd:`⌥+⌘+⇞` and :kbd:`⌘+↑` on macOS) +Line down :sc:`scroll_line_down` (also :kbd:`⌥+⌘+⇟` and :kbd:`⌘+↓` on macOS) +Page up :sc:`scroll_page_up` (also :kbd:`⌘+⇞` on macOS) +Page down :sc:`scroll_page_down` (also :kbd:`⌘+⇟` on macOS) +Top :sc:`scroll_home` (also :kbd:`⌘+↖` on macOS) +Bottom :sc:`scroll_end` (also :kbd:`⌘+↘` on macOS) +Previous shell prompt :sc:`scroll_to_previous_prompt` (see :ref:`shell_integration`) +Next shell prompt :sc:`scroll_to_next_prompt` (see :ref:`shell_integration`) ======================== ======================= Tabs diff --git a/docs/changelog.rst b/docs/changelog.rst index 7612a8556..2c85ab2c7 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1862,7 +1862,8 @@ To update |kitty|, :doc:`follow the instructions `. using standard keyboards) via `IBus `_ (:iss:`469`) -- Implement completion for the kitty command in bash and zsh +- Implement completion for the kitty command in bash and zsh. See + :ref:`shell_integration`. - Render the text under the cursor in a fixed color, configurable via the option :opt:`cursor_text_color` (:iss:`126`) diff --git a/docs/faq.rst b/docs/faq.rst index 89b5a747d..985449ff6 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -51,6 +51,9 @@ type it each time:: alias ssh="kitty +kitten ssh" +Remember to also setup :ref:`shell_integration` for completion and other +niceties. + If for some reason that does not work (typically because the server is using a non POSIX compliant shell as ``/bin/sh``), you can try using it with ``python`` instead:: diff --git a/kitty/conf/types.py b/kitty/conf/types.py index 1c4d8c3bc..c0acee516 100644 --- a/kitty/conf/types.py +++ b/kitty/conf/types.py @@ -47,6 +47,7 @@ def remove_markup(text: str) -> str: 'sessions': f'{website_url("overview")}#startup-sessions', 'functional': f'{website_url("keyboard-protocol")}#functional-key-definitions', 'action-select_tab': f'{website_url("actions")}#select-tab', + 'shell_integration': website_url("shell-integration"), } def sub(m: Match) -> str: diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index 9cdcca3f1..9e9a82290 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1016,6 +1016,9 @@ class Screen: def scroll_to_next_mark(self, mark: int = 0, backwards: bool = True) -> bool: pass + def scroll_to_prompt(self, num_of_prompts: int = -1) -> bool: + pass + def reverse_scroll(self, amt: int, fill_from_scrollback: bool = False) -> bool: pass diff --git a/kitty/options/definition.py b/kitty/options/definition.py index d7e1473d5..c0dae4194 100644 --- a/kitty/options/definition.py +++ b/kitty/options/definition.py @@ -2892,6 +2892,20 @@ map('Scroll to bottom', only="macos", ) +map('Scroll to previous shell prompt', + 'scroll_to_previous_prompt kitty_mod+x scroll_to_prompt -1', + long_text=''' +Requires :ref:`shell_integration` to work. +''' + ) + +map('Scroll to next shell prompt', + 'scroll_to_next_prompt kitty_mod+d scroll_to_prompt 1', + long_text=''' +Requires :ref:`shell_integration` to work. +''' + ) + map('Browse scrollback buffer in less', 'show_scrollback kitty_mod+h show_scrollback', long_text=''' diff --git a/kitty/options/types.py b/kitty/options/types.py index 41f77fa1a..82345c1a2 100644 --- a/kitty/options/types.py +++ b/kitty/options/types.py @@ -712,6 +712,10 @@ defaults.map = [ KeyDefinition(False, KeyAction('scroll_home'), 1024, False, 57356, ()), # scroll_end KeyDefinition(False, KeyAction('scroll_end'), 1024, False, 57357, ()), + # scroll_to_previous_prompt + KeyDefinition(False, KeyAction('scroll_to_prompt', (-1,)), 1024, False, 120, ()), + # scroll_to_next_prompt + KeyDefinition(False, KeyAction('scroll_to_prompt', (1,)), 1024, False, 100, ()), # show_scrollback KeyDefinition(False, KeyAction('show_scrollback'), 1024, False, 104, ()), # new_window diff --git a/kitty/options/utils.py b/kitty/options/utils.py index d492268b4..1cc9e79f2 100644 --- a/kitty/options/utils.py +++ b/kitty/options/utils.py @@ -249,13 +249,14 @@ def remote_control(func: str, rest: str) -> FuncArgsType: return func, r -@func_with_args('nth_window') -def nth_window(func: str, rest: str) -> FuncArgsType: +@func_with_args('nth_window', 'scroll_to_prompt') +def single_integer_arg(func: str, rest: str) -> FuncArgsType: try: num = int(rest) except Exception: - log_error('Invalid nth_window number: {}'.format(rest)) - num = 1 + if rest: + log_error(f'Invalid number for {func}: {rest}') + num = -1 if func == 'scroll_to_prompt' else 1 return func, [num] diff --git a/kitty/window.py b/kitty/window.py index 7190964e6..403fa5fc5 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -1032,6 +1032,20 @@ class Window: if self.screen.is_main_linebuf(): self.screen.scroll(SCROLL_FULL, False) + @ac('sc', ''' + Scroll to the previous/next shell command prompt + Allows easy jumping from one command to the next. Requires working + :ref:`shell_integration`. Takes a single, optional, number as argument which is + the number of prompts to jump, negative values jump up and positive values jump down. + For example:: + + map ctrl+p scroll_to_prompt -1 # jump to previous + map ctrl+n scroll_to_prompt 1 # jump to next + ''') + def scroll_to_prompt(self, num_of_prompts: int = -1) -> None: + if self.screen.is_main_linebuf(): + self.screen.scroll_to_prompt(num_of_prompts) + @ac('mk', 'Toggle the current marker on/off') def toggle_marker(self, ftype: str, spec: Union[str, Tuple[Tuple[int, str], ...]], flags: int) -> None: from .marks import marker_from_spec