From a1a0c9ab8065f1a5e138098f453c027ab10f4b09 Mon Sep 17 00:00:00 2001 From: pagedown Date: Fri, 4 Feb 2022 22:52:06 +0800 Subject: [PATCH] Add new mappable action scroll_prompt_to_bottom --- docs/changelog.rst | 3 +++ kitty/fast_data_types.pyi | 3 +++ kitty/screen.c | 28 ++++++++++++++++++++++++++++ kitty/window.py | 4 ++++ 4 files changed, 38 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index f27f28ada..520686f71 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -93,6 +93,9 @@ Detailed list of changes - Fix a regression in the previous release that broke strikethrough (:disc:`4632`) +- A new action :ac:`scroll_prompt_to_bottom` to moves the non-empty prompt lines + to the bottom. (:pull:`4634`) + 0.24.2 [2022-02-03] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index 804b139b6..adc079fb4 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1105,6 +1105,9 @@ class Screen: def reverse_scroll(self, amt: int, fill_from_scrollback: bool = False) -> bool: pass + def scroll_prompt_to_bottom(self) -> None: + pass + def clear_selection(self) -> None: pass diff --git a/kitty/screen.c b/kitty/screen.c index b8d0ae211..70328f7ea 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -3718,6 +3718,33 @@ reverse_scroll(Screen *self, PyObject *args) { Py_RETURN_NONE; } + +static PyObject* +scroll_prompt_to_bottom(Screen *self, PyObject *args UNUSED) { + if (self->linebuf != self->main_linebuf || !self->historybuf->count) Py_RETURN_NONE; + int q = screen_cursor_at_a_shell_prompt(self); + index_type limit_y = q > -1 ? (unsigned int)q : self->cursor->y; + index_type y = self->lines - 1; + // not before prompt or cursor line + while (y > limit_y) { + Line *line = checked_range_line(self, y); + if (line_length(line)) break; + y--; + } + // don't scroll back beyond the history buffer range + unsigned int count = MIN(self->lines - (y + 1), self->historybuf->count); + if (count > 0) { + _reverse_scroll(self, count, true); + screen_cursor_down(self, count); + } + // always scroll to the bottom + if (self->scrolled_by != 0) { + self->scrolled_by = 0; + self->scroll_changed = true; + } + Py_RETURN_NONE; +} + static PyObject* dump_lines_with_attrs(Screen *self, PyObject *accum) { int y = (self->linebuf == self->main_linebuf) ? -self->historybuf->count : 0; @@ -3790,6 +3817,7 @@ static PyMethodDef methods[] = { MND(garbage_collect_hyperlink_pool, METH_NOARGS) MND(hyperlink_for_id, METH_O) MND(reverse_scroll, METH_VARARGS) + MND(scroll_prompt_to_bottom, METH_NOARGS) METHOD(current_char_width, METH_NOARGS) MND(insert_lines, METH_VARARGS) MND(delete_lines, METH_VARARGS) diff --git a/kitty/window.py b/kitty/window.py index 95c54511d..345530729 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -1241,6 +1241,10 @@ class Window: if self.screen.is_main_linebuf(): self.screen.scroll_to_prompt(num_of_prompts) + @ac('sc', 'Scroll prompt to the bottom of the screen') + def scroll_prompt_to_bottom(self) -> None: + self.screen.scroll_prompt_to_bottom() + @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