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:
* Features
* 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
* Fix for those not running IBus, where the IBus workaround caused
broken keys in other keymaps set with non-IBus tools (Steve
Boddy, LP#1494606)
* Fix custom commands to use the standard gerr function instead
of the broken local one (Steve Boddy)
terminator 0.98:
* Features

View File

@ -20,6 +20,7 @@
import os
import sys
import argparse
from terminatorlib.util import dbg, err
try:
@ -27,40 +28,60 @@ try:
except ImportError:
err('Unable to initialise Terminator remote library. This probably means dbus is not available')
sys.exit(1)
from terminatorlib.translation import _
APP_NAME='remotinator'
APP_VERSION='0.98'
COMMANDS={
'hsplit': ['terminal_hsplit', 'Split the current terminal horizontally'],
'vsplit': ['terminal_vsplit', 'Split the current terminal vertically'],
'terminals': ['get_terminals', 'Get a list of all terminals'],
'terminal_tab': ['get_terminal_tab', 'Get the UUID of a parent tab'],
'terminal_tab_title': ['get_terminal_tab_title', 'Get the title of a parent tab'],
}
# Command uuid req. Description
'new_window': [False, _('Open a new window')],
'new_tab': [True, _('Open a new tab')],
'hsplit': [True, _('Split the current terminal horizontally')],
'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__':
dbg ("%s starting up, version %s" % (APP_NAME, APP_VERSION))
if sys.argv[0].split('/')[-1] == APP_NAME:
if len(sys.argv) <2 or sys.argv[1] in ['-h', '--help']:
print "Usage: %s COMMAND" % sys.argv[0]
print " Commands:"
for command in COMMANDS:
print " %s : %s" % (command, COMMANDS[command][1])
command_desc=''
for command in sorted(COMMANDS.keys()):
command_desc += " %-*s %s %s\n" % (max([len(x) for x in COMMANDS.keys()]),
command,
COMMANDS[command][0] and '*' or ' ',
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)
command = sys.argv[1]
else:
command = sys.argv[0].split('/')[-1]
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'])
func(options)

View File

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

View File

@ -60,7 +60,7 @@ class DBusService(Borg, dbus.service.Object):
self.terminator = Terminator()
@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"""
dbg('dbus method called: new_window with parameters %s'%(options))
oldopts = self.terminator.config.options_get()
@ -70,7 +70,7 @@ class DBusService(Borg, dbus.service.Object):
self.terminator.layout_done()
@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"""
dbg('dbus method called: new_tab with parameters %s'%(options))
oldopts = self.terminator.config.options_get()
@ -80,33 +80,76 @@ class DBusService(Borg, dbus.service.Object):
window.tab_new()
@dbus.service.method(BUS_NAME)
def terminal_hsplit(self, uuid=None):
"""Split a terminal horizontally, by UUID"""
return self.terminal_split(uuid, True)
def new_window(self):
"""Create a new Window"""
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)
def terminal_vsplit(self, uuid=None):
"""Split a terminal vertically, by UUID"""
return self.terminal_split(uuid, False)
def new_tab(self, uuid=None):
"""Create a new tab"""
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"""
dbg('dbus method called: terminal_hsplit')
dbg('dbus method called: %s' % type)
if not uuid:
return "ERROR: No UUID specified"
terminal = self.terminator.find_terminal_by_uuid(uuid)
terminals_before = set(self.get_terminals())
if not terminal:
return "ERROR: Terminal with supplied UUID not found"
if horiz:
elif type == 'tab':
terminal.key_new_tab()
elif type == 'hsplit':
terminal.key_split_horiz()
else:
elif type == 'vsplit':
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)
def get_terminals(self, uuid):
def get_terminals(self):
"""Return a list of all the 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)
def get_terminal_tab(self, uuid):
"""Return the UUID of the parent tab of a given terminal"""
@ -136,38 +179,58 @@ def with_proxy(func):
func(proxy, *args, **argd)
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
def new_window(session, options):
"""Call the dbus method to open a new window"""
session.new_window(options)
print session.new_window()
@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"""
session.new_tab(options)
print session.new_tab(uuid)
@with_proxy
def terminal_hsplit(session, uuid):
def hsplit(session, uuid, options):
"""Call the dbus method to horizontally split a terminal"""
session.terminal_hsplit(uuid)
print session.hsplit(uuid)
@with_proxy
def terminal_vsplit(session, uuid):
def vsplit(session, uuid, options):
"""Call the dbus method to vertically split a terminal"""
print session.terminal_vsplit(uuid)
print session.vsplit(uuid)
@with_proxy
def get_terminals(session, uuid):
def get_terminals(session, options):
"""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
def get_terminal_tab(session, uuid):
def get_window(session, uuid, options):
"""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
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"""
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)
if mapping and mapping not in ['close_window',
'full_screen',
'new_tab']:
'full_screen']:
dbg('Terminal::on_keypress: lookup found: %r' % mapping)
# 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
@ -1769,6 +1768,9 @@ class Terminal(gtk.VBox):
def key_new_window(self):
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):
spawn_new_terminator(self.origcwd, ['-u'])

View File

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