diff --git a/docs/changelog.rst b/docs/changelog.rst index bb268eba0..746c144ba 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -82,6 +82,9 @@ Detailed list of changes - ssh kitten: Fix location of generated terminfo files on NetBSD (:iss:`4622`) +- A new action to clear the screen up to the line containing the cursor, see + :ac:`clear_terminal` + 0.24.2 [2022-02-03] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/kitty/boss.py b/kitty/boss.py index 3776ec9c7..08741fd84 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -779,7 +779,8 @@ class Boss: map kitty_mod+f11 clear_terminal scrollback active # Scroll the contents of the screen into the scrollback map kitty_mod+f12 clear_terminal scroll active - + # Clear everything up to the line with the cursor + map kitty_mod+f9 clear_terminal to_cursor active ''') def clear_terminal(self, action: str, only_active: bool) -> None: if only_active: @@ -792,8 +793,10 @@ class Boss: reset = action == 'reset' how = 3 if action == 'scrollback' else 2 for w in windows: - if action == 'scroll': + if action in ('to_cursor', 'scroll'): w.screen.scroll_until_cursor() + if action == 'to_cursor': + w.screen.clear_scrollback() continue w.screen.cursor.x = w.screen.cursor.y = 0 if reset: diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index f2024f518..65640e705 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1136,6 +1136,9 @@ class Screen: def erase_in_display(self, how: int = 0, private: bool = False) -> None: pass + def clear_scrollback(self) -> None: + pass + def focus_changed(self, focused: bool) -> bool: pass diff --git a/kitty/screen.c b/kitty/screen.c index baa698571..0a0b8e6c3 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -1616,6 +1616,15 @@ screen_erase_in_line(Screen *self, unsigned int how, bool private) { } } +static void +screen_clear_scrollback(Screen *self) { + historybuf_clear(self->historybuf); + if (self->scrolled_by != 0) { + self->scrolled_by = 0; + self->scroll_changed = true; + } +} + void screen_erase_in_display(Screen *self, unsigned int how, bool private) { /* Erases display in a specific way. @@ -1662,11 +1671,7 @@ screen_erase_in_display(Screen *self, unsigned int how, bool private) { if (how == 1) linebuf_clear_attrs_and_dirty(self->linebuf, self->cursor->y); } if (how == 3 && self->linebuf == self->main_linebuf) { - historybuf_clear(self->historybuf); - if (self->scrolled_by != 0) { - self->scrolled_by = 0; - self->scroll_changed = true; - } + screen_clear_scrollback(self); } } @@ -1685,10 +1690,9 @@ screen_insert_lines(Screen *self, unsigned int count) { void screen_scroll_until_cursor(Screen *self) { unsigned int num_lines_to_scroll = MIN(self->margin_bottom, self->cursor->y + 1); - index_type y = self->cursor->y; self->cursor->y = self->margin_bottom; while (num_lines_to_scroll--) screen_index(self); - self->cursor->y = y; + self->cursor->y = self->margin_top; } void @@ -2957,6 +2961,7 @@ WRAP1E(cursor_back, 1, -1) WRAP1B(erase_in_line, 0) WRAP1B(erase_in_display, 0) WRAP0(scroll_until_cursor) +WRAP0(clear_scrollback) #define MODE_GETSET(name, uname) \ static PyObject* name##_get(Screen *self, void UNUSED *closure) { PyObject *ans = self->modes.m##uname ? Py_True : Py_False; Py_INCREF(ans); return ans; } \ @@ -3777,6 +3782,7 @@ static PyMethodDef methods[] = { MND(cursor_back, METH_VARARGS) MND(erase_in_line, METH_VARARGS) MND(erase_in_display, METH_VARARGS) + MND(clear_scrollback, METH_NOARGS) MND(scroll_until_cursor, METH_NOARGS) MND(hyperlinks_as_list, METH_NOARGS) MND(garbage_collect_hyperlink_pool, METH_NOARGS)