Cleanup clear to prompt implementation and allow moving cleared lies into scrollback
This commit is contained in:
parent
b8774327b6
commit
d4c302bea3
6 changed files with 48 additions and 18 deletions
|
|
@ -72,6 +72,9 @@ Detailed list of changes
|
|||
|
||||
- icat kitten: Add a command line argument to override terminal window size detection (:iss:`7165`)
|
||||
|
||||
- When :ac:`clearing terminal <clear_terminal>` add a new type ``to_cursor_scroll`` which can be
|
||||
used to clear to prompt while moving cleared lines into the scrollback
|
||||
|
||||
|
||||
0.32.2 [2024-02-12]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
|||
|
|
@ -1170,8 +1170,11 @@ def on_window_resize(self, os_window_id: int, w: int, h: int, dpi_changed: bool)
|
|||
map f1 clear_terminal scrollback active
|
||||
# Scroll the contents of the screen into the scrollback
|
||||
map f1 clear_terminal scroll active
|
||||
# Clear everything up to the line with the cursor
|
||||
# Clear everything up to the line with the cursor or if the cursor is at a prompt, the first line of the prompt.
|
||||
# Useful for clearing the screen up to the shell prompt and moving the shell prompt to the top of the screen.
|
||||
map f1 clear_terminal to_cursor active
|
||||
# Clear everything up to the line with the cursor or prompt, saving the cleared lines in the scrollback
|
||||
map f1 clear_terminal to_cursor_scroll active
|
||||
''')
|
||||
def clear_terminal(self, action: str, only_active: bool) -> None:
|
||||
if only_active:
|
||||
|
|
@ -1196,6 +1199,11 @@ def clear_terminal(self, action: str, only_active: bool) -> None:
|
|||
elif action == 'to_cursor':
|
||||
for w in windows:
|
||||
w.scroll_prompt_to_top(clear_scrollback=True)
|
||||
elif action == 'to_cursor_scroll':
|
||||
for w in windows:
|
||||
w.scroll_prompt_to_top(clear_scrollback=False)
|
||||
else:
|
||||
self.show_error(_('Unknown clear type'), _('The clear type: {} is unknown').format(action))
|
||||
|
||||
def increase_font_size(self) -> None: # legacy
|
||||
cfs = global_font_size()
|
||||
|
|
|
|||
|
|
@ -1171,7 +1171,7 @@ class Screen:
|
|||
def cmd_output(self, which: int, callback: Callable[[str], None], as_ansi: bool, insert_wrap_markers: bool) -> bool:
|
||||
pass
|
||||
|
||||
def scroll_until_cursor_prompt(self) -> None:
|
||||
def scroll_until_cursor_prompt(self, add_to_scrollback: bool = True) -> None:
|
||||
pass
|
||||
|
||||
def reset(self) -> None:
|
||||
|
|
|
|||
|
|
@ -93,6 +93,11 @@ def parse_send_text_bytes(text: str) -> bytes:
|
|||
return defines.expand_ansi_c_escapes(text).encode('utf-8')
|
||||
|
||||
|
||||
@func_with_args('scroll_prompt_to_top')
|
||||
def scroll_prompt_to_top(func: str, rest: str) -> FuncArgsType:
|
||||
return func, [to_bool(rest) if rest else False]
|
||||
|
||||
|
||||
@func_with_args('send_text')
|
||||
def send_text_parse(func: str, rest: str) -> FuncArgsType:
|
||||
args = rest.split(maxsplit=1)
|
||||
|
|
@ -211,7 +216,7 @@ def clear_terminal(func: str, rest: str) -> FuncArgsType:
|
|||
args = ['reset', True]
|
||||
else:
|
||||
action = vals[0].lower()
|
||||
if action not in ('reset', 'scroll', 'scrollback', 'clear', 'to_cursor',):
|
||||
if action not in ('reset', 'scroll', 'scrollback', 'clear', 'to_cursor', 'to_cursor_scroll'):
|
||||
log_error(f'{action} is unknown for clear_terminal, using reset')
|
||||
action = 'reset'
|
||||
args = [action, vals[1].lower() == 'active']
|
||||
|
|
|
|||
|
|
@ -1503,10 +1503,10 @@ screen_cursor_to_column(Screen *self, unsigned int column) {
|
|||
}
|
||||
}
|
||||
|
||||
#define INDEX_UP \
|
||||
#define INDEX_UP(add_to_history) \
|
||||
linebuf_index(self->linebuf, top, bottom); \
|
||||
INDEX_GRAPHICS(-1) \
|
||||
if (self->linebuf == self->main_linebuf && self->margin_top == 0) { \
|
||||
if (add_to_history) { \
|
||||
/* Only add to history when no top margin has been set */ \
|
||||
linebuf_init_line(self->linebuf, bottom); \
|
||||
historybuf_add_line(self->historybuf, self->linebuf->line, &self->as_ansi_buf); \
|
||||
|
|
@ -1525,17 +1525,29 @@ screen_index(Screen *self) {
|
|||
// Move cursor down one line, scrolling screen if needed
|
||||
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
||||
if (self->cursor->y == bottom) {
|
||||
INDEX_UP;
|
||||
const bool add_to_history = self->linebuf == self->main_linebuf && self->margin_top == 0;
|
||||
INDEX_UP(add_to_history);
|
||||
} else screen_cursor_down(self, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
screen_index_without_adding_to_history(Screen *self) {
|
||||
// Move cursor down one line, scrolling screen if needed
|
||||
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
||||
if (self->cursor->y == bottom) {
|
||||
INDEX_UP(false);
|
||||
} else screen_cursor_down(self, 1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
screen_scroll(Screen *self, unsigned int count) {
|
||||
// Scroll the screen up by count lines, not moving the cursor
|
||||
unsigned int top = self->margin_top, bottom = self->margin_bottom;
|
||||
const bool add_to_history = self->linebuf == self->main_linebuf && self->margin_top == 0;
|
||||
while (count > 0) {
|
||||
count--;
|
||||
INDEX_UP;
|
||||
INDEX_UP(add_to_history);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1868,9 +1880,10 @@ screen_move_into_scrollback(Screen *self) {
|
|||
}
|
||||
if (num_of_lines_to_move) {
|
||||
unsigned int top, bottom;
|
||||
const bool add_to_history = self->linebuf == self->main_linebuf && self->margin_top == 0;
|
||||
for (; num_of_lines_to_move; num_of_lines_to_move--) {
|
||||
top = 0, bottom = num_of_lines_to_move - 1;
|
||||
INDEX_UP
|
||||
INDEX_UP(add_to_history);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1945,14 +1958,15 @@ screen_insert_lines(Screen *self, unsigned int count) {
|
|||
}
|
||||
|
||||
static void
|
||||
screen_scroll_until_cursor_prompt(Screen *self) {
|
||||
screen_scroll_until_cursor_prompt(Screen *self, bool add_to_scrollback) {
|
||||
bool in_margins = cursor_within_margins(self);
|
||||
int q = screen_cursor_at_a_shell_prompt(self);
|
||||
unsigned int y = q > -1 ? (unsigned int)q : self->cursor->y;
|
||||
unsigned int num_lines_to_scroll = MIN(self->margin_bottom, y);
|
||||
unsigned int final_y = num_lines_to_scroll <= self->cursor->y ? self->cursor->y - num_lines_to_scroll : 0;
|
||||
self->cursor->y = self->margin_bottom;
|
||||
while (num_lines_to_scroll--) screen_index(self);
|
||||
if (add_to_scrollback) while (num_lines_to_scroll--) screen_index(self);
|
||||
else while (num_lines_to_scroll--) screen_index_without_adding_to_history(self);
|
||||
self->cursor->y = final_y;
|
||||
screen_ensure_bounds(self, false, in_margins);
|
||||
}
|
||||
|
|
@ -3751,7 +3765,8 @@ is_using_alternate_linebuf(Screen *self, PyObject *a UNUSED) {
|
|||
WRAP1E(cursor_back, 1, -1)
|
||||
WRAP1B(erase_in_line, 0)
|
||||
WRAP1B(erase_in_display, 0)
|
||||
WRAP0(scroll_until_cursor_prompt)
|
||||
static PyObject* scroll_until_cursor_prompt(Screen *self, PyObject *args) { int b=false; if(!PyArg_ParseTuple(args, "|p", &b)) return NULL; screen_scroll_until_cursor_prompt(self, b); Py_RETURN_NONE; }
|
||||
|
||||
WRAP0(clear_scrollback)
|
||||
|
||||
#define MODE_GETSET(name, uname) \
|
||||
|
|
@ -4699,7 +4714,7 @@ static PyMethodDef methods[] = {
|
|||
MND(erase_in_line, METH_VARARGS)
|
||||
MND(erase_in_display, METH_VARARGS)
|
||||
MND(clear_scrollback, METH_NOARGS)
|
||||
MND(scroll_until_cursor_prompt, METH_NOARGS)
|
||||
MND(scroll_until_cursor_prompt, METH_VARARGS)
|
||||
MND(hyperlinks_as_list, METH_NOARGS)
|
||||
MND(garbage_collect_hyperlink_pool, METH_NOARGS)
|
||||
MND(hyperlink_for_id, METH_O)
|
||||
|
|
|
|||
|
|
@ -1821,14 +1821,13 @@ def scroll_to_prompt(self, num_of_prompts: int = -1) -> Optional[bool]:
|
|||
return None
|
||||
return True
|
||||
|
||||
@ac('sc', 'Scroll prompt to the top of the screen, filling screen with empty lines, when in main screen')
|
||||
@ac('sc', 'Scroll prompt to the top of the screen, filling screen with empty lines, when in main screen.'
|
||||
' To avoid putting the lines above the prompt into the scrollback use scroll_prompt_to_top y')
|
||||
def scroll_prompt_to_top(self, clear_scrollback: bool = False) -> Optional[bool]:
|
||||
if self.screen.is_main_linebuf():
|
||||
self.screen.scroll_until_cursor_prompt()
|
||||
if clear_scrollback:
|
||||
self.screen.clear_scrollback()
|
||||
elif self.screen.scrolled_by > 0:
|
||||
self.screen.scroll(SCROLL_FULL, False)
|
||||
self.screen.scroll_until_cursor_prompt(not clear_scrollback)
|
||||
if self.screen.scrolled_by > 0:
|
||||
self.scroll_end()
|
||||
return None
|
||||
return True
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue