Implement @get-text
This commit is contained in:
parent
6ad49bd7fb
commit
e5b9bd2e5a
@ -383,7 +383,15 @@ as_ansi(LineBuf *self, PyObject *callback) {
|
|||||||
#define as_ansi_doc "as_ansi(callback) -> The contents of this buffer as ANSI escaped text. callback is called with each successive line."
|
#define as_ansi_doc "as_ansi(callback) -> The contents of this buffer as ANSI escaped text. callback is called with each successive line."
|
||||||
static Py_UCS4 t[5120];
|
static Py_UCS4 t[5120];
|
||||||
Line l = {.xnum=self->xnum};
|
Line l = {.xnum=self->xnum};
|
||||||
for(index_type i = 0; i < self->ynum; i++) {
|
// remove trailing empty lines
|
||||||
|
index_type ylimit = self->ynum - 1;
|
||||||
|
do {
|
||||||
|
init_line(self, (&l), self->line_map[ylimit]);
|
||||||
|
if (line_as_ansi(&l, t, 5120) != 0) break;
|
||||||
|
ylimit--;
|
||||||
|
} while(ylimit > 0);
|
||||||
|
|
||||||
|
for(index_type i = 0; i <= ylimit; i++) {
|
||||||
l.continued = ((i < self->ynum - 1) ? self->line_attrs[i+1] : self->line_attrs[i]) & CONTINUED_MASK;
|
l.continued = ((i < self->ynum - 1) ? self->line_attrs[i+1] : self->line_attrs[i]) & CONTINUED_MASK;
|
||||||
init_line(self, (&l), self->line_map[i]);
|
init_line(self, (&l), self->line_map[i]);
|
||||||
index_type num = line_as_ansi(&l, t, 5120);
|
index_type num = line_as_ansi(&l, t, 5120);
|
||||||
|
|||||||
@ -244,6 +244,7 @@ line_as_ansi(Line *self, Py_UCS4 *buf, index_type buflen) {
|
|||||||
#define WRITE_CH(val) if (i > buflen - 1) return i; buf[i++] = val;
|
#define WRITE_CH(val) if (i > buflen - 1) return i; buf[i++] = val;
|
||||||
|
|
||||||
index_type limit = xlimit_for_line(self), i=0;
|
index_type limit = xlimit_for_line(self), i=0;
|
||||||
|
if (limit == 0) return 0;
|
||||||
char_type previous_width = 0;
|
char_type previous_width = 0;
|
||||||
|
|
||||||
WRITE_SGR("0");
|
WRITE_SGR("0");
|
||||||
|
|||||||
@ -244,6 +244,49 @@ def new_window(boss, window, payload):
|
|||||||
return str(w.id)
|
return str(w.id)
|
||||||
|
|
||||||
|
|
||||||
|
@cmd(
|
||||||
|
'Get text from the specified window',
|
||||||
|
options_spec=MATCH_WINDOW_OPTION + '''\n
|
||||||
|
--extent
|
||||||
|
default=screen
|
||||||
|
choices=screen, all, selection
|
||||||
|
What text to get. The default of screen means all text currently on the screen. all means
|
||||||
|
all the screen+scrollback and selection means currently selected text.
|
||||||
|
|
||||||
|
|
||||||
|
--ansi
|
||||||
|
type=bool-set
|
||||||
|
By default, only plain text is return. If you specify this flag, the text will
|
||||||
|
include the formatting escape codes for colors/bold/italic/etc. Note that when
|
||||||
|
getting the current selection, the result is always plain text.
|
||||||
|
|
||||||
|
|
||||||
|
--self
|
||||||
|
type=bool-set
|
||||||
|
If specified get text from the window this command is run in, rather than the active window.
|
||||||
|
'''
|
||||||
|
)
|
||||||
|
def cmd_get_text(global_opts, opts, args):
|
||||||
|
return {'match': opts.match, 'extent': opts.extent, 'ansi': opts.ansi, 'self': opts.self}
|
||||||
|
|
||||||
|
|
||||||
|
def get_text(boss, window, payload):
|
||||||
|
match = payload['match']
|
||||||
|
if match:
|
||||||
|
windows = tuple(boss.match_windows(match))
|
||||||
|
if not windows:
|
||||||
|
raise ValueError('No matching windows for expression: {}'.format(match))
|
||||||
|
else:
|
||||||
|
windows = [window if window and payload['self'] else boss.active_window]
|
||||||
|
window = windows[0]
|
||||||
|
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')
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
cmap = {v.name: v for v in globals().values() if hasattr(v, 'is_cmd')}
|
cmap = {v.name: v for v in globals().values() if hasattr(v, 'is_cmd')}
|
||||||
|
|
||||||
|
|
||||||
@ -270,12 +313,15 @@ global_options_spec = partial('''\
|
|||||||
|
|
||||||
def read_from_stdin(send, no_response):
|
def read_from_stdin(send, no_response):
|
||||||
send = ('@kitty-cmd' + json.dumps(send)).encode('ascii')
|
send = ('@kitty-cmd' + json.dumps(send)).encode('ascii')
|
||||||
if not sys.stdout.isatty():
|
out = sys.stdout if sys.stdout.isatty() else sys.stderr
|
||||||
raise SystemExit('stdout is not a terminal')
|
if not out.isatty():
|
||||||
sys.stdout.buffer.write(b'\x1bP' + send + b'\x1b\\')
|
raise SystemExit('Neither stdout nor stderr is a terminal')
|
||||||
sys.stdout.flush()
|
out.buffer.write(b'\x1bP' + send + b'\x1b\\')
|
||||||
|
out.flush()
|
||||||
if no_response:
|
if no_response:
|
||||||
return {'ok': True}
|
return {'ok': True}
|
||||||
|
if not sys.stdin.isatty():
|
||||||
|
raise SystemExit('stdin is not a terminal')
|
||||||
|
|
||||||
received = b''
|
received = b''
|
||||||
dcs = re.compile(br'\x1bP@kitty-cmd([^\x1b]+)\x1b\\')
|
dcs = re.compile(br'\x1bP@kitty-cmd([^\x1b]+)\x1b\\')
|
||||||
|
|||||||
@ -312,14 +312,20 @@ class Window:
|
|||||||
self.screen.reset_callbacks()
|
self.screen.reset_callbacks()
|
||||||
self.screen = None
|
self.screen = None
|
||||||
|
|
||||||
def buffer_as_ansi(self):
|
def buffer_as_ansi(self, add_history=True):
|
||||||
data = []
|
data = []
|
||||||
self.screen.historybuf.as_ansi(data.append)
|
if add_history:
|
||||||
|
self.screen.historybuf.as_ansi(data.append)
|
||||||
self.screen.linebuf.as_ansi(data.append)
|
self.screen.linebuf.as_ansi(data.append)
|
||||||
return ''.join(data)
|
return ''.join(data)
|
||||||
|
|
||||||
def buffer_as_text(self):
|
def buffer_as_text(self, add_history=True):
|
||||||
return str(self.screen.historybuf) + '\n' + str(self.screen.linebuf)
|
ans = str(self.screen.linebuf).rstrip('\n')
|
||||||
|
if add_history:
|
||||||
|
h = str(self.screen.historybuf)
|
||||||
|
if h.strip():
|
||||||
|
ans = h + '\n' + ans
|
||||||
|
return ans
|
||||||
|
|
||||||
# actions {{{
|
# actions {{{
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user