mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-05-13 08:26:56 +00:00
Add a default mapping for searching the scrollback
Opens the scrollback pager in search mode. Particularly useful for newbies on macOS that are used to using cmd+f to trigger search mode. If there is a current selection, it is automatically searched for.
This commit is contained in:
parent
9b6b9733b9
commit
20b39ee163
10 changed files with 54 additions and 6 deletions
|
|
@ -25,6 +25,7 @@ Previous shell prompt :sc:`scroll_to_previous_prompt` (see :ref:`shell_int
|
|||
Next shell prompt :sc:`scroll_to_next_prompt` (see :ref:`shell_integration`)
|
||||
Browse scrollback in less :sc:`show_scrollback`
|
||||
Browse last cmd output :sc:`show_last_command_output` (see :ref:`shell_integration`)
|
||||
Search scrollback in less :sc:`search_scrollback` (also :kbd:`⌘+F` on macOS)
|
||||
========================= =======================
|
||||
|
||||
The scroll actions only take effect when the terminal is in the main screen.
|
||||
|
|
|
|||
|
|
@ -177,6 +177,10 @@ Detailed list of changes
|
|||
- Do not rewrap the text in the alternate screen buffer. Avoids flicker during
|
||||
live resize with no :opt:`resize_debounce_time` (:disc:`9142`)
|
||||
|
||||
- Add a default mapping :ac:`search_scrollback` to open the scrollback in a
|
||||
pager in search mode. If any text is currently selected it is automatically
|
||||
searched for.
|
||||
|
||||
0.44.0 [2025-11-03]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -3402,4 +3402,6 @@ class Boss:
|
|||
def ungrab_keyboard(self) -> None:
|
||||
grab_keyboard(False)
|
||||
|
||||
|
||||
def search_scrollback_in_active(self) -> None:
|
||||
if w := self.active_window:
|
||||
w.search_scrollback()
|
||||
|
|
|
|||
|
|
@ -1242,6 +1242,7 @@ process_cocoa_pending_actions(void) {
|
|||
if (cocoa_pending_actions[TOGGLE_MACOS_SECURE_KEYBOARD_ENTRY]) { call_boss(toggle_macos_secure_keyboard_entry, NULL); }
|
||||
if (cocoa_pending_actions[MACOS_CYCLE_THROUGH_OS_WINDOWS]) { call_boss(macos_cycle_through_os_windows, NULL); }
|
||||
if (cocoa_pending_actions[MACOS_CYCLE_THROUGH_OS_WINDOWS_BACKWARDS]) { call_boss(macos_cycle_through_os_windows_backwards, NULL); }
|
||||
if (cocoa_pending_actions[SEARCH_SCROLLBACK]) { call_boss(search_scrollback_in_active, NULL); }
|
||||
if (cocoa_pending_actions[TOGGLE_FULLSCREEN]) { call_boss(toggle_fullscreen, NULL); }
|
||||
if (cocoa_pending_actions[OPEN_KITTY_WEBSITE]) { call_boss(open_kitty_website, NULL); }
|
||||
if (cocoa_pending_actions[HIDE]) { call_boss(hide_macos_app, NULL); }
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ typedef enum {
|
|||
TOGGLE_MACOS_SECURE_KEYBOARD_ENTRY,
|
||||
MACOS_CYCLE_THROUGH_OS_WINDOWS,
|
||||
MACOS_CYCLE_THROUGH_OS_WINDOWS_BACKWARDS,
|
||||
SEARCH_SCROLLBACK,
|
||||
TOGGLE_FULLSCREEN,
|
||||
OPEN_KITTY_WEBSITE,
|
||||
HIDE,
|
||||
|
|
|
|||
|
|
@ -260,6 +260,7 @@ PENDING(reload_config, RELOAD_CONFIG)
|
|||
PENDING(toggle_macos_secure_keyboard_entry, TOGGLE_MACOS_SECURE_KEYBOARD_ENTRY)
|
||||
PENDING(macos_cycle_through_os_windows, MACOS_CYCLE_THROUGH_OS_WINDOWS)
|
||||
PENDING(macos_cycle_through_os_windows_backwards, MACOS_CYCLE_THROUGH_OS_WINDOWS_BACKWARDS)
|
||||
PENDING(search_scrollback, SEARCH_SCROLLBACK)
|
||||
PENDING(toggle_fullscreen, TOGGLE_FULLSCREEN)
|
||||
PENDING(open_kitty_website, OPEN_KITTY_WEBSITE)
|
||||
PENDING(hide_macos_app, HIDE)
|
||||
|
|
@ -320,7 +321,7 @@ typedef struct {
|
|||
GlobalShortcut previous_tab, next_tab, new_tab, new_window, close_window, reset_terminal;
|
||||
GlobalShortcut clear_terminal_and_scrollback, clear_screen, clear_scrollback, clear_last_command;
|
||||
GlobalShortcut toggle_macos_secure_keyboard_entry, toggle_fullscreen, open_kitty_website;
|
||||
GlobalShortcut hide_macos_app, hide_macos_other_apps, minimize_macos_window, quit;
|
||||
GlobalShortcut hide_macos_app, hide_macos_other_apps, minimize_macos_window, quit, search_scrollback;
|
||||
GlobalShortcut macos_cycle_through_os_windows, macos_cycle_through_os_windows_backwards;
|
||||
} GlobalShortcuts;
|
||||
static GlobalShortcuts global_shortcuts;
|
||||
|
|
@ -339,7 +340,7 @@ cocoa_set_global_shortcut(PyObject *self UNUSED, PyObject *args) {
|
|||
else Q(clear_terminal_and_scrollback); else Q(clear_scrollback); else Q(clear_screen); else Q(clear_last_command);
|
||||
else Q(reload_config); else Q(toggle_macos_secure_keyboard_entry); else Q(toggle_fullscreen);
|
||||
else Q(open_kitty_website); else Q(hide_macos_app); else Q(hide_macos_other_apps);
|
||||
else Q(minimize_macos_window); else Q(quit);
|
||||
else Q(minimize_macos_window); else Q(quit); else Q(search_scrollback);
|
||||
else Q(macos_cycle_through_os_windows); else Q(macos_cycle_through_os_windows_backwards);
|
||||
#undef Q
|
||||
if (gs == NULL) { PyErr_SetString(PyExc_KeyError, "Unknown shortcut name"); return NULL; }
|
||||
|
|
@ -795,6 +796,7 @@ cocoa_create_global_menu(void) {
|
|||
MENU_ITEM(editMenu, @"Clear Scrollback", clear_scrollback);
|
||||
MENU_ITEM(editMenu, @"Clear Screen", clear_screen);
|
||||
MENU_ITEM(editMenu, @"Clear Last Command", clear_last_command);
|
||||
MENU_ITEM(editMenu, @"Find", search_scrollback);
|
||||
[editMenu release];
|
||||
|
||||
NSMenuItem* windowMenuItem =
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ def set_cocoa_global_shortcuts(opts: Options) -> dict[str, SingleKey]:
|
|||
for ac in ('new_os_window', 'close_os_window', 'close_tab', 'edit_config_file', 'previous_tab',
|
||||
'next_tab', 'new_tab', 'new_window', 'close_window', 'toggle_macos_secure_keyboard_entry',
|
||||
'toggle_fullscreen', 'macos_cycle_through_os_windows', 'macos_cycle_through_os_windows_backwards',
|
||||
'hide_macos_app', 'hide_macos_other_apps', 'minimize_macos_window', 'quit'):
|
||||
'hide_macos_app', 'hide_macos_other_apps', 'minimize_macos_window', 'quit', 'search_scrollback'):
|
||||
val = get_macos_shortcut_for(func_map, ac)
|
||||
if val is not None:
|
||||
global_shortcuts[ac] = val
|
||||
|
|
|
|||
|
|
@ -3984,6 +3984,22 @@ To get the output of the last jumped to command, use :code:`@last_visited_cmd_ou
|
|||
Requires :ref:`shell integration <shell_integration>` to work.
|
||||
'''
|
||||
)
|
||||
|
||||
map('Search the scrollback within a pager',
|
||||
'search_scrollback kitty_mod+/ search_scrollback',
|
||||
long_text='''
|
||||
Search for currently selected text in the scrollback using the configured :opt:`scrollback_pager`.
|
||||
Assumes that pressing the :kbd:`/` key triggers search mode in the pager. If you want to create
|
||||
a manual mapping with a special pager for this, you can use something like:
|
||||
|
||||
map f1 combine : launch --stdin-source=@screen_scrollback --stdin-add-formatting --type=overlay mypager : send_key /
|
||||
|
||||
For more sophisticated control, such as using the current selection, use :ac:`remote_control_script`.
|
||||
''')
|
||||
|
||||
map('Search the scrollback within a pager', 'search_scrollback cmd+f search_scrollback', only='macos')
|
||||
|
||||
|
||||
egr() # }}}
|
||||
|
||||
|
||||
|
|
|
|||
3
kitty/options/types.py
generated
3
kitty/options/types.py
generated
|
|
@ -849,6 +849,8 @@ defaults.map = [
|
|||
KeyDefinition(trigger=SingleKey(mods=256, key=104), definition='show_scrollback'),
|
||||
# show_last_command_output
|
||||
KeyDefinition(trigger=SingleKey(mods=256, key=103), definition='show_last_command_output'),
|
||||
# search_scrollback
|
||||
KeyDefinition(trigger=SingleKey(mods=256, key=47), definition='search_scrollback'),
|
||||
# new_window
|
||||
KeyDefinition(trigger=SingleKey(mods=256, key=57345), definition='new_window'),
|
||||
# new_os_window
|
||||
|
|
@ -982,6 +984,7 @@ if is_macos:
|
|||
defaults.map.append(KeyDefinition(trigger=SingleKey(mods=8, key=57355), definition='scroll_page_down'))
|
||||
defaults.map.append(KeyDefinition(trigger=SingleKey(mods=8, key=57356), definition='scroll_home'))
|
||||
defaults.map.append(KeyDefinition(trigger=SingleKey(mods=8, key=57357), definition='scroll_end'))
|
||||
defaults.map.append(KeyDefinition(trigger=SingleKey(mods=8, key=102), definition='search_scrollback'))
|
||||
defaults.map.append(KeyDefinition(trigger=SingleKey(mods=8, key=57345), definition='new_window'))
|
||||
defaults.map.append(KeyDefinition(trigger=SingleKey(mods=8, key=110), definition='new_os_window'))
|
||||
defaults.map.append(KeyDefinition(trigger=SingleKey(mods=9, key=100), definition='close_window'))
|
||||
|
|
|
|||
|
|
@ -2101,11 +2101,29 @@ class Window:
|
|||
# actions {{{
|
||||
|
||||
@ac('cp', 'Show scrollback in a pager like less')
|
||||
def show_scrollback(self) -> None:
|
||||
def show_scrollback(self) -> Optional['Window']:
|
||||
text = self.as_text(as_ansi=True, add_history=True, add_wrap_markers=True)
|
||||
data = self.pipe_data(text, has_wrap_markers=True)
|
||||
cursor_on_screen = self.screen.scrolled_by < self.screen.lines - self.screen.cursor.y
|
||||
get_boss().display_scrollback(self, data['text'], data['input_line_number'], report_cursor=cursor_on_screen)
|
||||
return get_boss().display_scrollback(self, data['text'], data['input_line_number'], report_cursor=cursor_on_screen)
|
||||
|
||||
@ac('cp', '''
|
||||
Search scrollback in a pager like less. If there is selected text, it is automatically searched for.
|
||||
Note that this assumes that pressing the / key triggers search mode in the page configured as the
|
||||
scrollback pager.
|
||||
''')
|
||||
def search_scrollback(self) -> None:
|
||||
text = self.text_for_selection()
|
||||
w = self.show_scrollback()
|
||||
if w is not None:
|
||||
w.send_key('/')
|
||||
if text:
|
||||
btext = text.encode()
|
||||
sanitized = replace_c0_codes_except_nl_space_tab(btext)
|
||||
if not w.screen.in_bracketed_paste_mode:
|
||||
sanitized = sanitized.replace(b'\n', b'\x1bE')
|
||||
w.screen.paste_bytes(sanitized)
|
||||
w.send_key('enter')
|
||||
|
||||
def show_cmd_output(self, which: CommandOutput, title: str = 'Command output', as_ansi: bool = True, add_wrap_markers: bool = True) -> None:
|
||||
text = self.cmd_output(which, as_ansi=as_ansi, add_wrap_markers=add_wrap_markers)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue