Allow creating shortcuts to run arbitrary programs in new windows/tabs

This commit is contained in:
Kovid Goyal 2017-10-20 17:49:52 +05:30
parent 626847f2f5
commit 9a1b85081e
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 67 additions and 9 deletions

View File

@ -35,3 +35,7 @@ version 0.4.0 [future]
- Allow combining multiple independent actions into a single shortcut
- Add a new shortcut to pass the current selection to an external program
- Allow creating shortcuts to open new windows running arbitrary commands. You
can also pass the current selection to the command as an arguments and the
contents of the screen + scrollback buffer as stdin to the command.

View File

@ -293,8 +293,45 @@ class Boss:
def previous_tab(self):
self.tab_manager.next_tab(-1)
def new_tab(self):
self.tab_manager.new_tab()
def args_to_special_window(self, args):
args = list(args)
stdin = None
w = self.active_window
def data_for_at(arg):
if arg == '@selection':
return w.text_for_selection()
if arg == '@ansi':
return w.buffer_as_ansi()
elif arg == '@text':
return w.buffer_as_text()
if args[0].startswith('@'):
stdin = data_for_at(args[0]).encode('utf-8')
del args[0]
cmd = []
for arg in args:
if arg == '@selection':
arg = data_for_at(arg)
if not arg:
continue
cmd.append(arg)
return SpecialWindow(cmd, stdin)
def new_tab(self, *args):
special_window = None
if args:
special_window = self.args_to_special_window(args)
self.tab_manager.new_tab(special_window=special_window)
def new_window(self, *args):
tab = self.active_tab
if tab is not None:
if args:
tab.new_special_window(self.args_to_special_window(args))
else:
tab.new_window()
def move_tab_forward(self):
self.tab_manager.move_tab(1)

View File

@ -94,7 +94,7 @@ def parse_shortcut(sc):
KeyAction = namedtuple('KeyAction', 'func args')
shlex_actions = {'pass_selection_to_program'}
shlex_actions = {'pass_selection_to_program', 'new_window', 'new_tab'}
def parse_key_action(action):

View File

@ -236,7 +236,7 @@ map ctrl+shift+end scroll_end
map ctrl+shift+h show_scrollback
# Window management
map ctrl+shift+enter new_window
map ctrl+shift+enter new_window
map ctrl+shift+w close_window
map ctrl+shift+] next_window
map ctrl+shift+[ previous_window
@ -253,6 +253,15 @@ map ctrl+shift+7 seventh_window
map ctrl+shift+8 eighth_window
map ctrl+shift+9 ninth_window
map ctrl+shift+0 tenth_window
# You can also open a new window running an arbitrary program, for example:
# map ctrl+shift+y new_window mutt
# You can also pass the current selection to the new program by using the @selection placeholder
# map ctrl+shift+y new_window less @selection
# Finally, 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)
# 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
# Tab management
map ctrl+shift+right next_tab
@ -262,6 +271,9 @@ map ctrl+shift+q close_tab
map ctrl+shift+l next_layout
map ctrl+shift+. move_tab_forward
map ctrl+shift+, move_tab_backward
# Just as with new_window above, you can also pass the name of arbitrary
# commands to run when using new_tab.
# Miscellaneous
map ctrl+shift+equal increase_font_size

View File

@ -234,14 +234,19 @@ class Window:
remove_vao(self.gvao_id)
self.vao_id = self.gvao_id = None
# actions {{{
def show_scrollback(self):
def buffer_as_ansi(self):
data = []
self.screen.historybuf.as_ansi(data.append)
self.screen.linebuf.as_ansi(data.append)
data = ''.join(data).encode('utf-8')
get_boss().display_scrollback(data)
return ''.join(data)
def buffer_as_text(self):
return str(self.screen.historybuf) + '\n' + str(self.screen.linebuf)
# actions {{{
def show_scrollback(self):
get_boss().display_scrollback(self.buffer_as_ansi().encode('utf-8'))
def paste(self, text):
if text and not self.destroyed: