From 2fa8d7b7786a9be80f93ca415272bb0a0fd65c6d Mon Sep 17 00:00:00 2001 From: Tobi-wan Kenobi Date: Thu, 8 Dec 2016 12:44:52 +0100 Subject: [PATCH] [core/themes] Add module-specific themes Allow module-specific theme information to overload "default" configuration. I.e. it is now possible to have specific prefix or postfix configurations for different modules. The module name is derived for each widget from the module (__module__) from which it was instantiated. see #23 --- bumblebee/engine.py | 7 ++++++- bumblebee/output.py | 33 ++++++++++++++++++++------------- bumblebee/theme.py | 7 +++++++ tests/test_i3baroutput.py | 19 +++++++++++++++---- tests/util.py | 8 +++++++- themes/icons/awesome-fonts.json | 2 +- 6 files changed, 56 insertions(+), 20 deletions(-) diff --git a/bumblebee/engine.py b/bumblebee/engine.py index 2ba5107..d87e66f 100644 --- a/bumblebee/engine.py +++ b/bumblebee/engine.py @@ -13,6 +13,7 @@ class Module(object): this base class. """ def __init__(self, engine, widgets): + self.name = self.__module__.split(".")[-1] self._widgets = [] if widgets: self._widgets = widgets if isinstance(widgets, list) else [widgets] @@ -59,10 +60,14 @@ class Engine(object): """Start the event loop""" self._output.start() while self.running(): + self._output.begin() for module in self._modules: module.update(module.widgets()) - self._output.draw(widgets=module.widgets(), engine=self) + for widget in module.widgets(): + widget.set_module(module) + self._output.draw(widget=widget, engine=self) self._output.flush() + self._output.end() if self.running(): time.sleep(1) diff --git a/bumblebee/output.py b/bumblebee/output.py index 4b9603b..13b35c6 100644 --- a/bumblebee/output.py +++ b/bumblebee/output.py @@ -9,6 +9,13 @@ class Widget(object): """Represents a single visible block in the status bar""" def __init__(self, full_text): self._full_text = full_text + self._module = None + + def set_module(self, module): + self._module = module.name + + def module(self): + return self._module def full_text(self): """Retrieve the full text to display in the widget""" @@ -21,6 +28,7 @@ class I3BarOutput(object): """Manage output according to the i3bar protocol""" def __init__(self, theme): self._theme = theme + self._widgets = [] def start(self): """Print start preamble for i3bar protocol""" @@ -30,30 +38,29 @@ class I3BarOutput(object): """Finish i3bar protocol""" sys.stdout.write("]\n") - def draw_widget(self, result, widget): + def draw(self, widget, engine=None): """Draw a single widget""" full_text = widget.full_text() prefix = self._theme.prefix(widget) suffix = self._theme.suffix(widget) if prefix: - full_text = "{}{}".format(prefix, full_text) + full_text = u"{}{}".format(prefix, full_text) if suffix: - full_text = "{}{}".format(full_text, suffix) - result.append({ - u"full_text": "{}".format(full_text) + full_text = u"{}{}".format(full_text, suffix) + self._widgets.append({ + u"full_text": u"{}".format(full_text) }) - def draw(self, widgets, engine=None): - """Draw a number of widgets""" - if not isinstance(widgets, list): - widgets = [widgets] - result = [] - for widget in widgets: - self.draw_widget(result, widget) - sys.stdout.write(json.dumps(result)) + def begin(self): + """Start one output iteration""" + self._widgets = [] def flush(self): """Flushes output""" + sys.stdout.write(json.dumps(self._widgets)) + + def end(self): + """Finalizes output""" sys.stdout.write(",\n") sys.stdout.flush() diff --git a/bumblebee/theme.py b/bumblebee/theme.py index 3b53f7d..380b20e 100644 --- a/bumblebee/theme.py +++ b/bumblebee/theme.py @@ -55,9 +55,16 @@ class Theme(object): module_theme = self._theme.get(widget.module(), {}) + padding = None + if name != "padding": + padding = self._get(widget, "padding") + value = self._defaults.get(name, default) value = module_theme.get(name, value) + if value and padding: + value = u"{}{}{}".format(padding, value, padding) + return value # algorithm copied from diff --git a/tests/test_i3baroutput.py b/tests/test_i3baroutput.py index e621611..55d6e10 100644 --- a/tests/test_i3baroutput.py +++ b/tests/test_i3baroutput.py @@ -33,25 +33,34 @@ class TestI3BarOutput(unittest.TestCase): @mock.patch("sys.stdout", new_callable=StringIO) def test_draw_single_widget(self, stdout): self.output.draw(self.someWidget) + self.output.flush() result = json.loads(stdout.getvalue())[0] self.assertEquals(result["full_text"], self.someWidget.full_text()) @mock.patch("sys.stdout", new_callable=StringIO) def test_draw_multiple_widgets(self, stdout): - self.output.draw([self.someWidget, self.someWidget]) + for widget in [self.someWidget, self.someWidget]: + self.output.draw(widget) + self.output.flush() result = json.loads(stdout.getvalue()) for res in result: - self.assertEquals(res["full_text"], self.someWidget.full_text()) + self.assertEquals(res["full_text"], widget.full_text()) @mock.patch("sys.stdout", new_callable=StringIO) - def test_flush(self, stdout): - self.output.flush() + def test_begin(self, stdout): + self.output.begin() + self.assertEquals("", stdout.getvalue()) + + @mock.patch("sys.stdout", new_callable=StringIO) + def test_end(self, stdout): + self.output.end() self.assertEquals(",\n", stdout.getvalue()) @mock.patch("sys.stdout", new_callable=StringIO) def test_prefix(self, stdout): self.theme.set_prefix(" - ") self.output.draw(self.someWidget) + self.output.flush() result = json.loads(stdout.getvalue())[0] self.assertEquals(result["full_text"], "{}{}".format( self.theme.prefix(self.someWidget), self.someWidget.full_text()) @@ -61,6 +70,7 @@ class TestI3BarOutput(unittest.TestCase): def test_suffix(self, stdout): self.theme.set_suffix(" - ") self.output.draw(self.someWidget) + self.output.flush() result = json.loads(stdout.getvalue())[0] self.assertEquals(result["full_text"], "{}{}".format( self.someWidget.full_text(), self.theme.suffix(self.someWidget)) @@ -71,6 +81,7 @@ class TestI3BarOutput(unittest.TestCase): self.theme.set_suffix(" - ") self.theme.set_prefix(" * ") self.output.draw(self.someWidget) + self.output.flush() result = json.loads(stdout.getvalue())[0] self.assertEquals(result["full_text"], "{}{}{}".format( self.theme.prefix(self.someWidget), self.someWidget.full_text(), self.theme.suffix(self.someWidget)) diff --git a/tests/util.py b/tests/util.py index 28a562d..334664b 100644 --- a/tests/util.py +++ b/tests/util.py @@ -13,12 +13,18 @@ class MockOutput(object): def stop(self): pass - def draw(self, widgets, engine): + def draw(self, widget, engine): engine.stop() + def begin(self): + pass + def flush(self): pass + def end(self): + pass + class MockWidget(object): def __init__(self, text): self._text = text diff --git a/themes/icons/awesome-fonts.json b/themes/icons/awesome-fonts.json index 34abf24..3424710 100644 --- a/themes/icons/awesome-fonts.json +++ b/themes/icons/awesome-fonts.json @@ -1,5 +1,5 @@ { - "defaults": { "separator": "" }, + "defaults": { "separator": "", "padding": " " }, "date": { "prefix": "" }, "time": { "prefix": "" }, "memory": { "prefix": "" },