[formatting] reformat using "black -t py34"

getting rid of thinking about consistent formatting...
This commit is contained in:
tobi-wan-kenobi 2020-05-03 11:15:52 +02:00
parent fa98bcbdd1
commit 30c1f712a6
119 changed files with 3961 additions and 3495 deletions

View file

@ -19,58 +19,66 @@ import modules.contrib
log = logging.getLogger(__name__)
MODULE_HELP = 'Specify a space-separated list of modules to load. The order of the list determines their order in the i3bar (from left to right). Use <module>:<alias> to provide an alias in case you want to load the same module multiple times, but specify different parameters.'
PARAMETER_HELP = 'Provide configuration parameters in the form of <module>.<key>=<value>'
THEME_HELP = 'Specify the theme to use for drawing modules'
MODULE_HELP = "Specify a space-separated list of modules to load. The order of the list determines their order in the i3bar (from left to right). Use <module>:<alias> to provide an alias in case you want to load the same module multiple times, but specify different parameters."
PARAMETER_HELP = (
"Provide configuration parameters in the form of <module>.<key>=<value>"
)
THEME_HELP = "Specify the theme to use for drawing modules"
def all_modules():
"""Return a list of available modules"""
result = {}
for path in [ modules.core.__file__, modules.contrib.__file__ ]:
for path in [modules.core.__file__, modules.contrib.__file__]:
path = os.path.dirname(path)
for mod in glob.iglob('{}/*.py'.format(path)):
result[os.path.basename(mod).replace('.py', '')] = 1
for mod in glob.iglob("{}/*.py".format(path)):
result[os.path.basename(mod).replace(".py", "")] = 1
res = list(result.keys())
res.sort()
return res
class print_usage(argparse.Action):
def __init__(self, option_strings, dest, nargs=None, **kwargs):
argparse.Action.__init__(self, option_strings, dest, nargs, **kwargs)
self._indent = ' '*2
self._indent = " " * 2
def __call__(self, parser, namespace, value, option_string=None):
if value == 'modules':
if value == "modules":
self._args = namespace
self._format = 'plain'
self._format = "plain"
self.print_modules()
elif value == 'modules-markdown':
elif value == "modules-markdown":
self._args = namespace
self._format = 'markdown'
self._format = "markdown"
self.print_modules()
elif value == 'themes':
elif value == "themes":
self.print_themes()
sys.exit(0)
def print_themes(self):
print(', '.join(core.theme.themes()))
print(", ".join(core.theme.themes()))
def print_modules(self):
if self._format == 'markdown':
print('# Table of modules')
print('|Name |Description |')
print('|-----|------------|')
if self._format == "markdown":
print("# Table of modules")
print("|Name |Description |")
print("|-----|------------|")
for m in all_modules():
try:
basepath = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))
filename = os.path.join(basepath, 'modules', 'core', '{}.py'.format(m))
basepath = os.path.abspath(
os.path.join(os.path.dirname(os.path.realpath(__file__)), "..")
)
filename = os.path.join(basepath, "modules", "core", "{}.py".format(m))
if not os.path.exists(filename):
filename = os.path.join(basepath, 'modules', 'contrib', '{}.py'.format(m))
filename = os.path.join(
basepath, "modules", "contrib", "{}.py".format(m)
)
if not os.path.exists(filename):
log.warning('module {} not found'.format(m))
log.warning("module {} not found".format(m))
continue
doc = None
@ -79,72 +87,126 @@ class print_usage(argparse.Action):
doc = ast.get_docstring(tree)
if not doc:
log.warning('failed to find docstring for {}'.format(m))
log.warning("failed to find docstring for {}".format(m))
continue
if self._format == 'markdown':
doc = doc.replace('<', '\<')
doc = doc.replace('>', '\>')
doc = doc.replace('\n', '<br>')
print('|{} |{} |'.format(m, doc))
if self._format == "markdown":
doc = doc.replace("<", "\<")
doc = doc.replace(">", "\>")
doc = doc.replace("\n", "<br>")
print("|{} |{} |".format(m, doc))
else:
print(textwrap.fill('{}:'.format(m), 80,
initial_indent=self._indent*2, subsequent_indent=self._indent*2))
for line in doc.split('\n'):
print(textwrap.fill(line, 80,
initial_indent=self._indent*3, subsequent_indent=self._indent*6))
print(
textwrap.fill(
"{}:".format(m),
80,
initial_indent=self._indent * 2,
subsequent_indent=self._indent * 2,
)
)
for line in doc.split("\n"):
print(
textwrap.fill(
line,
80,
initial_indent=self._indent * 3,
subsequent_indent=self._indent * 6,
)
)
except Exception as e:
log.warning(e)
class Config(util.store.Store):
def __init__(self, args):
super(Config, self).__init__()
parser = argparse.ArgumentParser(description='bumblebee-status is a modular, theme-able status line generator for the i3 window manager. https://github.com/tobi-wan-kenobi/bumblebee-status/wiki')
parser.add_argument('-m', '--modules', nargs='+', action='append', default=[],
help=MODULE_HELP)
parser.add_argument('-p', '--parameters', nargs='+', action='append', default=[],
help=PARAMETER_HELP)
parser.add_argument('-t', '--theme', default='default', help=THEME_HELP)
parser.add_argument('-i', '--iconset', default='auto',
help='Specify the name of an iconset to use (overrides theme default)')
parser.add_argument('-a', '--autohide', nargs='+', default=[],
help='Specify a list of modules to hide when not in warning/error state')
parser.add_argument('-d', '--debug', action='store_true',
help='Add debug fields to i3 output')
parser.add_argument('-f', '--logfile', help='destination for the debug log file, if -d|--debug is specified; defaults to stderr')
parser.add_argument('-r', '--right-to-left', action='store_true', help='Draw widgets from right to left, rather than left to right (which is the default)')
parser.add_argument('-l', '--list', choices=['modules', 'themes', 'modules-markdown'], help='Display a list of available themes or available modules, along with their parameters',
action=print_usage)
parser = argparse.ArgumentParser(
description="bumblebee-status is a modular, theme-able status line generator for the i3 window manager. https://github.com/tobi-wan-kenobi/bumblebee-status/wiki"
)
parser.add_argument(
"-m", "--modules", nargs="+", action="append", default=[], help=MODULE_HELP
)
parser.add_argument(
"-p",
"--parameters",
nargs="+",
action="append",
default=[],
help=PARAMETER_HELP,
)
parser.add_argument("-t", "--theme", default="default", help=THEME_HELP)
parser.add_argument(
"-i",
"--iconset",
default="auto",
help="Specify the name of an iconset to use (overrides theme default)",
)
parser.add_argument(
"-a",
"--autohide",
nargs="+",
default=[],
help="Specify a list of modules to hide when not in warning/error state",
)
parser.add_argument(
"-d", "--debug", action="store_true", help="Add debug fields to i3 output"
)
parser.add_argument(
"-f",
"--logfile",
help="destination for the debug log file, if -d|--debug is specified; defaults to stderr",
)
parser.add_argument(
"-r",
"--right-to-left",
action="store_true",
help="Draw widgets from right to left, rather than left to right (which is the default)",
)
parser.add_argument(
"-l",
"--list",
choices=["modules", "themes", "modules-markdown"],
help="Display a list of available themes or available modules, along with their parameters",
action=print_usage,
)
self.__args = parser.parse_args(args)
for cfg in [ '~/.bumblebee-status.conf', '~/.config/bumblebee-status.conf', '~/.config/bumblebee-status/config' ]:
for cfg in [
"~/.bumblebee-status.conf",
"~/.config/bumblebee-status.conf",
"~/.config/bumblebee-status/config",
]:
cfg = os.path.expanduser(cfg)
self.load_config(cfg)
parameters = [ item for sub in self.__args.parameters for item in sub ]
parameters = [item for sub in self.__args.parameters for item in sub]
for param in parameters:
if not '=' in param:
log.error('missing value for parameter "{}" - ignoring this parameter'.format(param))
if not "=" in param:
log.error(
'missing value for parameter "{}" - ignoring this parameter'.format(
param
)
)
continue
key, value = param.split('=', 1)
key, value = param.split("=", 1)
self.set(key, value)
def load_config(self, filename):
if os.path.exists(filename):
log.info('loading {}'.format(filename))
log.info("loading {}".format(filename))
tmp = RawConfigParser()
tmp.read(filename)
if tmp.has_section('module-parameters'):
for key, value in tmp.items('module-parameters'):
if tmp.has_section("module-parameters"):
for key, value in tmp.items("module-parameters"):
self.set(key, value)
def modules(self):
return [item for sub in self.__args.modules for item in sub]
def interval(self, default=1):
return util.format.seconds(self.get('interval', default))
return util.format.seconds(self.get("interval", default))
def debug(self):
return self.__args.debug
@ -164,4 +226,5 @@ class Config(util.store.Store):
def autohide(self, name):
return name in self.__args.autohide
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4

