From e72975cc98996ebf7bfb9c5bdc99a1b151af6c6f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 9 May 2023 09:32:39 +0530 Subject: [PATCH] A new escape code that moves the current contents of the screen into the scrollback before clearing it --- docs/changelog.rst | 2 ++ kitty/options/definition.py | 3 +-- kitty/screen.c | 28 +++++++++++++++++++++++++++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 482a8d32e..59bdd22b8 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -38,6 +38,8 @@ Detailed list of changes 0.28.2 [future] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +- A new escape code ``[22J`` that moves the current contents of the screen into the scrollback before clearing it + - unicode_input kitten: Fix a regression in 0.28.0 that caused the order of recent and favorites entries to not be respected (:iss:`6214`) - unicode_input kitten: Fix a regression in 0.28.0 that caused editing of favorites to sometimes hang diff --git a/kitty/options/definition.py b/kitty/options/definition.py index 4a80eadb4..345d1bd87 100644 --- a/kitty/options/definition.py +++ b/kitty/options/definition.py @@ -3997,8 +3997,7 @@ clearing the screen, for example, for ZSH add the following to :file:`~/.zshrc`: .. code-block:: zsh scroll-and-clear-screen() { - printf '\\n%.0s' {1..$LINES} - zle clear-screen + printf "\e[H\e[22J" } zle -N scroll-and-clear-screen bindkey '^l' scroll-and-clear-screen diff --git a/kitty/screen.c b/kitty/screen.c index 630423bd6..65aa88179 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -1628,6 +1628,26 @@ screen_clear_scrollback(Screen *self) { } } +static Line* visual_line_(Screen *self, int y_); + +static void +screen_move_into_scrollback(Screen *self) { + if (self->linebuf != self->main_linebuf || self->margin_top != 0 || self->margin_bottom != self->lines - 1) return; + unsigned int num_of_lines_to_move = self->lines; + while (num_of_lines_to_move) { + Line *line = visual_line_(self, num_of_lines_to_move-1); + if (!line_is_empty(line)) break; + num_of_lines_to_move--; + } + if (num_of_lines_to_move) { + unsigned int top, bottom; + for (; num_of_lines_to_move; num_of_lines_to_move--) { + top = 0, bottom = num_of_lines_to_move - 1; + INDEX_UP + } + } +} + void screen_erase_in_display(Screen *self, unsigned int how, bool private) { /* Erases display in a specific way. @@ -1640,6 +1660,8 @@ screen_erase_in_display(Screen *self, unsigned int how, bool private) { including cursor position. * ``2`` -- Erases complete display. All lines are erased and changed to single-width. Cursor does not move. + * ``22`` -- Copy screen contents into scrollback if in main screen, + then do the same as ``2``. * ``3`` -- Erase complete display and scrollback buffer as well. :param bool private: when ``True`` character attributes are left unchanged */ @@ -1649,6 +1671,10 @@ screen_erase_in_display(Screen *self, unsigned int how, bool private) { a = self->cursor->y + 1; b = self->lines; break; case 1: a = 0; b = self->cursor->y; break; + case 22: + screen_move_into_scrollback(self); + how = 2; + /* fallthrough */ case 2: case 3: grman_clear(self->grman, how == 3, self->cell_size); @@ -1671,7 +1697,7 @@ screen_erase_in_display(Screen *self, unsigned int how, bool private) { self->is_dirty = true; clear_selection(&self->selections); } - if (how != 2) { + if (how < 2) { screen_erase_in_line(self, how, private); if (how == 1) linebuf_clear_attrs_and_dirty(self->linebuf, self->cursor->y); }