[core] Add support for custom colorsets (e.g. pywal)

In a theme file, it is now possible to provide an array of "color
definitions", which allow you to use names instead of colors throughout
the theme file.

Currently, only the colorset "wal" is supported, which reads all colors
from the wal JSON file (~/.cache/wal/colors.json) and makes them usable
in the theme (as "foreground", "background", "cursor", "color12", etc.).

An example of this can be found in the theme wal-powerline.

see #185
This commit is contained in:
Tobias Witek 2017-10-08 08:13:10 +02:00
parent f3fe67e681
commit 5d1d994dce
2 changed files with 65 additions and 3 deletions

View file

@ -25,17 +25,20 @@ def themes():
class Theme(object): class Theme(object):
"""Represents a collection of icons and colors""" """Represents a collection of icons and colors"""
def __init__(self, name): def __init__(self, name):
self._init(self.load(name))
self._widget = None self._widget = None
self._cycle_idx = 0 self._cycle_idx = 0
self._cycle = {} self._cycle = {}
self._prevbg = None self._prevbg = None
self._colorset = {}
self._init(self.load(name))
def _init(self, data): def _init(self, data):
"""Initialize theme from data structure""" """Initialize theme from data structure"""
self._theme = data self._theme = data
for iconset in data.get("icons", []): for iconset in data.get("icons", []):
self._merge(data, self._load_icons(iconset)) self._merge(data, self._load_icons(iconset))
for colorset in data.get("colors", []):
self._merge(self._colorset, self._load_colors(colorset))
self._defaults = data.get("defaults", {}) self._defaults = data.get("defaults", {})
self._cycles = self._theme.get("cycle", []) self._cycles = self._theme.get("cycle", [])
self.reset() self.reset()
@ -99,6 +102,21 @@ class Theme(object):
"""Return the SBW""" """Return the SBW"""
return self._get(widget, "separator-block-width", None) return self._get(widget, "separator-block-width", None)
def _load_wal_colors(self):
walfile = os.path.expanduser("~/.cache/wal/colors.json")
result = {}
with io.open(walfile) as data:
colors = json.load(data)
for field in ["special", "colors"]:
for key in colors[field]:
result[key] = colors[field][key]
return result
def _load_colors(self, name):
"""Load colors for a theme"""
if name == "wal":
return self._load_wal_colors()
def _load_icons(self, name): def _load_icons(self, name):
"""Load icons for a theme""" """Load icons for a theme"""
path = "{}/icons/".format(theme_path()) path = "{}/icons/".format(theme_path())
@ -110,7 +128,7 @@ class Theme(object):
if os.path.isfile(themefile): if os.path.isfile(themefile):
try: try:
with io.open(themefile,encoding="utf-8") as data: with io.open(themefile, encoding="utf-8") as data:
return json.load(data) return json.load(data)
except ValueError as exception: except ValueError as exception:
raise bumblebee.error.ThemeLoadError("JSON error: {}".format(exception)) raise bumblebee.error.ThemeLoadError("JSON error: {}".format(exception))
@ -155,7 +173,9 @@ class Theme(object):
widget.set(key, (idx + 1) % len(value)) widget.set(key, (idx + 1) % len(value))
value = value[idx] value = value[idx]
return value if isinstance(value, list) or isinstance(value, dict):
return value
return self._colorset.get(value, value)
# algorithm copied from # algorithm copied from
# http://blog.impressiver.com/post/31434674390/deep-merge-multiple-python-dicts # http://blog.impressiver.com/post/31434674390/deep-merge-multiple-python-dicts

42
themes/wal-powerline.json Normal file
View file

@ -0,0 +1,42 @@
{
"icons": [ "awesome-fonts" ],
"colors": [ "wal" ],
"defaults": {
"separator-block-width": 0,
"critical": {
"fg": "cursor",
"bg": "color5"
},
"warning": {
"fg": "cursor",
"bg": "color6"
},
"default_separators": false
},
"cycle": [
{
"fg": "foreground",
"bg": "background"
},
{
"fg": "background",
"bg": "foreground"
}
],
"dnf": {
"good": {
"fg": "background",
"bg": "color3"
}
},
"battery": {
"charged": {
"fg": "background",
"bg": "color3"
},
"AC": {
"fg": "background",
"bg": "color3"
}
}
}