A new pipe function that can be used to pipe the contents of the screen and scrollback buffer to any desired program running in a new window, tab or overlay window.

This commit is contained in:
Kovid Goyal 2018-09-09 18:29:29 +05:30
parent e5a7ba4f22
commit b9b38a4ec1
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 88 additions and 26 deletions

View File

@ -6,13 +6,17 @@ Changelog
0.12.2 [future] 0.12.2 [future]
------------------------------ ------------------------------
- Add a new ``last_used_layout`` function that can be mapped to a shortcut to - A new ``last_used_layout`` function that can be mapped to a shortcut to
switch to the previously used window layout (:iss:`870`) switch to the previously used window layout (:iss:`870`)
- Add new ``neighboring_window`` and ``move_window`` functions to switch to - New ``neighboring_window`` and ``move_window`` functions to switch to
neighboring windows in the current layout, and move them around, similar to neighboring windows in the current layout, and move them around, similar to
window movement in vim (:iss:`916`) window movement in vim (:iss:`916`)
- A new ``pipe`` function that can be used to pipe the contents of the screen
and scrollback buffer to any desired program running in a new window, tab or
overlay window. (:iss:`933`)
- Add a new :option:`kitty --start-as` command line flag to start kitty - Add a new :option:`kitty --start-as` command line flag to start kitty
fullscreen/maximized/minimized. This replaces the ``--start-in-fullscreen`` fullscreen/maximized/minimized. This replaces the ``--start-in-fullscreen``
flag introduced in the previous release (:iss:`935`) flag introduced in the previous release (:iss:`935`)

View File

@ -48,6 +48,23 @@ def listen_on(spec):
return s.fileno() return s.fileno()
def data_for_at(w, arg):
if arg == '@selection':
return w.text_for_selection()
if arg == '@ansi':
return w.as_text(as_ansi=True, add_history=True)
if arg == '@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 arg == '@alternate':
return w.as_text(alternate_screen=True)
if arg == '@ansi_alternate':
return w.as_text(as_ansi=True, alternate_screen=True)
class DumpCommands: # {{{ class DumpCommands: # {{{
def __init__(self, args): def __init__(self, args):
@ -774,29 +791,50 @@ class Boss:
if tm is not None: if tm is not None:
tm.next_tab(-1) tm.next_tab(-1)
def special_window_for_cmd(self, cmd, window=None, stdin=None, cwd_from=None, as_overlay=False):
w = window or self.active_window
if stdin:
stdin = data_for_at(w, stdin)
if stdin is not None:
stdin = stdin.encode('utf-8')
cmdline = []
for arg in cmd:
if arg == '@selection':
arg = data_for_at(w, arg)
if not arg:
continue
cmdline.append(arg)
overlay_for = w.id if as_overlay and w.overlay_for is None else None
return SpecialWindow(cmd, stdin, cwd_from=cwd_from, overlay_for=overlay_for)
def pipe(self, source, dest, exe, *args):
cmd = [exe] + list(args)
window = self.active_window
cwd_from = window.child.pid if window else None
def create_window():
return self.special_window_for_cmd(
cmd, stdin=source, as_overlay=dest == 'overlay', cwd_from=cwd_from)
if dest == 'overlay' or dest == 'window':
tab = self.active_tab
if tab is not None:
return tab.new_special_window(create_window())
elif dest == 'tab':
tm = self.active_tab_manager
if tm is not None:
tm.new_tab(special_window=create_window(), cwd_from=cwd_from)
else:
import subprocess
subprocess.Popen(cmd)
def args_to_special_window(self, args, cwd_from=None): def args_to_special_window(self, args, cwd_from=None):
args = list(args) args = list(args)
stdin = None stdin = None
w = self.active_window w = self.active_window
def data_for_at(arg):
if arg == '@selection':
return w.text_for_selection()
if arg == '@ansi':
return w.as_text(as_ansi=True, add_history=True)
if arg == '@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 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] != '@': if args[0].startswith('@') and args[0] != '@':
stdin = data_for_at(args[0]) or None stdin = data_for_at(w, args[0]) or None
if stdin is not None: if stdin is not None:
stdin = stdin.encode('utf-8') stdin = stdin.encode('utf-8')
del args[0] del args[0]
@ -804,7 +842,7 @@ class Boss:
cmd = [] cmd = []
for arg in args: for arg in args:
if arg == '@selection': if arg == '@selection':
arg = data_for_at(arg) arg = data_for_at(w, arg)
if not arg: if not arg:
continue continue
cmd.append(arg) cmd.append(arg)

View File

@ -163,6 +163,16 @@ def move_window(func, rest):
return func, [rest] return func, [rest]
@func_with_args('pipe')
def pipe(func, rest):
import shlex
rest = shlex.split(rest)
if len(rest) < 3:
log_error('Too few arguments to pipe function')
rest = ['none', 'none', 'true']
return func, rest
def parse_key_action(action): def parse_key_action(action):
parts = action.split(' ', 1) parts = action.split(' ', 1)
func = parts[0] func = parts[0]

View File

@ -825,13 +825,23 @@ k('scroll_page_down', 'kitty_mod+page_down', 'scroll_page_down', _('Scroll page
k('scroll_home', 'kitty_mod+home', 'scroll_home', _('Scroll to top')) k('scroll_home', 'kitty_mod+home', 'scroll_home', _('Scroll to top'))
k('scroll_end', 'kitty_mod+end', 'scroll_end', _('Scroll to bottom')) 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=_(''' 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 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 You can pipe the contents of the current screen + history buffer as
:file:`STDIN` to an arbitrary program using the ``pipe`` function. For example,
the following opens the scrollback buffer in less in an overlay window::
map f1 pipe @ansi overlay less +g -R
Placeholders available are: @text (which is plain text) and @ansi (which
includes text styling escape codes). For only the current screen, use @screen
or @ansi_screen. For the secondary screen, use @alternate and @ansi_alternate.
Note that the secondary screen is not currently displayed. For example if you
run a fullscreen terminal application, the secondary screen will be the screen
you return to when quitting the application.
To open in a new window or tab use ``window`` or ``tab`` respectively. You can
also use ``none`` in which case the data will be piped into the program without
creating any windows.
''')) '''))