Use a single generic function to get text and ANSI representations of all buffers
This commit is contained in:
parent
97b4256ba4
commit
9c21610215
8 changed files with 81 additions and 57 deletions
|
|
@ -406,10 +406,8 @@ def run_simple_kitten(self, type_of_input, kitten, *args):
|
|||
args = shlex.split(cmdline) if cmdline else []
|
||||
if '--program' not in cmdline:
|
||||
args.extend(('--program', self.opts.open_url_with))
|
||||
if type_of_input in ('text', 'history'):
|
||||
data = (w.buffer_as_text if type_of_input == 'history' else w.as_text)().encode('utf-8')
|
||||
elif type_of_input in ('ansi', 'ansi-history'):
|
||||
data = (w.buffer_as_ansi() if type_of_input == 'ansi-history' else w.as_text(as_ansi=True)).encode('utf-8')
|
||||
if type_of_input in ('text', 'history', 'ansi', 'ansi-history'):
|
||||
data = w.as_text(as_ansi='ansi' in type_of_input, add_history='history' in type_of_input).encode('utf-8')
|
||||
elif type_of_input == 'none':
|
||||
data = None
|
||||
else:
|
||||
|
|
@ -494,9 +492,13 @@ def data_for_at(arg):
|
|||
if arg == '@selection':
|
||||
return w.text_for_selection()
|
||||
if arg == '@ansi':
|
||||
return w.buffer_as_ansi()
|
||||
return w.as_text(as_ansi=True, add_history=True)
|
||||
if arg == '@text':
|
||||
return w.buffer_as_text()
|
||||
return w.as_text(add_history=True)
|
||||
if arg == '@screen':
|
||||
return w.as_text()
|
||||
if arg == '@ansi_screen':
|
||||
return w.as_text(as_ansi=True)
|
||||
|
||||
if args[0].startswith('@'):
|
||||
stdin = data_for_at(args[0]) or None
|
||||
|
|
|
|||
|
|
@ -202,6 +202,18 @@ as_ansi(HistoryBuf *self, PyObject *callback) {
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static inline Line*
|
||||
get_line(HistoryBuf *self, index_type y, Line *l) { init_line(self, y, l); return l; }
|
||||
|
||||
static PyObject*
|
||||
as_text(HistoryBuf *self, PyObject *args) {
|
||||
Line l = {.xnum=self->xnum};
|
||||
#define gl(self, y) get_line(self, y, &l);
|
||||
as_text_generic(args, self, gl, self->count, self->xnum, callback, as_ansi);
|
||||
#undef gl
|
||||
}
|
||||
|
||||
|
||||
static PyObject*
|
||||
dirty_lines(HistoryBuf *self) {
|
||||
#define dirty_lines_doc "dirty_lines() -> Line numbers of all lines that have dirty text."
|
||||
|
|
@ -223,6 +235,7 @@ static PyMethodDef methods[] = {
|
|||
METHOD(change_num_of_lines, METH_O)
|
||||
METHOD(line, METH_O)
|
||||
METHOD(as_ansi, METH_O)
|
||||
METHODB(as_text, METH_VARARGS),
|
||||
METHOD(dirty_lines, METH_NOARGS)
|
||||
METHOD(push, METH_VARARGS)
|
||||
METHOD(rewrap, METH_VARARGS)
|
||||
|
|
|
|||
|
|
@ -298,7 +298,8 @@ map ctrl+shift+0 tenth_window
|
|||
# map ctrl+shift+y new_window less @selection
|
||||
#
|
||||
# You can even send the contents of the current screen + history buffer as stdin using
|
||||
# the placeholders @text (which is the plain text) and @ansi (which includes text styling escape codes)
|
||||
# the placeholders @text (which is the plain text) and @ansi (which includes text styling escape codes).
|
||||
# For only the current screen, use @screen or @ansi_screen.
|
||||
# For example, the following command opens the scrollback buffer in less in a new window.
|
||||
# map ctrl+shift+y new_window @ansi less +G -R
|
||||
#
|
||||
|
|
|
|||
|
|
@ -406,6 +406,18 @@ as_ansi(LineBuf *self, PyObject *callback) {
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static inline Line*
|
||||
get_line(LineBuf *self, index_type y) {
|
||||
linebuf_init_line(self, y);
|
||||
return self->line;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
as_text(LineBuf *self, PyObject *args) {
|
||||
as_text_generic(args, self, get_line, self->ynum, self->xnum, callback, as_ansi);
|
||||
}
|
||||
|
||||
|
||||
static PyObject*
|
||||
__str__(LineBuf *self) {
|
||||
PyObject *lines = PyTuple_New(self->ynum);
|
||||
|
|
@ -440,6 +452,7 @@ static PyMethodDef methods[] = {
|
|||
METHOD(rewrap, METH_VARARGS)
|
||||
METHOD(clear, METH_NOARGS)
|
||||
METHOD(as_ansi, METH_O)
|
||||
METHODB(as_text, METH_VARARGS),
|
||||
METHOD(set_attribute, METH_VARARGS)
|
||||
METHOD(set_continued, METH_VARARGS)
|
||||
METHOD(dirty_lines, METH_NOARGS)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ xlimit_for_line(Line *line) {
|
|||
return xlimit;
|
||||
}
|
||||
|
||||
|
||||
void line_clear_text(Line *self, unsigned int at, unsigned int num, char_type ch);
|
||||
void line_apply_cursor(Line *self, Cursor *cursor, unsigned int at, unsigned int num, bool clear_char);
|
||||
void line_set_char(Line *, unsigned int , uint32_t , unsigned int , Cursor *, bool);
|
||||
|
|
@ -79,3 +80,39 @@ void historybuf_mark_line_clean(HistoryBuf *self, index_type y);
|
|||
void historybuf_mark_line_dirty(HistoryBuf *self, index_type y);
|
||||
void historybuf_refresh_sprite_positions(HistoryBuf *self);
|
||||
void historybuf_clear(HistoryBuf *self);
|
||||
|
||||
|
||||
#define as_text_generic(args, container, get_line, lines, columns, callback, as_ansi) { \
|
||||
PyObject *callback; \
|
||||
int as_ansi = 0; \
|
||||
if (!PyArg_ParseTuple(args, "O|p", &callback, &as_ansi)) return NULL; \
|
||||
PyObject *ret = NULL, *t = NULL; \
|
||||
Py_UCS4 *buf = NULL; \
|
||||
PyObject *nl = PyUnicode_FromString("\n"); \
|
||||
if (nl == NULL) goto end; \
|
||||
if (as_ansi) { \
|
||||
buf = malloc(sizeof(Py_UCS4) * columns * 100); \
|
||||
if (buf == NULL) { PyErr_NoMemory(); goto end; } \
|
||||
} \
|
||||
for (index_type y = 0; y < lines; y++) { \
|
||||
Line *line = get_line(container, y); \
|
||||
if (!line->continued && y > 0) { \
|
||||
ret = PyObject_CallFunctionObjArgs(callback, nl, NULL); \
|
||||
if (ret == NULL) goto end; \
|
||||
Py_CLEAR(ret); \
|
||||
} \
|
||||
if (as_ansi) { \
|
||||
index_type num = line_as_ansi(line, buf, columns * 100 - 2); \
|
||||
t = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, num); \
|
||||
} else { \
|
||||
t = PyObject_Str((PyObject*)line); \
|
||||
} \
|
||||
if (t == NULL) goto end; \
|
||||
ret = PyObject_CallFunctionObjArgs(callback, t, NULL); \
|
||||
Py_DECREF(t); if (ret == NULL) goto end; Py_DECREF(ret); \
|
||||
} \
|
||||
end: \
|
||||
Py_CLEAR(nl); free(buf); \
|
||||
if (PyErr_Occurred()) return NULL; \
|
||||
Py_RETURN_NONE; \
|
||||
}
|
||||
|
|
|
|||
|
|
@ -387,8 +387,7 @@ def get_text(boss, window, payload):
|
|||
if payload['extent'] == 'selection':
|
||||
ans = window.text_for_selection()
|
||||
else:
|
||||
f = window.buffer_as_ansi if payload['ansi'] else window.buffer_as_text
|
||||
ans = f(add_history=payload['extent'] == 'all')
|
||||
ans = window.as_text(as_ansi=bool(payload['ansi']), add_history=True)
|
||||
return ans
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1454,37 +1454,7 @@ screen_open_url(Screen *self) {
|
|||
|
||||
static PyObject*
|
||||
as_text(Screen *self, PyObject *args) {
|
||||
PyObject *callback, *ret = NULL, *t = NULL;
|
||||
Py_UCS4 *buf = NULL;
|
||||
int as_ansi = 0;
|
||||
if (!PyArg_ParseTuple(args, "O|p", &callback, &as_ansi)) return NULL;
|
||||
PyObject *nl = PyUnicode_FromString("\n");
|
||||
if (nl == NULL) goto end;
|
||||
if (as_ansi) {
|
||||
buf = malloc(sizeof(Py_UCS4) * self->columns * 100);
|
||||
if (buf == NULL) { PyErr_NoMemory(); goto end; }
|
||||
}
|
||||
for (index_type y = 0; y < self->lines; y++) {
|
||||
Line *line = visual_line_(self, y);
|
||||
if (!line->continued && y > 0) {
|
||||
ret = PyObject_CallFunctionObjArgs(callback, nl, NULL);
|
||||
if (ret == NULL) goto end;
|
||||
Py_CLEAR(ret);
|
||||
}
|
||||
if (as_ansi) {
|
||||
index_type num = line_as_ansi(line, buf, self->columns * 100 - 2);
|
||||
t = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, num);
|
||||
} else {
|
||||
t = PyObject_Str((PyObject*)line);
|
||||
}
|
||||
if (t == NULL) goto end;
|
||||
ret = PyObject_CallFunctionObjArgs(callback, t, NULL);
|
||||
Py_DECREF(t); if (ret == NULL) goto end; Py_DECREF(ret);
|
||||
}
|
||||
end:
|
||||
Py_CLEAR(nl); free(buf);
|
||||
if (PyErr_Occurred()) return NULL;
|
||||
Py_RETURN_NONE;
|
||||
as_text_generic(args, self, visual_line_, self->lines, self->columns, callback, as_ansi);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
|
|
|
|||
|
|
@ -315,30 +315,19 @@ def destroy(self):
|
|||
self.screen.reset_callbacks()
|
||||
self.screen = None
|
||||
|
||||
def buffer_as_ansi(self, add_history=True):
|
||||
data = []
|
||||
if add_history:
|
||||
self.screen.historybuf.as_ansi(data.append)
|
||||
self.screen.linebuf.as_ansi(data.append)
|
||||
return ''.join(data)
|
||||
|
||||
def buffer_as_text(self, add_history=True):
|
||||
ans = str(self.screen.linebuf).rstrip('\n')
|
||||
if add_history:
|
||||
h = str(self.screen.historybuf)
|
||||
if h.strip():
|
||||
ans = h + '\n' + ans
|
||||
return ans
|
||||
|
||||
def as_text(self, as_ansi=False):
|
||||
def as_text(self, as_ansi=False, add_history=False):
|
||||
lines = []
|
||||
self.screen.as_text(lines.append, as_ansi)
|
||||
if add_history:
|
||||
h = []
|
||||
self.screen.historybuf.as_text(h.append, as_ansi)
|
||||
lines = h + lines
|
||||
return ''.join(lines)
|
||||
|
||||
# actions {{{
|
||||
|
||||
def show_scrollback(self):
|
||||
get_boss().display_scrollback(self, self.buffer_as_ansi().encode('utf-8'))
|
||||
get_boss().display_scrollback(self, self.as_text(as_ansi=True, add_history=True).encode('utf-8'))
|
||||
|
||||
def paste(self, text):
|
||||
if text and not self.destroyed:
|
||||
|
|
|
|||
Loading…
Reference in a new issue