Use a single function for getting command output

This commit is contained in:
Kovid Goyal 2021-11-15 13:47:05 +05:30
parent 80b5f31256
commit 6afaec1d62
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
7 changed files with 60 additions and 67 deletions

View File

@ -62,7 +62,7 @@ from .utils import (
remove_socket_file, safe_print, set_primary_selection, single_instance,
startup_notification_handler
)
from .window import MatchPatternType, Window
from .window import MatchPatternType, Window, CommandOutput
class OSWindowDict(TypedDict):
@ -111,17 +111,17 @@ def data_for_at(w: Optional[Window], arg: str, add_wrap_markers: bool = False) -
if arg == '@ansi_alternate_scrollback':
return as_text(as_ansi=True, alternate_screen=True, add_history=True)
if arg == '@first_cmd_output_on_screen':
return w.first_cmd_output_on_screen(add_wrap_markers=add_wrap_markers)
return w.cmd_output(CommandOutput.first_on_screen, add_wrap_markers=add_wrap_markers)
if arg == '@ansi_first_cmd_output_on_screen':
return w.first_cmd_output_on_screen(as_ansi=True, add_wrap_markers=add_wrap_markers)
return w.cmd_output(CommandOutput.first_on_screen, as_ansi=True, add_wrap_markers=add_wrap_markers)
if arg == '@last_cmd_output':
return w.last_cmd_output(add_wrap_markers=add_wrap_markers)
return w.cmd_output(CommandOutput.last_run, add_wrap_markers=add_wrap_markers)
if arg == '@ansi_last_cmd_output':
return w.last_cmd_output(as_ansi=True, add_wrap_markers=add_wrap_markers)
return w.cmd_output(CommandOutput.last_run, as_ansi=True, add_wrap_markers=add_wrap_markers)
if arg == '@last_visited_cmd_output':
return w.last_visited_cmd_output(add_wrap_markers=add_wrap_markers)
return w.cmd_output(CommandOutput.last_visited, add_wrap_markers=add_wrap_markers)
if arg == '@ansi_last_visited_cmd_output':
return w.last_visited_cmd_output(as_ansi=True, add_wrap_markers=add_wrap_markers)
return w.cmd_output(CommandOutput.last_visited, as_ansi=True, add_wrap_markers=add_wrap_markers)
return None
@ -1320,8 +1320,10 @@ class Boss:
sel = self.data_for_at(which='@selection', window=w)
data = sel.encode('utf-8') if sel else None
elif q[0] in ('output', 'first_output', 'last_visited_output'):
func = {'output': w.last_cmd_output, 'first_output': w.first_cmd_output_on_screen, 'last_visited_output': w.last_visited_cmd_output}[q[0]]
data = func(as_ansi='ansi' in q, add_wrap_markers='screen' in q).encode('utf-8')
which = {
'output': CommandOutput.last_run, 'first_output': CommandOutput.first_on_screen,
'last_visited_output': CommandOutput.last_visited}[q[0]]
data = w.cmd_output(which, as_ansi='ansi' in q, add_wrap_markers='screen' in q).encode('utf-8')
else:
raise ValueError(f'Unknown type_of_input: {type_of_input}')
else:

View File

@ -1120,9 +1120,9 @@ class Screen:
pass
as_text_non_visual = as_text
as_text_alternate = as_text
first_cmd_output_on_screen = as_text
last_cmd_output = as_text
last_visited_cmd_output = as_text
def cmd_output(self, which: int, callback: Callable[[str], None], as_ansi: bool, insert_wrap_markers: bool) -> None:
pass
def scroll_until_cursor(self) -> None:
pass

View File

