Save the last jumped prompt position

This commit is contained in:
pagedown 2021-11-14 15:09:32 +08:00 committed by Kovid Goyal
parent bc454b4417
commit 9fe9c74021
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 32 additions and 15 deletions

View File

@ -64,6 +64,11 @@ init_overlay_line(Screen *self, index_type columns) {
return true; return true;
} }
static void
clear_last_visited_prompt(Screen *self) {
self->last_visited_prompt_scrolled_by = self->historybuf->count + 1;
}
#define RESET_CHARSETS \ #define RESET_CHARSETS \
self->g0_charset = translation_table(0); \ self->g0_charset = translation_table(0); \
self->g1_charset = self->g0_charset; \ self->g1_charset = self->g0_charset; \
@ -143,6 +148,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
self->hyperlink_pool = alloc_hyperlink_pool(); self->hyperlink_pool = alloc_hyperlink_pool();
if (!self->hyperlink_pool) { Py_CLEAR(self); return PyErr_NoMemory(); } if (!self->hyperlink_pool) { Py_CLEAR(self); return PyErr_NoMemory(); }
self->as_ansi_buf.hyperlink_pool = self->hyperlink_pool; self->as_ansi_buf.hyperlink_pool = self->hyperlink_pool;
clear_last_visited_prompt(self);
} }
return (PyObject*) self; return (PyObject*) self;
} }
@ -389,6 +395,7 @@ screen_resize(Screen *self, unsigned int lines, unsigned int columns) {
self->is_dirty = true; self->is_dirty = true;
clear_selection(&self->selections); clear_selection(&self->selections);
clear_selection(&self->url_ranges); clear_selection(&self->url_ranges);
clear_last_visited_prompt(self);
/* printf("old_cursor: (%u, %u) new_cursor: (%u, %u) beyond_content: %d\n", self->cursor->x, self->cursor->y, cursor_x, cursor_y, cursor_is_beyond_content); */ /* printf("old_cursor: (%u, %u) new_cursor: (%u, %u) beyond_content: %d\n", self->cursor->x, self->cursor->y, cursor_x, cursor_y, cursor_is_beyond_content); */
#define S(c, w) c->x = MIN(w.after.x, self->columns - 1); c->y = MIN(w.after.y, self->lines - 1); #define S(c, w) c->x = MIN(w.after.x, self->columns - 1); c->y = MIN(w.after.y, self->lines - 1);
S(self->cursor, cursor); S(self->cursor, cursor);
@ -1268,6 +1275,7 @@ screen_cursor_to_column(Screen *self, unsigned int column) {
linebuf_init_line(self->linebuf, bottom); \ linebuf_init_line(self->linebuf, bottom); \
historybuf_add_line(self->historybuf, self->linebuf->line, &self->as_ansi_buf); \ historybuf_add_line(self->historybuf, self->linebuf->line, &self->as_ansi_buf); \
self->history_line_added_count++; \ self->history_line_added_count++; \
if (self->last_visited_prompt_scrolled_by <= self->historybuf->count) self->last_visited_prompt_scrolled_by++; \
} \ } \
linebuf_clear_line(self->linebuf, bottom, true); \ linebuf_clear_line(self->linebuf, bottom, true); \
self->is_dirty = true; \ self->is_dirty = true; \
@ -2017,22 +2025,28 @@ shell_prompt_marking(Screen *self, PyObject *data) {
static bool static bool
screen_history_scroll_to_prompt(Screen *self, int num_of_prompts_to_jump) { screen_history_scroll_to_prompt(Screen *self, int num_of_prompts_to_jump) {
if (self->linebuf != self->main_linebuf || !num_of_prompts_to_jump) return false; if (self->linebuf != self->main_linebuf) return false;
int delta = num_of_prompts_to_jump < 0 ? -1 : 1;
num_of_prompts_to_jump = num_of_prompts_to_jump < 0 ? -num_of_prompts_to_jump : num_of_prompts_to_jump;
int y = -self->scrolled_by;
#define ensure_y_ok if (y >= (int)self->lines || -y > (int)self->historybuf->count) return false;
ensure_y_ok;
while (num_of_prompts_to_jump) {
y += delta;
ensure_y_ok;
if (range_line_(self, y)->attrs.prompt_kind == PROMPT_START) {
num_of_prompts_to_jump--;
}
}
#undef ensure_y_ok
unsigned int old = self->scrolled_by; unsigned int old = self->scrolled_by;
self->scrolled_by = y >= 0 ? 0 : -y; if (num_of_prompts_to_jump == 0) {
if (self->last_visited_prompt_scrolled_by > self->historybuf->count) return false;
self->scrolled_by = self->last_visited_prompt_scrolled_by;
} else {
int delta = num_of_prompts_to_jump < 0 ? -1 : 1;
num_of_prompts_to_jump = num_of_prompts_to_jump < 0 ? -num_of_prompts_to_jump : num_of_prompts_to_jump;
int y = -self->scrolled_by;
#define ensure_y_ok if (y >= (int)self->lines || -y > (int)self->historybuf->count) return false;
ensure_y_ok;
while (num_of_prompts_to_jump) {
y += delta;
ensure_y_ok;
if (range_line_(self, y)->attrs.prompt_kind == PROMPT_START) {
num_of_prompts_to_jump--;
}
}
#undef ensure_y_ok
self->scrolled_by = y >= 0 ? 0 : -y;
self->last_visited_prompt_scrolled_by = self->scrolled_by;
}
if (old != self->scrolled_by) self->scroll_changed = true; if (old != self->scrolled_by) self->scroll_changed = true;
return old != self->scrolled_by; return old != self->scrolled_by;
} }

View File

@ -144,6 +144,7 @@ typedef struct {
uint8_t *canvas; uint8_t *canvas;
size_t requested_height, width_px, height_px; size_t requested_height, width_px, height_px;
} last_rendered_window_char; } last_rendered_window_char;
unsigned int last_visited_prompt_scrolled_by;
} Screen; } Screen;

View File

@ -1180,10 +1180,12 @@ class Window:
Allows easy jumping from one command to the next. Requires working Allows easy jumping from one command to the next. Requires working
:ref:`shell_integration`. Takes a single, optional, number as argument which is :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. the number of prompts to jump, negative values jump up and positive values jump down.
A value of zero will jump to the last prompt visited by this action.
For example:: For example::
map ctrl+p scroll_to_prompt -1 # jump to previous map ctrl+p scroll_to_prompt -1 # jump to previous
map ctrl+n scroll_to_prompt 1 # jump to next map ctrl+n scroll_to_prompt 1 # jump to next
map ctrl+o scroll_to_prompt 0 # jump to last visited
''') ''')
def scroll_to_prompt(self, num_of_prompts: int = -1) -> None: def scroll_to_prompt(self, num_of_prompts: int = -1) -> None:
if self.screen.is_main_linebuf(): if self.screen.is_main_linebuf():