As part of GTK3 fixup, some backported improvements to the DBus

interface, and remotinator (Steve Boddy)
* Can now open a window or tab using remotinator
* Can get the window uuid, or title using remotinator
* Moved new tab key handling into the terminal for consistency
* Standardise response when a new term is created (split, win
  or tab) to reply with new terms uuid
* For GTK3 gave the DBus a slightly different name so they it
  can run at same time as GTK2
* remotinator now uses argparse for commandline option handling,
  vastly improving the option handling
* remotinator help strings are translatable now
This commit is contained in:
Stephen Boddy 2015-09-19 05:21:36 +02:00
parent a31b5136e8
commit 286231e4b9
6 changed files with 156 additions and 58 deletions

View File

@ -1,10 +1,24 @@
terminator trunk: terminator trunk:
* Features * Features
* Enhancements * Enhancements
* As part of GTK3 fixup, some backported improvements to the DBus
interface, and remotinator (Steve Boddy)
* Can now open a window or tab using remotinator
* Can get the window uuid, or title using remotinator
* Moved new tab key handling into the terminal for consistency
* Standardise response when a new term is created (split, win
or tab) to reply with new terms uuid
* For GTK3 gave the DBus a slightly different name so they it
can run at same time as GTK2
* remotinator now uses argparse for commandline option handling,
vastly improving the option handling
* remotinator help strings are translatable now
* Bug fixes * Bug fixes
* Fix for those not running IBus, where the IBus workaround caused * Fix for those not running IBus, where the IBus workaround caused
broken keys in other keymaps set with non-IBus tools (Steve broken keys in other keymaps set with non-IBus tools (Steve
Boddy, LP#1494606) Boddy, LP#1494606)
* Fix custom commands to use the standard gerr function instead
of the broken local one (Steve Boddy)
terminator 0.98: terminator 0.98:
* Features * Features

View File

@ -20,6 +20,7 @@
import os import os
import sys import sys
import argparse
from terminatorlib.util import dbg, err from terminatorlib.util import dbg, err
try: try:
@ -27,40 +28,60 @@ try:
except ImportError: except ImportError:
err('Unable to initialise Terminator remote library. This probably means dbus is not available') err('Unable to initialise Terminator remote library. This probably means dbus is not available')
sys.exit(1) sys.exit(1)
from terminatorlib.translation import _
APP_NAME='remotinator' APP_NAME='remotinator'
APP_VERSION='0.98' APP_VERSION='0.98'
COMMANDS={ COMMANDS={
'hsplit': ['terminal_hsplit', 'Split the current terminal horizontally'], # Command uuid req. Description
'vsplit': ['terminal_vsplit', 'Split the current terminal vertically'], 'new_window': [False, _('Open a new window')],
'terminals': ['get_terminals', 'Get a list of all terminals'], 'new_tab': [True, _('Open a new tab')],
'terminal_tab': ['get_terminal_tab', 'Get the UUID of a parent tab'], 'hsplit': [True, _('Split the current terminal horizontally')],
'terminal_tab_title': ['get_terminal_tab_title', 'Get the title of a parent tab'], 'vsplit': [True, _('Split the current terminal vertically')],
} 'get_terminals': [False, _('Get a list of all terminals')],
'get_window': [True, _('Get the UUID of a parent window')],
'get_window_title': [True, _('Get the title of a parent window')],
'get_tab': [True, _('Get the UUID of a parent tab')],
'get_tab_title': [True, _('Get the title of a parent tab')],
}
if __name__ == '__main__': if __name__ == '__main__':
dbg ("%s starting up, version %s" % (APP_NAME, APP_VERSION)) dbg ("%s starting up, version %s" % (APP_NAME, APP_VERSION))
if sys.argv[0].split('/')[-1] == APP_NAME: command_desc=''
if len(sys.argv) <2 or sys.argv[1] in ['-h', '--help']: for command in sorted(COMMANDS.keys()):
print "Usage: %s COMMAND" % sys.argv[0] command_desc += " %-*s %s %s\n" % (max([len(x) for x in COMMANDS.keys()]),
print " Commands:" command,
for command in COMMANDS: COMMANDS[command][0] and '*' or ' ',
print " %s : %s" % (command, COMMANDS[command][1]) COMMANDS[command][1])
# Parse args
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
usage='%(prog)s command [options]',
description=_('Run one of the following Terminator DBus commands:\n\n%s') % (command_desc),
epilog=_('* These entries require either TERMINATOR_UUID environment var,\n or the --uuid option must be used.'))
parser.add_argument('-u', '--uuid', dest='uuid', type=str, metavar='UUID', default=argparse.SUPPRESS,
help=_('Terminal UUID for when not in env var TERMINATOR_UUID'))
parser.add_argument('command', type=str, nargs=1, choices=sorted(COMMANDS.keys()),
help=argparse.SUPPRESS)
parser.add_argument('-v', '--version', action='version', version='%%(prog)s %s' %(APP_VERSION))
options = vars(parser.parse_args()) # Straight to dict
# Pull out the command
command = options['command'][0]
del options['command']
func = getattr(ipc, command)
uuid_required = COMMANDS[command][0]
if uuid_required:
uuid = options.get('uuid', os.environ.get('TERMINATOR_UUID'))
if uuid:
func(uuid, options)
else:
err("$TERMINATOR_UUID is not set, or passed as an option.")
sys.exit(1) sys.exit(1)
command = sys.argv[1]
else: else:
command = sys.argv[0].split('/')[-1] func(options)
if not command in COMMANDS or not hasattr(ipc, COMMANDS[command][0]):
err("Unknown command: %s" % command)
sys.exit(1)
if not os.environ.has_key('TERMINATOR_UUID'):
err("$TERMINATOR_UUID is not set. Are you definitely running inside Terminator?")
sys.exit(1)
func = getattr(ipc, COMMANDS[command][0])
func(os.environ['TERMINATOR_UUID'])

View File

@ -103,10 +103,10 @@ if __name__ == '__main__':
optionslist = dbus.Dictionary(optionslist, signature='ss') optionslist = dbus.Dictionary(optionslist, signature='ss')
if OPTIONS.new_tab: if OPTIONS.new_tab:
dbg('Requesting a new tab') dbg('Requesting a new tab')
ipc.new_tab(optionslist) ipc.new_tab_cmdline(optionslist)
else: else:
dbg('Requesting a new window') dbg('Requesting a new window')
ipc.new_window(optionslist) ipc.new_window_cmdline(optionslist)
sys.exit() sys.exit()
except ImportError: except ImportError:
dbg('dbus not imported') dbg('dbus not imported')

View File

@ -60,7 +60,7 @@ class DBusService(Borg, dbus.service.Object):
self.terminator = Terminator() self.terminator = Terminator()
@dbus.service.method(BUS_NAME, in_signature='a{ss}') @dbus.service.method(BUS_NAME, in_signature='a{ss}')
def new_window(self, options=dbus.Dictionary()): def new_window_cmdline(self, options=dbus.Dictionary()):
"""Create a new Window""" """Create a new Window"""
dbg('dbus method called: new_window with parameters %s'%(options)) dbg('dbus method called: new_window with parameters %s'%(options))
oldopts = self.terminator.config.options_get() oldopts = self.terminator.config.options_get()
@ -70,7 +70,7 @@ class DBusService(Borg, dbus.service.Object):
self.terminator.layout_done() self.terminator.layout_done()
@dbus.service.method(BUS_NAME, in_signature='a{ss}') @dbus.service.method(BUS_NAME, in_signature='a{ss}')
def new_tab(self, options=dbus.Dictionary()): def new_tab_cmdline(self, options=dbus.Dictionary()):
"""Create a new tab""" """Create a new tab"""
dbg('dbus method called: new_tab with parameters %s'%(options)) dbg('dbus method called: new_tab with parameters %s'%(options))
oldopts = self.terminator.config.options_get() oldopts = self.terminator.config.options_get()
@ -80,33 +80,76 @@ class DBusService(Borg, dbus.service.Object):
window.tab_new() window.tab_new()
@dbus.service.method(BUS_NAME) @dbus.service.method(BUS_NAME)
def terminal_hsplit(self, uuid=None): def new_window(self):
"""Split a terminal horizontally, by UUID""" """Create a new Window"""
return self.terminal_split(uuid, True) terminals_before = set(self.get_terminals())
self.terminator.new_window()
terminals_after = set(self.get_terminals())
new_terminal_set = list(terminals_after - terminals_before)
if len(new_terminal_set) != 1:
"ERROR: Cannot determine the UUID of the added terminal"
else:
return new_terminal_set[0]
@dbus.service.method(BUS_NAME) @dbus.service.method(BUS_NAME)
def terminal_vsplit(self, uuid=None): def new_tab(self, uuid=None):
"""Split a terminal vertically, by UUID""" """Create a new tab"""
return self.terminal_split(uuid, False) return self.new_terminal(uuid, 'tab')
def terminal_split(self, uuid, horiz): @dbus.service.method(BUS_NAME)
def hsplit(self, uuid=None):
"""Split a terminal horizontally, by UUID"""
return self.new_terminal(uuid, 'hsplit')
@dbus.service.method(BUS_NAME)
def vsplit(self, uuid=None):
"""Split a terminal vertically, by UUID"""
return self.new_terminal(uuid, 'vsplit')
def new_terminal(self, uuid, type):
"""Split a terminal horizontally or vertically, by UUID""" """Split a terminal horizontally or vertically, by UUID"""
dbg('dbus method called: terminal_hsplit') dbg('dbus method called: %s' % type)
if not uuid: if not uuid:
return "ERROR: No UUID specified" return "ERROR: No UUID specified"
terminal = self.terminator.find_terminal_by_uuid(uuid) terminal = self.terminator.find_terminal_by_uuid(uuid)
terminals_before = set(self.get_terminals())
if not terminal: if not terminal:
return "ERROR: Terminal with supplied UUID not found" return "ERROR: Terminal with supplied UUID not found"
if horiz: elif type == 'tab':
terminal.key_new_tab()
elif type == 'hsplit':
terminal.key_split_horiz() terminal.key_split_horiz()
else: elif type == 'vsplit':
terminal.key_split_vert() terminal.key_split_vert()
else:
return "ERROR: Unknown type \"%s\" specified" % (type)
terminals_after = set(self.get_terminals())
# Detect the new terminal UUID
new_terminal_set = list(terminals_after - terminals_before)
if len(new_terminal_set) != 1:
return "ERROR: Cannot determine the UUID of the added terminal"
else:
return new_terminal_set[0]
@dbus.service.method(BUS_NAME) @dbus.service.method(BUS_NAME)
def get_terminals(self, uuid): def get_terminals(self):
"""Return a list of all the terminals""" """Return a list of all the terminals"""
return [x.uuid.urn for x in self.terminator.terminals] return [x.uuid.urn for x in self.terminator.terminals]
@dbus.service.method(BUS_NAME)
def get_window(self, uuid=None):
"""Return the UUID of the parent window of a given terminal"""
terminal = self.terminator.find_terminal_by_uuid(uuid)
window = terminal.get_toplevel()
return window.uuid.urn
@dbus.service.method(BUS_NAME)
def get_window_title(self, uuid=None):
"""Return the title of a parent window of a given terminal"""
terminal = self.terminator.find_terminal_by_uuid(uuid)
window = terminal.get_toplevel()
return window.get_title()
@dbus.service.method(BUS_NAME) @dbus.service.method(BUS_NAME)
def get_terminal_tab(self, uuid): def get_terminal_tab(self, uuid):
"""Return the UUID of the parent tab of a given terminal""" """Return the UUID of the parent tab of a given terminal"""
@ -136,38 +179,58 @@ def with_proxy(func):
func(proxy, *args, **argd) func(proxy, *args, **argd)
return _exec return _exec
@with_proxy
def new_window_cmdline(session, options):
"""Call the dbus method to open a new window"""
session.new_window_cmdline(options)
@with_proxy
def new_tab_cmdline(session, options):
"""Call the dbus method to open a new tab in the first window"""
session.new_tab_cmdline(options)
@with_proxy @with_proxy
def new_window(session, options): def new_window(session, options):
"""Call the dbus method to open a new window""" """Call the dbus method to open a new window"""
session.new_window(options) print session.new_window()
@with_proxy @with_proxy
def new_tab(session, options): def new_tab(session, uuid, options):
"""Call the dbus method to open a new tab in the first window""" """Call the dbus method to open a new tab in the first window"""
session.new_tab(options) print session.new_tab(uuid)
@with_proxy @with_proxy
def terminal_hsplit(session, uuid): def hsplit(session, uuid, options):
"""Call the dbus method to horizontally split a terminal""" """Call the dbus method to horizontally split a terminal"""
session.terminal_hsplit(uuid) print session.hsplit(uuid)
@with_proxy @with_proxy
def terminal_vsplit(session, uuid): def vsplit(session, uuid, options):
"""Call the dbus method to vertically split a terminal""" """Call the dbus method to vertically split a terminal"""
print session.terminal_vsplit(uuid) print session.vsplit(uuid)
@with_proxy @with_proxy
def get_terminals(session, uuid): def get_terminals(session, options):
"""Call the dbus method to return a list of all terminals""" """Call the dbus method to return a list of all terminals"""
print '\n'.join(session.get_terminals(uuid)) print '\n'.join(session.get_terminals())
@with_proxy @with_proxy
def get_terminal_tab(session, uuid): def get_window(session, uuid, options):
"""Call the dbus method to return the toplevel tab for a terminal""" """Call the dbus method to return the toplevel tab for a terminal"""
print session.get_terminal_tab(uuid) print session.get_window(uuid)
@with_proxy @with_proxy
def get_terminal_tab_title(session, uuid): def get_window_title(session, uuid, options):
"""Call the dbus method to return the title of a tab""" """Call the dbus method to return the title of a tab"""
print session.get_terminal_tab_title(uuid) print session.get_window_title(uuid)
@with_proxy
def get_tab(session, uuid, options):
"""Call the dbus method to return the toplevel tab for a terminal"""
print session.get_tab(uuid)
@with_proxy
def get_tab_title(session, uuid, options):
"""Call the dbus method to return the title of a tab"""
print session.get_tab_title(uuid)

View File

@ -859,8 +859,7 @@ class Terminal(gtk.VBox):
return(False) return(False)
if mapping and mapping not in ['close_window', if mapping and mapping not in ['close_window',
'full_screen', 'full_screen']:
'new_tab']:
dbg('Terminal::on_keypress: lookup found: %r' % mapping) dbg('Terminal::on_keypress: lookup found: %r' % mapping)
# handle the case where user has re-bound copy to ctrl+<key> # handle the case where user has re-bound copy to ctrl+<key>
# we only copy if there is a selection otherwise let it fall through # we only copy if there is a selection otherwise let it fall through
@ -1769,6 +1768,9 @@ class Terminal(gtk.VBox):
def key_new_window(self): def key_new_window(self):
self.terminator.new_window(self.terminator.pid_cwd(self.pid)) self.terminator.new_window(self.terminator.pid_cwd(self.pid))
def key_new_tab(self):
self.get_toplevel().tab_new(self)
def key_new_terminator(self): def key_new_terminator(self):
spawn_new_terminator(self.origcwd, ['-u']) spawn_new_terminator(self.origcwd, ['-u'])

View File

@ -208,8 +208,6 @@ class Window(Container, gtk.Window):
gtk.gdk.Event(gtk.gdk.DELETE)): gtk.gdk.Event(gtk.gdk.DELETE)):
self.on_destroy_event(window, self.on_destroy_event(window,
gtk.gdk.Event(gtk.gdk.DESTROY)) gtk.gdk.Event(gtk.gdk.DESTROY))
elif mapping == 'new_tab':
self.tab_new(self.get_focussed_terminal())
else: else:
return(False) return(False)
return(True) return(True)