@ -3033,9 +3033,8 @@ For example, the following opens the output in less in an overlay window::
map f1 launch --stdin-source=@last_cmd_output --stdin-add-formatting --type=overlay less +G -R
To get the first command output on the screen, use :code:`@first_cmd_output_on_screen`.
To get the first command output below the last scrolled position via scroll_to_prompt, use
:code:`@last_visited_cmd_output`.
To get the output of the first command on the screen, use :code:`@first_cmd_output_on_screen`.
To get the output of the last jumped to command, use :code:`@last_visited_cmd_output`.
''')
egr() # }}}

View File

@ -74,21 +74,25 @@ If specified get text from the window this command is run in, rather than the ac
}
def response_from_kitty(self, boss: Boss, window: Optional[Window], payload_get: PayloadGetType) -> ResponseType:
from kitty.window import CommandOutput
window = self.windows_for_match_payload(boss, window, payload_get)[0]
if payload_get('extent') == 'selection':
ans = window.text_for_selection()
elif payload_get('extent') == 'first_cmd_output_on_screen':
ans = window.first_cmd_output_on_screen(
ans = window.cmd_output(
CommandOutput.first_on_screen,
as_ansi=bool(payload_get('ansi')),
add_wrap_markers=bool(payload_get('wrap_markers')),
)
elif payload_get('extent') == 'last_cmd_output':
ans = window.last_cmd_output(
ans = window.cmd_output(
CommandOutput.last_run,
as_ansi=bool(payload_get('ansi')),
add_wrap_markers=bool(payload_get('wrap_markers')),
)
elif payload_get('extent') == 'last_visited_cmd_output':
ans = window.last_visited_cmd_output(
ans = window.cmd_output(
CommandOutput.last_visited,
as_ansi=bool(payload_get('ansi')),
add_wrap_markers=bool(payload_get('wrap_markers')),
)

View File

@ -2736,39 +2736,35 @@ find_cmd_output(Screen *self, OutputOffset *oo, index_type start_y, unsigned int
}
static PyObject*
first_cmd_output_on_screen(Screen *self, PyObject *args) {
if (self->linebuf != self->main_linebuf) return PyUnicode_FromString("");
cmd_output(Screen *self, PyObject *args) {
unsigned int which = 0;
DECREF_AFTER_FUNCTION PyObject *which_args = PyTuple_GetSlice(args, 0, 1);
DECREF_AFTER_FUNCTION PyObject *as_text_args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
if (!which_args || !as_text_args) return NULL;
if (!PyArg_ParseTuple(which_args, "I", &which)) return NULL;
if (self->linebuf != self->main_linebuf) Py_RETURN_NONE;
OutputOffset oo = {.screen=self};
if (find_cmd_output(self, &oo, 0, self->scrolled_by, 1, true)) {
return as_text_generic(args, &oo, get_line_from_offset, oo.num_lines, &self->as_ansi_buf);
bool found = false;
switch (which) {
case 0: // last run cmd
found = find_cmd_output(self, &oo, self->cursor->y, self->scrolled_by, -1, false);
break;
case 1: // first on screen
found = find_cmd_output(self, &oo, 0, self->scrolled_by, 1, true);
break;
case 2: // last visited cmd
if (self->last_visited_prompt.scrolled_by <= self->historybuf->count && self->last_visited_prompt.is_set) {
found = find_cmd_output(self, &oo, 0, self->last_visited_prompt.scrolled_by, 0, false);
} break;
default:
PyErr_Format(PyExc_KeyError, "%u is not a valid type of command", which);
return NULL;
}
return PyUnicode_FromString("");
if (found) return as_text_generic(as_text_args, &oo, get_line_from_offset, oo.num_lines, &self->as_ansi_buf);
Py_RETURN_NONE;
}
static PyObject*
last_cmd_output(Screen *self, PyObject *args) {
if (self->linebuf != self->main_linebuf) return PyUnicode_FromString("");
OutputOffset oo = {.screen=self};
if (find_cmd_output(self, &oo, self->cursor->y, self->scrolled_by, -1, false)) {
return as_text_generic(args, &oo, get_line_from_offset, oo.num_lines, &self->as_ansi_buf);
}
return PyUnicode_FromString("");
}
static PyObject*
last_visited_cmd_output(Screen *self, PyObject *args) {
if (self->linebuf != self->main_linebuf || self->last_visited_prompt.scrolled_by > self->historybuf->count || !self->last_visited_prompt.is_set) return PyUnicode_FromString("");
OutputOffset oo = {.screen=self};
if (find_cmd_output(self, &oo, 0, self->last_visited_prompt.scrolled_by, 0, false)) {
return as_text_generic(args, &oo, get_line_from_offset, oo.num_lines, &self->as_ansi_buf);
}
return PyUnicode_FromString("");
}
static PyObject*
screen_truncate_point_for_length(PyObject UNUSED *self, PyObject *args) {
PyObject *str; unsigned int num_cells, start_pos = 0;
@ -3758,9 +3754,7 @@ static PyMethodDef methods[] = {
MND(as_text, METH_VARARGS)
MND(as_text_non_visual, METH_VARARGS)
MND(as_text_alternate, METH_VARARGS)
MND(first_cmd_output_on_screen, METH_VARARGS)
MND(last_cmd_output, METH_VARARGS)
MND(last_visited_cmd_output, METH_VARARGS)
MND(cmd_output, METH_VARARGS)
MND(tab, METH_NOARGS)
MND(backspace, METH_NOARGS)
MND(linefeed, METH_NOARGS)

View File

@ -87,6 +87,10 @@ class DynamicColor(IntEnum):
default_fg, default_bg, cursor_color, highlight_fg, highlight_bg = range(1, 6)
class CommandOutput(IntEnum):
last_run, first_on_screen, last_visited = 0, 1, 2
DYNAMIC_COLOR_CODES = {
10: DynamicColor.default_fg,
11: DynamicColor.default_bg,
@ -1041,19 +1045,9 @@ class Window:
) -> str:
return as_text(self.screen, as_ansi, add_history, add_wrap_markers, alternate_screen, add_cursor)
def first_cmd_output_on_screen(self, as_ansi: bool = False, add_wrap_markers: bool = False) -> str:
def cmd_output(self, which: CommandOutput = CommandOutput.last_run, as_ansi: bool = False, add_wrap_markers: bool = False) -> str:
lines: List[str] = []
self.screen.first_cmd_output_on_screen(lines.append, as_ansi, add_wrap_markers)
return ''.join(lines)
def last_cmd_output(self, as_ansi: bool = False, add_wrap_markers: bool = False) -> str:
lines: List[str] = []
self.screen.last_cmd_output(lines.append, as_ansi, add_wrap_markers)
return ''.join(lines)
def last_visited_cmd_output(self, as_ansi: bool = False, add_wrap_markers: bool = False) -> str:
lines: List[str] = []
self.screen.last_visited_cmd_output(lines.append, as_ansi, add_wrap_markers)
self.screen.cmd_output(which, lines.append, as_ansi, add_wrap_markers)
return ''.join(lines)
@property
@ -1091,7 +1085,7 @@ class Window:
Requires :ref:`shell_integration` to work
''')
def show_first_command_output_on_screen(self) -> None:
text = self.first_cmd_output_on_screen(as_ansi=True, add_wrap_markers=True)
text = self.cmd_output(CommandOutput.first_on_screen, as_ansi=True, add_wrap_markers=True)
text = text.replace('\r\n', '\n').replace('\r', '\n')
get_boss().display_scrollback(self, text, title='First command output on screen', report_cursor=False)
@ -1101,7 +1095,7 @@ class Window:
Requires :ref:`shell_integration` to work
''')
def show_last_command_output(self) -> None:
text = self.last_cmd_output(as_ansi=True, add_wrap_markers=True)
text = self.cmd_output(CommandOutput.last_run, as_ansi=True, add_wrap_markers=True)
text = text.replace('\r\n', '\n').replace('\r', '\n')
get_boss().display_scrollback(self, text, title='Last command output', report_cursor=False)
@ -1111,7 +1105,7 @@ class Window:
Requires :ref:`shell_integration` to work
''')
def show_last_visited_command_output(self) -> None:
text = self.last_visited_cmd_output(as_ansi=True, add_wrap_markers=True)
text = self.cmd_output(CommandOutput.last_visited, as_ansi=True, add_wrap_markers=True)
text = text.replace('\r\n', '\n').replace('\r', '\n')
get_boss().display_scrollback(self, text, title='Last visited command output', report_cursor=False)

View File

@ -959,12 +959,12 @@ class TestScreen(BaseTest):
def fco():
a = []
s.first_cmd_output_on_screen(a.append)
s.cmd_output(1, a.append)
return ''.join(a)
def lco():
a = []
s.last_cmd_output(a.append)
s.cmd_output(0, a.append)
return ''.join(a)
s = self.create_screen()