View file

@ -1,41 +1,49 @@
import util.format
def never(init):
def call_init(obj, *args, **kwargs):
init(obj, *args, **kwargs)
if obj.parameter('interval') is None:
obj.set('interval', 'never')
if obj.parameter("interval") is None:
obj.set("interval", "never")
return call_init
def every(hours=0, minutes=0, seconds=0):
def decorator_init(init):
def call_init(obj, *args, **kwargs):
init(obj, *args, **kwargs)
if obj.parameter('interval') is None:
obj.set('interval', hours*3600 + minutes*60 + seconds)
if obj.parameter("interval") is None:
obj.set("interval", hours * 3600 + minutes * 60 + seconds)
return call_init
return decorator_init
def scrollable(func):
def wrapper(module, widget):
text = func(module, widget)
if not text:
return text
width = widget.get('theme.width', util.format.asint(module.parameter('width', 30)))
if util.format.asbool(module.parameter('scrolling.makewide', True)):
widget.set('theme.minwidth', 'A'*width)
width = widget.get(
"theme.width", util.format.asint(module.parameter("width", 30))
)
if util.format.asbool(module.parameter("scrolling.makewide", True)):
widget.set("theme.minwidth", "A" * width)
if width < 0 or len(text) <= width:
return text
start = widget.get('scrolling.start', 0)
bounce = util.format.asbool(module.parameter('scrolling.bounce', True))
scroll_speed = util.format.asint(module.parameter('scrolling.speed', 1))
direction = widget.get('scrolling.direction', 'right')
start = widget.get("scrolling.start", 0)
bounce = util.format.asbool(module.parameter("scrolling.bounce", True))
scroll_speed = util.format.asint(module.parameter("scrolling.speed", 1))
direction = widget.get("scrolling.direction", "right")
if direction == 'left':
if direction == "left":
scroll_speed = -scroll_speed
if start + scroll_speed <= 0: # bounce back
widget.set('scrolling.direction', 'right')
if start + scroll_speed <= 0: # bounce back
widget.set("scrolling.direction", "right")
next_start = start + scroll_speed
if next_start + width > len(text):
@ -43,11 +51,13 @@ def scrollable(func):
next_start = 0
else:
next_start = start - scroll_speed
widget.set('scrolling.direction', 'left')
widget.set("scrolling.direction", "left")
widget.set('scrolling.start', next_start)
widget.set("scrolling.start", next_start)
return text[start : start + width]
return text[start:start+width]
return wrapper
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4

