diff --git a/bumblebee/theme.py b/bumblebee/theme.py index b9462f2..3b53f7d 100644 --- a/bumblebee/theme.py +++ b/bumblebee/theme.py @@ -1,6 +1,7 @@ """Theme support""" import os +import copy import json import bumblebee.error @@ -12,11 +13,13 @@ def theme_path(): class Theme(object): """Represents a collection of icons and colors""" def __init__(self, name): - theme = self.load(name) self._init(self.load(name)) def _init(self, data): """Initialize theme from data structure""" + for iconset in data.get("icons", []): + self._merge(data, self._load_icons(iconset)) + self._theme = data self._defaults = data.get("defaults", {}) def prefix(self, widget): @@ -31,10 +34,14 @@ class Theme(object): theme = json.loads(data) self._init(theme) - def load(self, name): + def _load_icons(self, name): + path = "{}/icons/".format(theme_path()) + return self.load(name, path=path) + + def load(self, name, path=theme_path()): """Load and parse a theme file""" - path = theme_path() themefile = "{}/{}.json".format(path, name) + if os.path.isfile(themefile): try: with open(themefile) as data: @@ -44,10 +51,32 @@ class Theme(object): else: raise bumblebee.error.ThemeLoadError("no such theme: {}".format(name)) - def _get(self, widget, name,default=None): - value = default - value = self._defaults.get(name, value) + def _get(self, widget, name, default=None): + + module_theme = self._theme.get(widget.module(), {}) + + value = self._defaults.get(name, default) + value = module_theme.get(name, value) return value + # algorithm copied from + # http://blog.impressiver.com/post/31434674390/deep-merge-multiple-python-dicts + # nicely done :) + def _merge(self, target, *args): + if len(args) > 1: + for item in args: + self._merge(item) + return target + + item = args[0] + if not isinstance(item, dict): + return item + for key, value in item.items(): + if key in target and isinstance(target[key], dict): + self._merge(target[key], value) + else: + target[key] = copy.deepcopy(value) + return target + # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/test_theme.py b/tests/test_theme.py index 6d57a71..a956d4f 100644 --- a/tests/test_theme.py +++ b/tests/test_theme.py @@ -9,8 +9,15 @@ class TestTheme(unittest.TestCase): def setUp(self): self.nonexistentThemeName = "no-such-theme" self.invalidThemeName = "invalid" - self.validThemeName = "solarized-powerline" + self.validThemeName = "test" self.someWidget = MockWidget("foo") + self.theme = Theme(self.validThemeName) + + self.widgetTheme = "test-widget" + self.defaultPrefix = "default-prefix" + self.defaultSuffix = "default-suffix" + self.widgetPrefix = "widget-prefix" + self.widgetSuffix = "widget-suffix" def test_load_valid_theme(self): try: @@ -26,14 +33,14 @@ class TestTheme(unittest.TestCase): with self.assertRaises(ThemeLoadError): Theme(self.invalidThemeName) - def test_prefix(self): - theme = Theme(self.validThemeName) - theme.loads('{"defaults": { "prefix": "test" }}') - self.assertEquals(theme.prefix(self.someWidget), "test") + def test_default_prefix(self): + self.assertEquals(self.theme.prefix(self.someWidget), self.defaultPrefix) - def test_suffix(self): - theme = Theme(self.validThemeName) - theme.loads('{"defaults": { "suffix": "test" }}') - self.assertEquals(theme.suffix(self.someWidget), "test") + def test_default_suffix(self): + self.assertEquals(self.theme.suffix(self.someWidget), self.defaultSuffix) + + def test_widget_prefix(self): + self.someWidget.set_module(self.widgetTheme) + self.assertEquals(self.theme.prefix(self.someWidget), self.widgetPrefix) # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/util.py b/tests/util.py index 462c6c8..28a562d 100644 --- a/tests/util.py +++ b/tests/util.py @@ -22,10 +22,17 @@ class MockOutput(object): class MockWidget(object): def __init__(self, text): self._text = text + self._module = None + + def set_module(self, name): + self._module = name def update(self, widgets): pass + def module(self): + return self._module + def full_text(self): return self._text diff --git a/themes/icons/test.json b/themes/icons/test.json new file mode 100644 index 0000000..ad17178 --- /dev/null +++ b/themes/icons/test.json @@ -0,0 +1,6 @@ +{ + "test-widget": { + "prefix": "widget-prefix", + "suffix": "widget-suffix" + } +} diff --git a/themes/test.json b/themes/test.json new file mode 100644 index 0000000..5f5cd00 --- /dev/null +++ b/themes/test.json @@ -0,0 +1,7 @@ +{ + "icons": [ "test" ], + "defaults": { + "prefix": "default-prefix", + "suffix": "default-suffix" + } +}