From e5a7ba4f2280bbea75e400c629fda7b7d7f5d465 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 9 Sep 2018 15:32:05 +0530 Subject: [PATCH] Allow viewing the current contents of the alternate screen in a new window. Fixes #933 --- kitty/boss.py | 4 ++++ kitty/config_data.py | 3 ++- kitty/screen.c | 16 ++++++++++++++++ kitty/window.py | 9 ++++++--- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/kitty/boss.py b/kitty/boss.py index 84147ee9a..81df7dbc6 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -790,6 +790,10 @@ class Boss: return w.as_text() if arg == '@ansi_screen': return w.as_text(as_ansi=True) + if arg == '@alternate': + return w.as_text(alternate_screen=True) + if arg == '@ansi_alternate': + return w.as_text(as_ansi=True, alternate_screen=True) if args[0].startswith('@') and args[0] != '@': stdin = data_for_at(args[0]) or None diff --git a/kitty/config_data.py b/kitty/config_data.py index 9660f7335..cdd660134 100644 --- a/kitty/config_data.py +++ b/kitty/config_data.py @@ -827,7 +827,8 @@ k('scroll_end', 'kitty_mod+end', 'scroll_end', _('Scroll to bottom')) k('show_scrollback', 'kitty_mod+h', 'show_scrollback', _('Browse scrollback buffer in less'), long_text=_(''' You can send the contents of the current screen + history buffer as stdin to an arbitrary program using 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 only the current screen, use @screen or @ansi_screen. For the secondary screen, use +@alternate and @ansi_alternate. For example, the following command opens the scrollback buffer in less in a new window:: map kitty_mod+y new_window @ansi less +G -R diff --git a/kitty/screen.c b/kitty/screen.c index 0000f5e36..82e12f9f9 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -1684,6 +1684,21 @@ as_text_non_visual(Screen *self, PyObject *args) { as_text_generic(args, self, range_line_, self->lines, self->columns); } +static inline PyObject* +as_text_generic_wrapper(Screen *self, PyObject *args, Line*(get_line)(Screen *, int)) { + as_text_generic(args, self, get_line, self->lines, self->columns); +} + +static PyObject* +as_text_alternate(Screen *self, PyObject *args) { + LineBuf *original = self->linebuf; + self->linebuf = original == self->main_linebuf ? self->alt_linebuf : self->main_linebuf; + PyObject *ans = as_text_generic_wrapper(self, args, range_line_); + self->linebuf = original; + return ans; +} + + static PyObject* screen_wcswidth(PyObject UNUSED *self, PyObject *str) { if (PyUnicode_READY(str) != 0) return NULL; @@ -2169,6 +2184,7 @@ static PyMethodDef methods[] = { MND(set_pending_timeout, METH_O) MND(as_text, METH_VARARGS) MND(as_text_non_visual, METH_VARARGS) + MND(as_text_alternate, METH_VARARGS) MND(tab, METH_NOARGS) MND(backspace, METH_NOARGS) MND(linefeed, METH_NOARGS) diff --git a/kitty/window.py b/kitty/window.py index befccba51..92d2181d7 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -436,10 +436,13 @@ class Window: self.screen.reset_callbacks() self.screen = None - def as_text(self, as_ansi=False, add_history=False, add_wrap_markers=False): + def as_text(self, as_ansi=False, add_history=False, add_wrap_markers=False, alternate_screen=False): lines = [] - add_history = add_history and not self.screen.is_using_alternate_linebuf() - f = self.screen.as_text_non_visual if add_history else self.screen.as_text + add_history = add_history and not self.screen.is_using_alternate_linebuf() and not alternate_screen + if alternate_screen: + f = self.screen.as_text_alternate + else: + f = self.screen.as_text_non_visual if add_history else self.screen.as_text f(lines.append, as_ansi, add_wrap_markers) if add_history: h = []