View file

@ -1,6 +1,6 @@
__callbacks = {}
def register(event, callback, *args, **kwargs):
cb = callback
if len(args) + len(kwargs) > 0:
@ -8,12 +8,15 @@ def register(event, callback, *args, **kwargs):
__callbacks.setdefault(event, []).append(cb)
def clear():
__callbacks.clear()
def trigger(event, *args, **kwargs):
cb = __callbacks.get(event, [])
if len(cb) == 0: return False
if len(cb) == 0:
return False
for callback in cb:
if len(args) + len(kwargs) == 0:
@ -22,4 +25,5 @@ def trigger(event, *args, **kwargs):
callback(*args, **kwargs)
return True
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4

View file

@ -11,45 +11,59 @@ RIGHT_MOUSE = 3
WHEEL_UP = 4
WHEEL_DOWN = 5
def button_name(button):
if button == LEFT_MOUSE: return 'left-mouse'
if button == RIGHT_MOUSE: return 'right-mouse'
if button == MIDDLE_MOUSE: return 'middle-mouse'
if button == WHEEL_UP: return 'wheel-up'
if button == WHEEL_DOWN: return 'wheel-down'
return 'n/a'
if button == LEFT_MOUSE:
return "left-mouse"
if button == RIGHT_MOUSE:
return "right-mouse"
if button == MIDDLE_MOUSE:
return "middle-mouse"
if button == WHEEL_UP:
return "wheel-up"
if button == WHEEL_DOWN:
return "wheel-down"
return "n/a"
class Object(object):
def __init__(self):
super(Object, self).__init__()
self.id = str(uuid.uuid4())
def __event_id(obj_id, button):
return '{}::{}'.format(obj_id, button_name(button))
return "{}::{}".format(obj_id, button_name(button))
def __execute(cmd):
try:
util.cli.execute(cmd, wait=False)
except Exception as e:
logging.error('failed to invoke callback: {}'.format(e))
logging.error("failed to invoke callback: {}".format(e))
def register(obj, button=None, cmd=None):
event_id = __event_id(obj.id if obj is not None else '', button)
logging.debug('registering callback {}'.format(event_id))
event_id = __event_id(obj.id if obj is not None else "", button)
logging.debug("registering callback {}".format(event_id))
if callable(cmd):
core.event.register(event_id, cmd)
else:
core.event.register(event_id, lambda _: __execute(cmd))
def trigger(event):
if not 'button' in event: return
if not "button" in event:
return
triggered = False
for field in ['instance', 'name']:
if not field in event: continue
if core.event.trigger(__event_id(event[field], event['button']), event):
for field in ["instance", "name"]:
if not field in event:
continue
if core.event.trigger(__event_id(event[field], event["button"]), event):
triggered = True
if not triggered:
core.event.trigger(__event_id('', event['button']), event)
core.event.trigger(__event_id("", event["button"]), event)
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4

