This commit is contained in:
Kovid Goyal 2025-06-27 08:35:40 +05:30
commit 63758f6692
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
4 changed files with 47 additions and 14 deletions

View file

@ -1305,7 +1305,7 @@ class Screen:
def scroll_to_next_mark(self, mark: int = 0, backwards: bool = True) -> bool:
pass
def scroll_to_prompt(self, num_of_prompts: int = -1) -> bool:
def scroll_to_prompt(self, num_of_prompts: int = -1, scroll_offset = 0) -> bool:
pass
def set_last_visited_prompt(self, visual_y: int = 0) -> bool:

View file

@ -318,17 +318,40 @@ def remote_control_script(func: str, rest: str) -> FuncArgsType:
return func, args
@func_with_args('nth_os_window', 'nth_window', 'scroll_to_prompt', 'visual_window_select_action_trigger', 'next_layout')
@func_with_args('nth_os_window', 'nth_window', 'visual_window_select_action_trigger', 'next_layout')
def single_integer_arg(func: str, rest: str) -> FuncArgsType:
try:
num = int(rest)
except Exception:
if rest:
log_error(f'Invalid number for {func}: {rest}')
num = -1 if func == 'scroll_to_prompt' else 1
num = 1
return func, [num]
@func_with_args('scroll_to_prompt')
def scroll_to_prompt(func: str, rest: str) -> FuncArgsType:
vals = rest.strip().split()
if len(vals) > 2:
log_error('scroll_to_prompt needs one or two arguments, using defaults')
args = [-1, 0]
else:
try:
args = [int(vals[0])]
except Exception:
log_error(f'{vals[0]} is not a valid number of prompts to jump')
args = [-1]
if len(vals) == 2:
try:
args.append(int(vals[1]))
except Exception:
log_error(f'{vals[1]} is not a valid scroll offset')
args.append(0)
else:
args.append(0)
return func, args
@func_with_args('sleep')
def sleep(func: str, sleep_time: str) -> FuncArgsType:
mult = 1

View file

@ -2891,7 +2891,7 @@ shell_prompt_marking(Screen *self, char *buf) {
}
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, int scroll_offset) {
if (self->linebuf != self->main_linebuf) return false;
unsigned int old = self->scrolled_by;
if (num_of_prompts_to_jump == 0) {
@ -2903,6 +2903,7 @@ screen_history_scroll_to_prompt(Screen *self, int 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;
y += scroll_offset;
while (num_of_prompts_to_jump) {
y += delta;
ensure_y_ok;
@ -2910,6 +2911,7 @@ screen_history_scroll_to_prompt(Screen *self, int num_of_prompts_to_jump) {
num_of_prompts_to_jump--;
}
}
y -= scroll_offset;
#undef ensure_y_ok
self->scrolled_by = y >= 0 ? 0 : -y;
screen_set_last_visited_prompt(self, 0);
@ -4728,8 +4730,9 @@ scroll(Screen *self, PyObject *args) {
static PyObject*
scroll_to_prompt(Screen *self, PyObject *args) {
int num_of_prompts = -1;
if (!PyArg_ParseTuple(args, "|i", &num_of_prompts)) return NULL;
if (screen_history_scroll_to_prompt(self, num_of_prompts)) { Py_RETURN_TRUE; }
int scroll_offset = 0;
if (!PyArg_ParseTuple(args, "|ii", &num_of_prompts, &scroll_offset)) return NULL;
if (screen_history_scroll_to_prompt(self, num_of_prompts, scroll_offset)) { Py_RETURN_TRUE; }
Py_RETURN_FALSE;
}

View file

@ -2029,18 +2029,25 @@ def scroll_end(self) -> bool | None:
@ac('sc', '''
Scroll to the previous/next shell command prompt
Allows easy jumping from one command to the next. Requires working
: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.
A value of zero will jump to the last prompt visited by this action.
:ref:`shell_integration`. Takes two optional numbers as arguments:
The first is 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. Defaults to -1
The second is the number of lines to show above the prompt that was
jumped to. This is somewhat like `less`'s `--jump-target` option or
vim's `scrolloff` setting. Defaults to 0.
For example::
map ctrl+p scroll_to_prompt -1 # jump to previous
map ctrl+n scroll_to_prompt 1 # jump to next
map ctrl+o scroll_to_prompt 0 # jump to last visited
map ctrl+p scroll_to_prompt -1 3 # jump to previous, showing 3 lines prior
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) -> bool | None:
def scroll_to_prompt(self, num_of_prompts: int = -1, scroll_offset: int = 0) -> bool | None:
if self.screen.is_main_linebuf():
self.screen.scroll_to_prompt(num_of_prompts)
self.screen.scroll_to_prompt(num_of_prompts, scroll_offset)
return None
return True