diff --git a/layout-files-examples/2-3-grid.json b/layout-files-examples/2-3-grid.json index 5266aa36..5d6c9d21 100644 --- a/layout-files-examples/2-3-grid.json +++ b/layout-files-examples/2-3-grid.json @@ -1,30 +1,36 @@ { - "tab1": [ - { - "children": [ - { - "command": "bash" - }, - { - "command": "bash" - }, - { - "command": "bash" - } - ] - }, - { - "children": [ - { - "command": "bash" - }, - { - "command": "bash" - }, - { - "command": "bash" - } - ] - } - ] + "layout": { + "tab1": [ + { + "children": [ + { + "command": "bash" + }, + { + "command": "bash" + }, + { + "command": "bash" + } + ] + }, + { + "children": [ + { + "command": "bash" + }, + { + "command": "bash" + }, + { + "command": "bash" + } + ] + } + ] + }, + "profile": { + "background_color": "#170717", + "foreground_color": "#f5c0b7" + } } diff --git a/layout-files-examples/2-columns.json b/layout-files-examples/2-columns.json index 8030d45a..1524f19e 100644 --- a/layout-files-examples/2-columns.json +++ b/layout-files-examples/2-columns.json @@ -1,11 +1,13 @@ { - "vertical": false, - "tab1": [ - { - "command": "bash" - }, - { - "command": "bash" - } - ] + "layout": { + "vertical": false, + "tab1": [ + { + "command": "bash" + }, + { + "command": "bash" + } + ] + } } diff --git a/layout-files-examples/3-rows.json b/layout-files-examples/3-rows.json index 560857ab..aaf4fd91 100644 --- a/layout-files-examples/3-rows.json +++ b/layout-files-examples/3-rows.json @@ -1,13 +1,15 @@ { - "tab1": [ - { - "command": "bash" - }, - { - "command": "bash" - }, - { - "command": "bash" - } - ] + "layout": { + "tab1": [ + { + "command": "bash" + }, + { + "command": "bash" + }, + { + "command": "bash" + } + ] + } } diff --git a/layout-files-examples/3-tabs-2-rows.json b/layout-files-examples/3-tabs-2-rows.json index 0dc7f9bd..e0d2d2c8 100644 --- a/layout-files-examples/3-tabs-2-rows.json +++ b/layout-files-examples/3-tabs-2-rows.json @@ -1,26 +1,28 @@ { - "tab1": [ - { - "command": "bash" - }, - { - "command": "bash" - } - ], - "tab2": [ - { - "command": "bash" - }, - { - "command": "bash" - } - ], - "tab3": [ - { - "command": "bash" - }, - { - "command": "bash" - } - ] + "layout": { + "tab1": [ + { + "command": "bash" + }, + { + "command": "bash" + } + ], + "tab2": [ + { + "command": "bash" + }, + { + "command": "bash" + } + ], + "tab3": [ + { + "command": "bash" + }, + { + "command": "bash" + } + ] + } } diff --git a/layout-files-examples/3-tabs-3-columns.json b/layout-files-examples/3-tabs-3-columns.json index ae9e103c..86792074 100644 --- a/layout-files-examples/3-tabs-3-columns.json +++ b/layout-files-examples/3-tabs-3-columns.json @@ -1,36 +1,38 @@ { - "vertical": false, - "tab1": [ - { - "command": "bash" - }, - { - "command": "bash" - }, - { - "command": "bash" - } - ], - "tab2": [ - { - "command": "bash" - }, - { - "command": "bash" - }, - { - "command": "bash" - } - ], - "tab3": [ - { - "command": "bash" - }, - { - "command": "bash" - }, - { - "command": "bash" - } - ] + "layout": { + "vertical": false, + "tab1": [ + { + "command": "bash" + }, + { + "command": "bash" + }, + { + "command": "bash" + } + ], + "tab2": [ + { + "command": "bash" + }, + { + "command": "bash" + }, + { + "command": "bash" + } + ], + "tab3": [ + { + "command": "bash" + }, + { + "command": "bash" + }, + { + "command": "bash" + } + ] + } } diff --git a/layout-files-examples/4-4-grid.json b/layout-files-examples/4-4-grid.json index 5266aa36..789c0810 100644 --- a/layout-files-examples/4-4-grid.json +++ b/layout-files-examples/4-4-grid.json @@ -1,30 +1,75 @@ { - "tab1": [ - { - "children": [ - { - "command": "bash" - }, - { - "command": "bash" - }, - { - "command": "bash" - } - ] - }, - { - "children": [ - { - "command": "bash" - }, - { - "command": "bash" - }, - { - "command": "bash" - } - ] - } - ] + "layout": { + "tab1": [ + { + "children": [ + { + "command": "bash" + }, + { + "command": "bash" + }, + { + "command": "bash" + }, + { + "command": "bash" + } + ] + }, + { + "children": [ + { + "command": "bash" + }, + { + "command": "bash" + }, + { + "command": "bash" + }, + { + "command": "bash" + } + ] + }, + { + "children": [ + { + "command": "bash" + }, + { + "command": "bash" + }, + { + "command": "bash" + }, + { + "command": "bash" + } + ] + }, + { + "children": [ + { + "command": "bash" + }, + { + "command": "bash" + }, + { + "command": "bash" + }, + { + "command": "bash" + } + ] + } + ] + }, + "profile": { + "background_color": "#070717", + "foreground_color": "#f5c0b7", + "font": "Monospace 16" + } } diff --git a/terminator b/terminator index 9727a9ed..89e6b5c9 100755 --- a/terminator +++ b/terminator @@ -51,6 +51,7 @@ from terminatorlib.factory import Factory from terminatorlib.version import APP_NAME, APP_VERSION from terminatorlib.util import dbg, err from terminatorlib.layoutlauncher import LayoutLauncher +from terminatorlib.configjson import ConfigJson if __name__ == '__main__': # Workaround for IBus intefering with broadcast when using dead keys @@ -68,6 +69,11 @@ if __name__ == '__main__': OPTIONS,dbus_options = terminatorlib.optionparse.parse_options() + if OPTIONS.configjson: + layoutname = ConfigJson().extend_config(OPTIONS.configjson) + if layoutname and ((not OPTIONS.layout) or OPTIONS.layout == 'default'): + OPTIONS.layout = layoutname + TERMINATOR = Terminator() TERMINATOR.set_origcwd(ORIGCWD) diff --git a/terminatorlib/layoutfile.py b/terminatorlib/configjson.py similarity index 67% rename from terminatorlib/layoutfile.py rename to terminatorlib/configjson.py index add0b529..fe92434f 100644 --- a/terminatorlib/layoutfile.py +++ b/terminatorlib/configjson.py @@ -2,9 +2,15 @@ from .util import dbg, err from os import path import sys import json -import traceback +import copy +from .config import Config -class LayoutFile(object): +class ConfigJson(object): + JSON_PROFILE_NAME = "__internal_json_profile__" + JSON_LAYOUT_NAME = "__internal_json_layout__" + + profile_to_use = 'default' + def build_single_tab_layout(self, layoutjson, vertical): dbg ('Budiling a single tab layout from json: %s ' % layoutjson) @@ -50,6 +56,7 @@ class LayoutFile(object): 'type': 'Terminal', 'order': order, 'parent': parent, + 'profile': self.profile_to_use, 'command': layoutjson['command'] } @@ -87,21 +94,7 @@ class LayoutFile(object): counter += 1 - def get_layout_file(self, layoutname): - if (not path.exists(layoutname)): - return None - - dbg('Loading layout from a file: %s' % layoutname) - - layoutjson = None - - try: - with open(layoutname) as json_file: - layoutjson = json.load(json_file) - except Exception as ex: - err('Error loading layout file %s (%s)' % (layoutname, ex)) - return None - + def get_layout(self, layoutjson): try: vertical = True if "vertical" in layoutjson: @@ -119,6 +112,57 @@ class LayoutFile(object): dbg('Json layout is: %s' % result) return result except Exception as ex: - err('Error building a layout from file %s (%s)' % (layoutname, ex)) - traceback.print_exc(ex) + err('Error building a layout from file %s' % ex) return None + + def get_profile(self, profilejson, baseprofile): + try: + result = copy.deepcopy(baseprofile) + + result.update(profilejson) + + dbg('Json profile is: %s' % result) + return result + except Exception as ex: + err('Error building a profile from json file %s' % ex) + return None + + def read_config(self, jsonfile): + if not path.exists(jsonfile): + dbg("Json config file is missing %s" % jsonfile) + return None + + dbg('Loading config json from a file: %s' % jsonfile) + + layoutjson = None + + try: + with open(jsonfile) as json_file: + layoutjson = json.load(json_file) + except Exception as ex: + err('Error loading config json file %s (%s)' % (jsonfile, ex)) + return None + + return layoutjson + + def extend_config(self, jsonfile): + configjson = self.read_config(jsonfile) + + if not configjson: + return None + + config = Config() + + if 'profile' in configjson: + profile = self.get_profile(configjson['profile'], config.base.profiles['default']) + if profile: + config.base.profiles[self.JSON_PROFILE_NAME] = profile + self.profile_to_use = self.JSON_PROFILE_NAME + + if 'layout' in configjson: + layout = self.get_layout(configjson['layout']) + if layout: + config.base.layouts[self.JSON_LAYOUT_NAME] = layout + return self.JSON_LAYOUT_NAME + + return None diff --git a/terminatorlib/optionparse.py b/terminatorlib/optionparse.py index 63a6f625..8efd242b 100644 --- a/terminatorlib/optionparse.py +++ b/terminatorlib/optionparse.py @@ -74,6 +74,8 @@ def parse_options(): 'execute inside the terminal, and its arguments')) parser.add_option('-g', '--config', dest='config', help=_('Specify a config file')) + parser.add_option('-j', '--config-json', dest='configjson', + help=_('Specify a partial config json file')) parser.add_option('-x', '--execute', dest='execute', action='callback', callback=execute_cb, help=_('Use the rest of the command line as a command to execute ' diff --git a/terminatorlib/terminator.py b/terminatorlib/terminator.py index 1ba97332..fea5009c 100644 --- a/terminatorlib/terminator.py +++ b/terminatorlib/terminator.py @@ -16,7 +16,6 @@ from .keybindings import Keybindings from .util import dbg, err, enumerate_descendants from .factory import Factory from .version import APP_NAME, APP_VERSION -from .layoutfile import LayoutFile try: from gi.repository import GdkX11 @@ -50,6 +49,7 @@ class Terminator(Borg): keybindings = None style_providers = None last_focused_term = None + layout_file = None origcwd = None dbus_path = None @@ -227,14 +227,12 @@ class Terminator(Borg): self.prelayout_windows = self.windows[:] layout = copy.deepcopy(self.config.layout_get_config(layoutname)) + if not layout: - layoutfile = LayoutFile() - layout = layoutfile.get_layout_file(layoutname) - if not layout: - # User specified a non-existent layout. default to one Terminal - err('layout %s not defined' % layout) - self.new_window() - return + # User specified a non-existent layout. default to one Terminal + err('layout %s not defined' % layout) + self.new_window() + return # Wind the flat objects into a hierarchy hierarchy = {} @@ -425,6 +423,7 @@ class Terminator(Borg): background-color: alpha(%s, %s); } """ profiles = self.config.base.profiles + for profile in list(profiles.keys()): if profiles[profile]['use_theme_colors']: # Create a dummy window/vte and realise it so it has correct