View file

@ -7,35 +7,41 @@ import core.widget
import core.decorators
try:
error = ModuleNotFoundError('')
error = ModuleNotFoundError("")
except Exception as e:
ModuleNotFoundError = Exception
log = logging.getLogger(__name__)
def load(module_name, config=core.config.Config([]), theme=None):
error = None
module_short, alias = (module_name.split(':') + [module_name])[0:2]
config.set('__alias__', alias)
for namespace in [ 'core', 'contrib' ]:
module_short, alias = (module_name.split(":") + [module_name])[0:2]
config.set("__alias__", alias)
for namespace in ["core", "contrib"]:
try:
mod = importlib.import_module('modules.{}.{}'.format(namespace, module_short))
log.debug('importing {} from {}.{}'.format(module_short, namespace, module_short))
return getattr(mod, 'Module')(config, theme)
mod = importlib.import_module(
"modules.{}.{}".format(namespace, module_short)
)
log.debug(
"importing {} from {}.{}".format(module_short, namespace, module_short)
)
return getattr(mod, "Module")(config, theme)
except ImportError as e:
error = e
log.fatal('failed to import {}: {}'.format(module_name, error))
error = e
log.fatal("failed to import {}: {}".format(module_name, error))
return Error(config=config, module=module_name, error=error)
class Module(core.input.Object):
def __init__(self, config=core.config.Config([]), theme=None, widgets=[]):
super().__init__()
self.__config = config
self.__widgets = widgets if isinstance(widgets, list) else [ widgets ]
self.__widgets = widgets if isinstance(widgets, list) else [widgets]
self.module_name = self.__module__.split('.')[-1]
self.module_name = self.__module__.split(".")[-1]
self.name = self.module_name
self.alias = self.__config.get('__alias__', None)
self.alias = self.__config.get("__alias__", None)
self.id = self.alias if self.alias else self.name
self.next_update = None
@ -50,13 +56,13 @@ class Module(core.input.Object):
def parameter(self, key, default=None):
value = default
for prefix in [ self.name, self.module_name, self.alias ]:
value = self.__config.get('{}.{}'.format(prefix, key), value)
for prefix in [self.name, self.module_name, self.alias]:
value = self.__config.get("{}.{}".format(prefix, key), value)
# TODO retrieve from config file
return value
def set(self, key, value):
self.__config.set('{}.{}'.format(self.name, key), value)
self.__config.set("{}.{}".format(self.name, key), value)
def update(self):
pass
@ -65,8 +71,8 @@ class Module(core.input.Object):
try:
self.update()
except Exception as e:
self.set('interval', 1)
module = Error(config=self.__config, module='error', error=str(e))
self.set("interval", 1)
module = Error(config=self.__config, module="error", error=str(e))
self.__widgets = [module.widget()]
self.update = module.update
@ -75,28 +81,31 @@ class Module(core.input.Object):
self.__widgets = widgets
return self.__widgets
def add_widget(self, full_text='', name=None):
def add_widget(self, full_text="", name=None):
widget = core.widget.Widget(full_text=full_text, name=name, module=self)
self.widgets().append(widget)
return widget
def widget(self, name=None):
if not name: return self.widgets()[0]
if not name:
return self.widgets()[0]
for w in self.widgets():
if w.name == name: return w
if w.name == name:
return w
return None
def state(self, widget):
return []
def threshold_state(self, value, warn, crit):
if value > float(self.parameter('critical', crit)):
return 'critical'
if value > float(self.parameter('warning', warn)):
return 'warning'
if value > float(self.parameter("critical", crit)):
return "critical"
if value > float(self.parameter("warning", warn)):
return "warning"
return None
class Error(Module):
def __init__(self, module, error, config=core.config.Config([]), theme=None):
super().__init__(config, theme, core.widget.Widget(self.full_text))
@ -104,9 +113,10 @@ class Error(Module):
self.__error = error
def full_text(self, widget):
return '{}: {}'.format(self.__module, self.__error)
return "{}: {}".format(self.__module, self.__error)
def state(self, widget):
return ['critical']
return ["critical"]
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4

