[all] Major refactoring
Introduce an "Engine" class to abstract some of the details of loading modules, registering events, etc.
This commit is contained in:
parent
a6bdd0557c
commit
d62258c89d
5 changed files with 135 additions and 116 deletions
110
bumblebee-status
110
bumblebee-status
|
@ -1,114 +1,20 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import glob
|
|
||||||
import pkgutil
|
|
||||||
import argparse
|
|
||||||
import textwrap
|
|
||||||
import threading
|
|
||||||
import importlib
|
|
||||||
import bumblebee.theme
|
import bumblebee.theme
|
||||||
import bumblebee.modules
|
import bumblebee.engine
|
||||||
import bumblebee.outputs.i3
|
import bumblebee.outputs.i3
|
||||||
|
|
||||||
def print_module_list():
|
|
||||||
print "available modules:"
|
|
||||||
path = os.path.dirname(bumblebee.modules.__file__)
|
|
||||||
for mod in [ name for _, name, _ in pkgutil.iter_modules([path])]:
|
|
||||||
m = importlib.import_module("bumblebee.modules.{}".format(mod))
|
|
||||||
|
|
||||||
desc = "n/a" if not hasattr(m, "description") else getattr(m, "description")()
|
|
||||||
usage = "n/a" if not hasattr(m, "usage") else getattr(m, "usage")()
|
|
||||||
notes = "n/a" if not hasattr(m, "notes") else getattr(m, "notes")()
|
|
||||||
|
|
||||||
print " {}: ".format(mod)
|
|
||||||
print textwrap.fill("Description: {}".format(desc),
|
|
||||||
80, initial_indent=" ", subsequent_indent=" ")
|
|
||||||
print textwrap.fill("Usage : {}".format(usage),
|
|
||||||
80, initial_indent=" ", subsequent_indent=" ")
|
|
||||||
print textwrap.fill("Notes : {}".format(notes),
|
|
||||||
80, initial_indent=" ", subsequent_indent=" ")
|
|
||||||
print ""
|
|
||||||
|
|
||||||
def print_theme_list():
|
|
||||||
d = bumblebee.theme.getpath()
|
|
||||||
|
|
||||||
print "available themes:"
|
|
||||||
print textwrap.fill(", ".join(
|
|
||||||
[ os.path.basename(f).replace(".json", "") for f in glob.iglob("{}/*.json".format(d)) ]),
|
|
||||||
80, initial_indent = " ", subsequent_indent = " "
|
|
||||||
)
|
|
||||||
|
|
||||||
def init_argument_parser():
|
|
||||||
parser = argparse.ArgumentParser(description="display system data in the i3bar")
|
|
||||||
parser.add_argument("-m", "--modules", nargs="+", help="List of modules to load. The order of the list determines their order in the i3bar (from left to right)", default=[])
|
|
||||||
parser.add_argument("-e", "--events", nargs="+", help="List of click events that should be handled. Format is: <module name><splitter, see -s><button ID><splitter><command to execute>", default=[])
|
|
||||||
parser.add_argument("-l", "--list", action="store_true", help="List all available modules and themes")
|
|
||||||
parser.add_argument("-t", "--theme", help="Specify which theme to use for drawing the modules")
|
|
||||||
parser.add_argument("-i", "--interval", help="Specify the update interval", default=1, type=int)
|
|
||||||
parser.add_argument("-s", "--split", help="Specify string to use for splitting modules and their arguments", default="::")
|
|
||||||
|
|
||||||
return parser
|
|
||||||
|
|
||||||
def getmodule(args, output, modulespec):
|
|
||||||
s = args.split
|
|
||||||
module_name = modulespec if not s in modulespec else modulespec.split(s)[0]
|
|
||||||
module_args = None if not s in modulespec else modulespec.split(s)[1:]
|
|
||||||
module = importlib.import_module("bumblebee.modules.{}".format(module_name))
|
|
||||||
return getattr(module, "Module")(output, module_args)
|
|
||||||
|
|
||||||
def register_event(args, output, event):
|
|
||||||
ev = event.split(args.split)
|
|
||||||
if len(ev) < 3:
|
|
||||||
sys.stderr.write("invalid format for click event, expect 3 parameters")
|
|
||||||
return
|
|
||||||
output.add_callback(
|
|
||||||
module=ev[0],
|
|
||||||
button=int(ev[1]),
|
|
||||||
cmd=ev[2],
|
|
||||||
)
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = init_argument_parser()
|
args = bumblebee.engine.Arguments()
|
||||||
|
|
||||||
if len(sys.argv) == 1:
|
theme = bumblebee.theme.Theme(args.args())
|
||||||
parser.print_help()
|
output = bumblebee.outputs.i3.Output(args.args())
|
||||||
parser.exit()
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
engine = bumblebee.engine.Engine(args.args(), theme, output)
|
||||||
|
engine.load_modules()
|
||||||
|
engine.register_events()
|
||||||
|
|
||||||
if args.list:
|
engine.run()
|
||||||
print_module_list()
|
|
||||||
print_theme_list()
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
refresh = threading.Condition()
|
|
||||||
theme = bumblebee.theme.Theme(args.theme) if args.theme else bumblebee.theme.Theme()
|
|
||||||
output = bumblebee.outputs.i3.i3bar(refresh, theme)
|
|
||||||
|
|
||||||
modules = []
|
|
||||||
for m in args.modules:
|
|
||||||
modules.append(getmodule(args, output, m))
|
|
||||||
|
|
||||||
for e in args.events:
|
|
||||||
register_event(args, output, e)
|
|
||||||
|
|
||||||
print output.start()
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
refresh.acquire()
|
|
||||||
while True:
|
|
||||||
theme.reset()
|
|
||||||
for m in modules:
|
|
||||||
output.add(m)
|
|
||||||
theme.next()
|
|
||||||
print output.get()
|
|
||||||
sys.stdout.flush()
|
|
||||||
refresh.wait(args.interval)
|
|
||||||
|
|
||||||
print output.stop()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
118
bumblebee/engine.py
Normal file
118
bumblebee/engine.py
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import glob
|
||||||
|
import pkgutil
|
||||||
|
import textwrap
|
||||||
|
import argparse
|
||||||
|
import threading
|
||||||
|
import importlib
|
||||||
|
import bumblebee.theme
|
||||||
|
|
||||||
|
class Arguments:
|
||||||
|
def __init__(self):
|
||||||
|
parser = self.create_parser()
|
||||||
|
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
parser.print_help()
|
||||||
|
parser.exit()
|
||||||
|
|
||||||
|
self._args = parser.parse_args()
|
||||||
|
|
||||||
|
if self._args.list:
|
||||||
|
self.print_module_list()
|
||||||
|
self.print_theme_list()
|
||||||
|
parser.exit()
|
||||||
|
|
||||||
|
def args(self):
|
||||||
|
return self._args
|
||||||
|
|
||||||
|
def create_parser(self):
|
||||||
|
parser = argparse.ArgumentParser(description="display system data in the i3bar")
|
||||||
|
parser.add_argument("-m", "--modules", nargs="+", help="List of modules to load. The order of the list determines their order in the i3bar (from left to right)", default=[])
|
||||||
|
parser.add_argument("-e", "--events", nargs="+", help="List of click events that should be handled. Format is: <module name><splitter, see -s><button ID><splitter><command to execute>", default=[])
|
||||||
|
parser.add_argument("-l", "--list", action="store_true", help="List all available modules and themes")
|
||||||
|
parser.add_argument("-t", "--theme", help="Specify which theme to use for drawing the modules", default="default")
|
||||||
|
parser.add_argument("-i", "--interval", help="Specify the update interval", default=1, type=int)
|
||||||
|
parser.add_argument("-s", "--split", help="Specify string to use for splitting modules and their arguments", default="::")
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def print_theme_list(self):
|
||||||
|
d = bumblebee.theme.getpath()
|
||||||
|
|
||||||
|
print "available themes:"
|
||||||
|
print textwrap.fill(", ".join(
|
||||||
|
[ os.path.basename(f).replace(".json", "") for f in glob.iglob("{}/*.json".format(d)) ]),
|
||||||
|
80, initial_indent = " ", subsequent_indent = " "
|
||||||
|
)
|
||||||
|
|
||||||
|
def print_module_list(self):
|
||||||
|
print "available modules:"
|
||||||
|
path = os.path.dirname(bumblebee.modules.__file__)
|
||||||
|
for mod in [ name for _, name, _ in pkgutil.iter_modules([path])]:
|
||||||
|
m = importlib.import_module("bumblebee.modules.{}".format(mod))
|
||||||
|
|
||||||
|
desc = "n/a" if not hasattr(m, "description") else getattr(m, "description")()
|
||||||
|
usage = "n/a" if not hasattr(m, "usage") else getattr(m, "usage")()
|
||||||
|
notes = "n/a" if not hasattr(m, "notes") else getattr(m, "notes")()
|
||||||
|
|
||||||
|
print " {}: ".format(mod)
|
||||||
|
print textwrap.fill("Description: {}".format(desc),
|
||||||
|
80, initial_indent=" ", subsequent_indent=" ")
|
||||||
|
print textwrap.fill("Usage : {}".format(usage),
|
||||||
|
80, initial_indent=" ", subsequent_indent=" ")
|
||||||
|
print textwrap.fill("Notes : {}".format(notes),
|
||||||
|
80, initial_indent=" ", subsequent_indent=" ")
|
||||||
|
print ""
|
||||||
|
|
||||||
|
class Engine:
|
||||||
|
def __init__(self, args, theme, output):
|
||||||
|
self._modules = []
|
||||||
|
self._output = output
|
||||||
|
self._args = args
|
||||||
|
self._theme = theme
|
||||||
|
|
||||||
|
def load_module(self, modulespec):
|
||||||
|
name = modulespec.split(self._args.split)[0]
|
||||||
|
args = None if name == modulespec else modulespec.split(self._args.split)[1:]
|
||||||
|
module = importlib.import_module("bumblebee.modules.{}".format(name))
|
||||||
|
return getattr(module, "Module")(self._output, args)
|
||||||
|
|
||||||
|
def load_modules(self):
|
||||||
|
for m in self._args.modules:
|
||||||
|
self._modules.append(self.load_module(m))
|
||||||
|
|
||||||
|
def register_event(self, eventspec):
|
||||||
|
event = eventspec.split(self._args.split)
|
||||||
|
if len(event) < 3:
|
||||||
|
raise Exception("invalid click event format, expected 3 parameters")
|
||||||
|
self._output.add_callback(
|
||||||
|
module = event[0],
|
||||||
|
button = int(event[1]),
|
||||||
|
cmd = event[2],
|
||||||
|
)
|
||||||
|
|
||||||
|
def register_events(self):
|
||||||
|
for e in self._args.events:
|
||||||
|
self.register_event(e)
|
||||||
|
pass
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
print self._output.start()
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
refresh = threading.Condition()
|
||||||
|
refresh.acquire()
|
||||||
|
while True:
|
||||||
|
# improve this
|
||||||
|
self._theme.reset()
|
||||||
|
for m in self._modules:
|
||||||
|
self._output.add(m, self._theme)
|
||||||
|
self._theme.next()
|
||||||
|
print self._output.get()
|
||||||
|
sys.stdout.flush()
|
||||||
|
refresh.wait(self._args.interval)
|
||||||
|
|
||||||
|
print self._output.stop()
|
||||||
|
|
||||||
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
@ -1,11 +1,10 @@
|
||||||
|
|
||||||
class Output(object):
|
class Output(object):
|
||||||
def __init__(self, refresh, theme):
|
def __init__(self, args):
|
||||||
self._theme = theme
|
|
||||||
self._refresh = refresh
|
|
||||||
self._callbacks = {}
|
self._callbacks = {}
|
||||||
|
|
||||||
def redraw(self):
|
def redraw(self):
|
||||||
|
pass
|
||||||
self._refresh.acquire()
|
self._refresh.acquire()
|
||||||
self._refresh.notify()
|
self._refresh.notify()
|
||||||
self._refresh.release()
|
self._refresh.release()
|
||||||
|
@ -30,13 +29,10 @@ class Output(object):
|
||||||
), None)
|
), None)
|
||||||
return cb
|
return cb
|
||||||
|
|
||||||
def theme(self):
|
|
||||||
return self._theme
|
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def add(self, obj):
|
def add(self, obj, theme):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
|
|
|
@ -27,9 +27,9 @@ def read_input(output):
|
||||||
subprocess.Popen(shlex.split(cb), stdout=DEVNULL, stderr=DEVNULL)
|
subprocess.Popen(shlex.split(cb), stdout=DEVNULL, stderr=DEVNULL)
|
||||||
output.redraw()
|
output.redraw()
|
||||||
|
|
||||||
class i3bar(bumblebee.output.Output):
|
class Output(bumblebee.output.Output):
|
||||||
def __init__(self, refresh, theme):
|
def __init__(self, args):
|
||||||
super(i3bar, self).__init__(refresh, theme)
|
super(Output, self).__init__(args)
|
||||||
self._data = []
|
self._data = []
|
||||||
|
|
||||||
self.add_callback("i3-msg workspace prev_on_output", 4)
|
self.add_callback("i3-msg workspace prev_on_output", 4)
|
||||||
|
@ -41,8 +41,7 @@ class i3bar(bumblebee.output.Output):
|
||||||
def start(self):
|
def start(self):
|
||||||
return json.dumps({ "version": 1, "click_events": True }) + "["
|
return json.dumps({ "version": 1, "click_events": True }) + "["
|
||||||
|
|
||||||
def add(self, obj):
|
def add(self, obj, theme):
|
||||||
theme = self.theme()
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
d = obj.data()
|
d = obj.data()
|
||||||
|
|
|
@ -7,10 +7,10 @@ def getpath():
|
||||||
class Theme:
|
class Theme:
|
||||||
_cycle_index = 0
|
_cycle_index = 0
|
||||||
_cycle = None
|
_cycle = None
|
||||||
def __init__(self, name="default"):
|
def __init__(self, args):
|
||||||
self._data = None
|
self._data = None
|
||||||
path = os.path.dirname(os.path.realpath(__file__))
|
path = os.path.dirname(os.path.realpath(__file__))
|
||||||
with open("{}/{}.json".format(getpath(), name)) as f:
|
with open("{}/{}.json".format(getpath(), args.theme)) as f:
|
||||||
self._data = json.load(f)
|
self._data = json.load(f)
|
||||||
self._defaults = self._data.get("defaults", {})
|
self._defaults = self._data.get("defaults", {})
|
||||||
self._cycle = self._defaults.get("cycle", [])
|
self._cycle = self._defaults.get("cycle", [])
|
||||||
|
|
Loading…
Reference in a new issue