View file

@ -7,15 +7,17 @@ import core.event
import util.format
def dump_json(obj):
return obj.dict()
def assign(src, dst, key, src_key=None, default=None):
if not src_key:
if key.startswith('_'):
if key.startswith("_"):
src_key = key
else:
src_key = key.replace('_', '-') # automagically replace _ with -
src_key = key.replace("_", "-") # automagically replace _ with -
for k in src_key if isinstance(src_key, list) else [src_key]:
if k in src:
@ -24,12 +26,23 @@ def assign(src, dst, key, src_key=None, default=None):
if default is not None:
dst[key] = default
class block(object):
__COMMON_THEME_FIELDS = [
'separator', 'separator-block-width', 'default-separators',
'border-top', 'border-left', 'border-right', 'border-bottom',
'fg', 'bg', 'padding', 'prefix', 'suffix'
"separator",
"separator-block-width",
"default-separators",
"border-top",
"border-left",
"border-right",
"border-bottom",
"fg",
"bg",
"padding",
"prefix",
"suffix",
]
def __init__(self, theme, module, widget):
self.__attributes = {}
for key in self.__COMMON_THEME_FIELDS:
@ -37,72 +50,85 @@ class block(object):
if tmp is not None:
self.__attributes[key] = tmp
self.__attributes['name'] = module.id
self.__attributes['instance'] = widget.id
self.__attributes['prev-bg'] = theme.get('bg', 'previous')
self.__attributes["name"] = module.id
self.__attributes["instance"] = widget.id
self.__attributes["prev-bg"] = theme.get("bg", "previous")
def set(self, key, value):
self.__attributes[key] = value
def is_pango(self, attr):
if isinstance(attr, dict) and 'pango' in attr:
if isinstance(attr, dict) and "pango" in attr:
return True
return False
def pangoize(self, text):
if not self.is_pango(text):
return text
self.__attributes['markup'] = 'pango'
attr = dict(text['pango'])
text = attr.get('full_text', '')
if 'full_text' in attr:
del attr['full_text']
result = '<span'
self.__attributes["markup"] = "pango"
attr = dict(text["pango"])
text = attr.get("full_text", "")
if "full_text" in attr:
del attr["full_text"]
result = "<span"
for key, value in attr.items():
result = '{} {}="{}"'.format(result, key, value)
result = '{}>{}</span>'.format(result, text)
result = "{}>{}</span>".format(result, text)
return result
def dict(self):
result = {}
assign(self.__attributes, result, 'full_text', ['full_text', 'separator'])
assign(self.__attributes, result, 'separator', 'default-separators')
assign(self.__attributes, result, "full_text", ["full_text", "separator"])
assign(self.__attributes, result, "separator", "default-separators")
if '_decorator' in self.__attributes:
assign(self.__attributes, result, 'color', 'bg')
assign(self.__attributes, result, 'background', 'prev-bg')
result['_decorator'] = True
if "_decorator" in self.__attributes:
assign(self.__attributes, result, "color", "bg")
assign(self.__attributes, result, "background", "prev-bg")
result["_decorator"] = True
else:
assign(self.__attributes, result, 'color', 'fg')
assign(self.__attributes, result, 'background', 'bg')
assign(self.__attributes, result, "color", "fg")
assign(self.__attributes, result, "background", "bg")
if 'full_text' in self.__attributes:
result['full_text'] = self.pangoize(result['full_text'])
result['full_text'] = self.__format(self.__attributes['full_text'])
if "full_text" in self.__attributes:
result["full_text"] = self.pangoize(result["full_text"])
result["full_text"] = self.__format(self.__attributes["full_text"])
for k in [
'name', 'instance', 'separator_block_width', 'border', 'border_top',
'border_bottom', 'border_left', 'border_right', 'markup',
'_raw', '_suffix', '_prefix', 'min_width'
"name",
"instance",
"separator_block_width",
"border",
"border_top",
"border_bottom",
"border_left",
"border_right",
"markup",
"_raw",
"_suffix",
"_prefix",
"min_width",
]:
assign(self.__attributes, result, k)
return result
def __pad(self, text):
padding = self.__attributes.get('padding', '')
if not text: return padding
return '{}{}{}'.format(padding, text, padding)
padding = self.__attributes.get("padding", "")
if not text:
return padding
return "{}{}{}".format(padding, text, padding)
def __format(self, text):
if text is None: return None
prefix = self.__pad(self.pangoize(self.__attributes.get('prefix')))
suffix = self.__pad(self.pangoize(self.__attributes.get('suffix')))
self.set('_prefix', prefix)
self.set('_suffix', suffix)
self.set('_raw', text)
return '{}{}{}'.format(prefix, text, suffix)
if text is None:
return None
prefix = self.__pad(self.pangoize(self.__attributes.get("prefix")))
suffix = self.__pad(self.pangoize(self.__attributes.get("suffix")))
self.set("_prefix", prefix)
self.set("_suffix", suffix)
self.set("_raw", text)
return "{}{}{}".format(prefix, text, suffix)
class i3(object):
def __init__(self, theme=core.theme.Theme(), config=core.config.Config([])):
@ -110,10 +136,10 @@ class i3(object):
self.__content = {}
self.__theme = theme
self.__config = config
core.event.register('update', self.update)
core.event.register('start', self.draw, 'start')
core.event.register('draw', self.draw, 'statusline')
core.event.register('stop', self.draw, 'stop')
core.event.register("update", self.update)
core.event.register("start", self.draw, "start")
core.event.register("draw", self.draw, "statusline")
core.event.register("stop", self.draw, "stop")
def theme(self, new_theme=None):
if new_theme:
@ -123,63 +149,65 @@ class i3(object):
def modules(self, modules=None):
if not modules:
return self.__modules
self.__modules = modules if isinstance(modules, list) else [ modules ]
self.__modules = modules if isinstance(modules, list) else [modules]
def draw(self, what, args=None):
cb = getattr(self, what)
data = cb(args) if args else cb()
if 'blocks' in data:
sys.stdout.write(json.dumps(data['blocks'], default=dump_json))
if 'suffix' in data:
sys.stdout.write(data['suffix'])
sys.stdout.write('\n')
if "blocks" in data:
sys.stdout.write(json.dumps(data["blocks"], default=dump_json))
if "suffix" in data:
sys.stdout.write(data["suffix"])
sys.stdout.write("\n")
sys.stdout.flush()
def start(self):
return {
'blocks': { 'version': 1, 'click_events': True },
'suffix': '\n[',
"blocks": {"version": 1, "click_events": True},
"suffix": "\n[",
}
def stop(self):
return { 'suffix': '\n]' }
return {"suffix": "\n]"}
def __separator_block(self, module, widget):
if not self.__theme.get('separator'):
if not self.__theme.get("separator"):
return []
blk = block(self.__theme, module, widget)
blk.set('_decorator', True)
blk.set("_decorator", True)
return [blk]
def __content_block(self, module, widget):
blk = block(self.__theme, module, widget)
minwidth = widget.theme('minwidth')
minwidth = widget.theme("minwidth")
if minwidth is not None:
try:
blk.set('min-width', '-'*int(minwidth))
blk.set("min-width", "-" * int(minwidth))
except:
blk.set('min-width', minwidth)
blk.set('full_text', self.__content[widget])
if widget.get('pango', False):
blk.set('markup', 'pango')
blk.set("min-width", minwidth)
blk.set("full_text", self.__content[widget])
if widget.get("pango", False):
blk.set("markup", "pango")
if self.__config.debug():
state = module.state(widget)
if isinstance(state, list):
state = ', '.join(state)
blk.set('__state', state)
state = ", ".join(state)
blk.set("__state", state)
return blk
def blocks(self, module):
blocks = []
for widget in module.widgets():
if widget.module and self.__config.autohide(widget.module.name):
if not any(state in widget.state() for state in [ 'warning', 'critical']):
if not any(
state in widget.state() for state in ["warning", "critical"]
):
continue
if module.hidden():
continue
blocks.extend(self.__separator_block(module, widget))
blocks.append(self.__content_block(module, widget))
core.event.trigger('next-widget')
core.event.trigger("next-widget")
return blocks
# TODO: only updates full text, not the state!?
@ -189,14 +217,16 @@ class i3(object):
if affected_modules and not module.id in affected_modules:
continue
if not affected_modules and module.next_update:
if module.parameter('interval', '') == 'never':
if module.parameter("interval", "") == "never":
continue
if now < module.next_update:
continue
if not redraw_only:
module.update_wrapper()
if module.parameter('interval', '') != 'never':
module.next_update = now + util.format.seconds(module.parameter('interval', self.__config.interval()))
if module.parameter("interval", "") != "never":
module.next_update = now + util.format.seconds(
module.parameter("interval", self.__config.interval())
)
for widget in module.widgets():
self.__content[widget] = widget.full_text()
@ -204,12 +234,10 @@ class i3(object):
blocks = []
for module in self.__modules:
blocks.extend(self.blocks(module))
return {
'blocks': blocks,
'suffix': ','
}
return {"blocks": blocks, "suffix": ","}
def wait(self, interval):
time.sleep(interval)
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4

View file

@ -10,24 +10,26 @@ import util.algorithm
log = logging.getLogger(__name__)
THEME_BASE_DIR=os.path.dirname(os.path.realpath(__file__))
PATHS=[
'.',
os.path.join(THEME_BASE_DIR, '../themes'),
os.path.expanduser('~/.config/bumblebee-status/themes'),
THEME_BASE_DIR = os.path.dirname(os.path.realpath(__file__))
PATHS = [
".",
os.path.join(THEME_BASE_DIR, "../themes"),
os.path.expanduser("~/.config/bumblebee-status/themes"),
]
def themes():
themes_dict = {}
for path in PATHS:
for filename in glob.iglob('{}/*.json'.format(path)):
if 'test' not in filename:
themes_dict[os.path.basename(filename).replace('.json', '')] = 1
for filename in glob.iglob("{}/*.json".format(path)):
if "test" not in filename:
themes_dict[os.path.basename(filename).replace(".json", "")] = 1
result = list(themes_dict.keys())
result.sort()
return result
def merge_replace(value, new_value, key):
if not isinstance(value, dict):
return new_value
@ -35,12 +37,13 @@ def merge_replace(value, new_value, key):
util.algorithm.merge(value, new_value)
return value
# right now, merging needs explicit pango support :(
if 'pango' in value:
value['pango']['full_text'] = new_value
if "pango" in value:
value["pango"]["full_text"] = new_value
return value
class Theme(object):
def __init__(self, name='default', iconset='auto', raw_data=None):
def __init__(self, name="default", iconset="auto", raw_data=None):
self.name = name
self.__widget_count = 0
self.__previous = {}
@ -48,15 +51,15 @@ class Theme(object):
self.__keywords = {}
self.__value_idx = {}
self.__data = raw_data if raw_data else self.load(name)
for icons in self.__data.get('icons', []):
util.algorithm.merge(self.__data, self.load(icons, 'icons'))
if iconset != 'auto':
util.algorithm.merge(self.__data, self.load(iconset, 'icons'))
for colors in self.__data.get('colors', []):
for icons in self.__data.get("icons", []):
util.algorithm.merge(self.__data, self.load(icons, "icons"))
if iconset != "auto":
util.algorithm.merge(self.__data, self.load(iconset, "icons"))
for colors in self.__data.get("colors", []):
util.algorithm.merge(self.__keywords, self.load_keywords(colors))
core.event.register('draw', self.__start)
core.event.register('next-widget', self.__next_widget)
core.event.register("draw", self.__start)
core.event.register("next-widget", self.__next_widget)
def keywords(self):
return self.__keywords
@ -64,17 +67,20 @@ class Theme(object):
def color(self, name, default=None):
return self.keywords().get(name, default)
def load(self, name, subdir=''):
if isinstance(name, dict): return name # support plain data
def load(self, name, subdir=""):
if isinstance(name, dict):
return name # support plain data
for path in PATHS:
theme_file = os.path.join(path, subdir, '{}.json'.format(name))
theme_file = os.path.join(path, subdir, "{}.json".format(name))
result = self.__load_json(theme_file)
if result != {}: return result
raise RuntimeError('unable to find theme {}'.format(name))
if result != {}:
return result
raise RuntimeError("unable to find theme {}".format(name))
def __load_json(self, filename):
filename = os.path.expanduser(filename)
if not os.path.isfile(filename): return {}
if not os.path.isfile(filename):
return {}
with io.open(filename) as data:
return json.load(data)
@ -82,15 +88,15 @@ class Theme(object):
try:
if isinstance(name, dict):
return name
if name.lower() == 'wal':
wal = self.__load_json('~/.cache/wal/colors.json')
if name.lower() == "wal":
wal = self.__load_json("~/.cache/wal/colors.json")
result = {}
for field in ['special', 'colors']:
for field in ["special", "colors"]:
for key in wal.get(field, {}):
result[key] = wal[field][key]
return result
except Exception as e:
log.error('failed to load colors: {}', e)
log.error("failed to load colors: {}", e)
def __start(self):
self.__widget_count = 0
@ -107,14 +113,14 @@ class Theme(object):
def get(self, key, widget=None, default=None):
if not widget:
widget = core.widget.Widget('')
widget = core.widget.Widget("")
# special handling
if widget == 'previous':
if widget == "previous":
return self.__previous.get(key, None)
value = default
for option in ['defaults', 'cycle']:
for option in ["defaults", "cycle"]:
if option in self.__data:
tmp = self.__data[option]
if isinstance(tmp, list):
@ -127,7 +133,9 @@ class Theme(object):
value = merge_replace(value, self.__data.get(key, value), key)
if widget.module:
value = merge_replace(value, self.get(widget.module.name, None, {}).get(key, value), key)
value = merge_replace(
value, self.get(widget.module.name, None, {}).get(key, value), key
)
if not key in widget.state():
for state in widget.state():
@ -138,11 +146,12 @@ class Theme(object):
value = self.__keywords.get(value, value)
if isinstance(value, list):
idx = self.__value_idx.get('{}::{}'.format(widget.id, key), 0) % len(value)
self.__value_idx['{}::{}'.format(widget.id, key)] = idx
idx = self.__value_idx.get("{}::{}".format(widget.id, key), 0) % len(value)
self.__value_idx["{}::{}".format(widget.id, key)] = idx
widget.set(key, idx)
value = value[idx]
self.__current[key] = value
return value
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4

View file

@ -4,8 +4,9 @@ import core.decorators
import util.store
import util.format
class Widget(util.store.Store, core.input.Object):
def __init__(self, full_text='', name=None, module=None):
def __init__(self, full_text="", name=None, module=None):
super(Widget, self).__init__()
self.__full_text = full_text
self.module = module
@ -19,25 +20,27 @@ class Widget(util.store.Store, core.input.Object):
def module(self, module):
self.__module = module
if self.index() < 0: return
if self.index() < 0:
return
if module:
custom_ids = util.format.aslist(module.parameter('id'))
custom_ids = util.format.aslist(module.parameter("id"))
if len(custom_ids) > self.index():
self.id = custom_ids[self.index()]
def index(self):
if not self.module: return 0
if not self.module:
return 0
idx = 0
for w in self.module.widgets():
if w.id == self.id:
return idx
idx = idx + 1
return -1 # not found
return -1 # not found
def theme(self, attribute):
attr = 'theme.{}'.format(attribute)
attr = "theme.{}".format(attribute)
if self.module:
param = util.format.aslist(self.module.parameter(attr))
if param and len(param) > self.index():
@ -54,12 +57,13 @@ class Widget(util.store.Store, core.input.Object):
def state(self):
rv = []
if self.get('state', None):
tmp = self.get('state')
if self.get("state", None):
tmp = self.get("state")
rv = tmp[:] if isinstance(tmp, list) else [tmp]
if self.module:
tmp = self.module.state(self)
rv.extend(tmp if isinstance(tmp, list) else [tmp])
return rv
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4