From a8a6c9bba2d5719e80d49f2eac215419e412af24 Mon Sep 17 00:00:00 2001 From: Tobi-wan Kenobi Date: Sat, 3 Dec 2016 20:38:54 +0100 Subject: [PATCH] [core] Refactor engine This is going to be a bit more comprehensive than anticipated. In order to cleanly refactor the core and the engine, basically start from scratch with the implementation. Goals: * Test coverage * Maintain backwards compatibility with module interface as much as possible (but still make modules easier to code) * Simplicity see #23 --- README.md | 82 ------------- bin/customupdates | 21 ---- bin/load-i3-bars.sh | 26 ---- bin/toggle-display.sh | 12 -- bumblebee-status | 18 --- bumblebee/config.py | 120 ++---------------- bumblebee/engine.py | 38 ------ bumblebee/module.py | 61 ---------- bumblebee/modules/__init__.py | 0 bumblebee/modules/battery.py | 52 -------- bumblebee/modules/brightness.py | 33 ----- bumblebee/modules/caffeine.py | 38 ------ bumblebee/modules/cmus.py | 78 ------------ bumblebee/modules/cpu.py | 30 ----- bumblebee/modules/date.py | 1 - bumblebee/modules/datetime.py | 1 - bumblebee/modules/disk.py | 40 ------ bumblebee/modules/dnf.py | 98 --------------- bumblebee/modules/layout.py | 67 ----------- bumblebee/modules/load.py | 37 ------ bumblebee/modules/memory.py | 38 ------ bumblebee/modules/nic.py | 62 ---------- bumblebee/modules/pacman.py | 58 --------- bumblebee/modules/pasink.py | 1 - bumblebee/modules/pasource.py | 1 - bumblebee/modules/ping.py | 97 --------------- bumblebee/modules/pulseaudio.py | 92 -------------- bumblebee/modules/spacer.py | 17 --- bumblebee/modules/time.py | 34 ------ bumblebee/modules/xrandr.py | 89 -------------- bumblebee/output.py | 121 ------------------- bumblebee/outputs/__init__.py | 0 bumblebee/outputs/i3.py | 76 ------------ bumblebee/theme.py | 129 -------------------- bumblebee/util.py | 33 ----- screenshots/battery.png | Bin 1733 -> 0 bytes screenshots/brightness.png | Bin 1323 -> 0 bytes screenshots/caffeine.png | Bin 1143 -> 0 bytes screenshots/cmus.png | Bin 5031 -> 0 bytes screenshots/cpu.png | Bin 1811 -> 0 bytes screenshots/date.png | Bin 2877 -> 0 bytes screenshots/datetime.png | Bin 4889 -> 0 bytes screenshots/disk.png | Bin 3721 -> 0 bytes screenshots/dnf.png | Bin 1113 -> 0 bytes screenshots/load.png | Bin 2005 -> 0 bytes screenshots/memory.png | Bin 3603 -> 0 bytes screenshots/nic.png | Bin 2474 -> 0 bytes screenshots/pacman.png | Bin 860 -> 0 bytes screenshots/pasink.png | Bin 1486 -> 0 bytes screenshots/pasource.png | Bin 1505 -> 0 bytes screenshots/ping.png | Bin 1655 -> 0 bytes screenshots/pulseaudio.png | Bin 2495 -> 0 bytes screenshots/spacer.png | Bin 521 -> 0 bytes screenshots/themes/default.png | Bin 7251 -> 0 bytes screenshots/themes/powerline-gruvbox.png | Bin 11594 -> 0 bytes screenshots/themes/powerline-solarized.png | Bin 11991 -> 0 bytes screenshots/themes/powerline.png | Bin 10701 -> 0 bytes screenshots/themes/solarized.png | Bin 9612 -> 0 bytes screenshots/time.png | Bin 2456 -> 0 bytes screenshots/xrandr.png | Bin 2693 -> 0 bytes tests/__init__.py | 0 tests/modules/__init__.py | 0 tests/modules/test_cpu.py | 26 ---- tests/test_config.py | 14 ++- themes/default.json | 7 -- themes/gruvbox-powerline.json | 44 ------- themes/icons/ascii.json | 119 ------------------ themes/icons/awesome-fonts.json | 134 --------------------- themes/icons/paxy97.json | 5 - themes/powerline.json | 41 ------- themes/solarized-powerline.json | 42 ------- themes/solarized.json | 41 ------- 72 files changed, 19 insertions(+), 2155 deletions(-) delete mode 100644 README.md delete mode 100755 bin/customupdates delete mode 100755 bin/load-i3-bars.sh delete mode 100755 bin/toggle-display.sh mode change 100755 => 100644 bumblebee-status delete mode 100644 bumblebee/engine.py delete mode 100644 bumblebee/module.py delete mode 100644 bumblebee/modules/__init__.py delete mode 100644 bumblebee/modules/battery.py delete mode 100644 bumblebee/modules/brightness.py delete mode 100644 bumblebee/modules/caffeine.py delete mode 100644 bumblebee/modules/cmus.py delete mode 100644 bumblebee/modules/cpu.py delete mode 120000 bumblebee/modules/date.py delete mode 120000 bumblebee/modules/datetime.py delete mode 100644 bumblebee/modules/disk.py delete mode 100644 bumblebee/modules/dnf.py delete mode 100644 bumblebee/modules/layout.py delete mode 100644 bumblebee/modules/load.py delete mode 100644 bumblebee/modules/memory.py delete mode 100644 bumblebee/modules/nic.py delete mode 100644 bumblebee/modules/pacman.py delete mode 120000 bumblebee/modules/pasink.py delete mode 120000 bumblebee/modules/pasource.py delete mode 100644 bumblebee/modules/ping.py delete mode 100644 bumblebee/modules/pulseaudio.py delete mode 100644 bumblebee/modules/spacer.py delete mode 100644 bumblebee/modules/time.py delete mode 100644 bumblebee/modules/xrandr.py delete mode 100644 bumblebee/output.py delete mode 100644 bumblebee/outputs/__init__.py delete mode 100644 bumblebee/outputs/i3.py delete mode 100644 bumblebee/theme.py delete mode 100644 bumblebee/util.py delete mode 100644 screenshots/battery.png delete mode 100644 screenshots/brightness.png delete mode 100644 screenshots/caffeine.png delete mode 100644 screenshots/cmus.png delete mode 100644 screenshots/cpu.png delete mode 100644 screenshots/date.png delete mode 100644 screenshots/datetime.png delete mode 100644 screenshots/disk.png delete mode 100644 screenshots/dnf.png delete mode 100644 screenshots/load.png delete mode 100644 screenshots/memory.png delete mode 100644 screenshots/nic.png delete mode 100644 screenshots/pacman.png delete mode 100644 screenshots/pasink.png delete mode 100644 screenshots/pasource.png delete mode 100644 screenshots/ping.png delete mode 100644 screenshots/pulseaudio.png delete mode 100644 screenshots/spacer.png delete mode 100644 screenshots/themes/default.png delete mode 100644 screenshots/themes/powerline-gruvbox.png delete mode 100644 screenshots/themes/powerline-solarized.png delete mode 100644 screenshots/themes/powerline.png delete mode 100644 screenshots/themes/solarized.png delete mode 100644 screenshots/time.png delete mode 100644 screenshots/xrandr.png delete mode 100644 tests/__init__.py delete mode 100644 tests/modules/__init__.py delete mode 100644 tests/modules/test_cpu.py delete mode 100644 themes/default.json delete mode 100644 themes/gruvbox-powerline.json delete mode 100644 themes/icons/ascii.json delete mode 100644 themes/icons/awesome-fonts.json delete mode 100644 themes/icons/paxy97.json delete mode 100644 themes/powerline.json delete mode 100644 themes/solarized-powerline.json delete mode 100644 themes/solarized.json diff --git a/README.md b/README.md deleted file mode 100644 index d039179..0000000 --- a/README.md +++ /dev/null @@ -1,82 +0,0 @@ -# bumblebee-status - -bumblebee-status is a modular, theme-able status line generator for the [i3 window manager](https://i3wm.org/). - -Focus is on: -* Ease of use (no configuration files!) -* Theme support -* Extensibility (of course...) - -I hope you like it and appreciate any kind of feedback: Bug reports, Feature requests, etc. :) - -Thanks a lot! - -# Documentation -See [the wiki](https://github.com/tobi-wan-kenobi/bumblebee-status/wiki) for documentation. - -Other resources: - -* A list of [available modules](https://github.com/tobi-wan-kenobi/bumblebee-status/wiki/Available-Modules) -* [How to write a theme](https://github.com/tobi-wan-kenobi/bumblebee-status/wiki/How-to-write-a-theme) -* [How to write a module](https://github.com/tobi-wan-kenobi/bumblebee-status/wiki/How-to-write-a-module) - -# Installation -``` -$ git clone git://github.com/tobi-wan-kenobi/bumblebee-status -``` - -# Usage - -Next, open your i3wm configuration and modify the *status_command* for your i3bar like this: - -``` -bar { - status_command = -m -p -t -} -``` - -You can retrieve a list of modules and themes by entering: -``` -$ cd bumblebee-status -$ ./bumblebee-status -l themes -$ ./bumblebee-status -l modules -``` - -As a simple example, this is what my i3 configuration looks like: - -``` -bar { - font pango:Inconsolata 10 - position top - tray_output none - status_command ~/.i3/bumblebee-status/bumblebee-status -m nic disk:/ cpu memory battery date time pasink pasource dnf -p time.format="%H:%M CW %V" date.format="%a, %b %d %Y" -t solarized-powerline -} - -``` - - -Restart i3wm and - that's it! - - -# Examples -Here are some screenshots for all themes that currently exist: - -Gruvbox Powerline (`-t gruvbox-powerline`) (contributed by [@paxy97](https://github.com/paxy97)): - -![Gruvbox Powerline](https://github.com/tobi-wan-kenobi/bumblebee-status/blob/master/screenshots/themes/powerline-gruvbox.png) - -Solarized Powerline (`-t solarized-powerline`): - -![Solarized Powerline](https://github.com/tobi-wan-kenobi/bumblebee-status/blob/master/screenshots/themes/powerline-solarized.png) - -Solarized (`-t solarized`): - -![Solarized](https://github.com/tobi-wan-kenobi/bumblebee-status/blob/master/screenshots/themes/solarized.png) - -Powerline (`-t powerline`): - -![Powerline](https://github.com/tobi-wan-kenobi/bumblebee-status/blob/master/screenshots/themes/powerline.png) - -Default (nothing or `-t default`): - -![Default](https://github.com/tobi-wan-kenobi/bumblebee-status/blob/master/screenshots/themes/default.png) diff --git a/bin/customupdates b/bin/customupdates deleted file mode 100755 index 3176c9d..0000000 --- a/bin/customupdates +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/bash -if ! type -P fakeroot >/dev/null; then - error 'Cannot find the fakeroot binary.' - exit 1 -fi - -if [[ -z $CHECKUPDATES_DB ]]; then - CHECKUPDATES_DB="${TMPDIR:-/tmp}/checkup-db-${USER}/" -fi - -trap 'rm -f $CHECKUPDATES_DB/db.lck' INT TERM EXIT - -DBPath="${DBPath:-/var/lib/pacman/}" -eval $(awk -F' *= *' '$1 ~ /DBPath/ { print $1 "=" $2 }' /etc/pacman.conf) - -mkdir -p "$CHECKUPDATES_DB" -ln -s "${DBPath}/local" "$CHECKUPDATES_DB" &> /dev/null -fakeroot -- pacman -Sy --dbpath "$CHECKUPDATES_DB" --logfile /dev/null &> /dev/null -fakeroot pacman -Su -p --dbpath "$CHECKUPDATES_DB" - -exit 0 diff --git a/bin/load-i3-bars.sh b/bin/load-i3-bars.sh deleted file mode 100755 index cbe0e95..0000000 --- a/bin/load-i3-bars.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash - -if [ ! -f ~/.i3/config.template ]; then - cp ~/.i3/config ~/.i3/config.template -else - cp ~/.i3/config.template ~/.i3/config -fi - -screens=$(xrandr -q|grep ' connected'| grep -P '\d+x\d+' |cut -d' ' -f1) - -echo "screens: $screens" - -while read -r line; do - screen=$(echo $line | cut -d' ' -f1) - others=$(echo $screens|tr ' ' '\n'|grep -v $screen|tr '\n' '-'|sed 's/.$//') - - if [ -f ~/.i3/config.$screen-$others ]; then - cat ~/.i3/config.$screen-$others >> ~/.i3/config - else - if [ -f ~/.i3/config.$screen ]; then - cat ~/.i3/config.$screen >> ~/.i3/config - fi - fi -done <<< "$screens" - -i3-msg restart diff --git a/bin/toggle-display.sh b/bin/toggle-display.sh deleted file mode 100755 index bd13a29..0000000 --- a/bin/toggle-display.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -echo $(dirname $(readlink -f "$0")) - -i3bar_update=$(dirname $(readlink -f "$0"))/load-i3-bars.sh - -xrandr "$@" - -if [ -f $i3bar_update ]; then - sleep 1 - $i3bar_update -fi diff --git a/bumblebee-status b/bumblebee-status old mode 100755 new mode 100644 index 42258a4..e69de29 --- a/bumblebee-status +++ b/bumblebee-status @@ -1,18 +0,0 @@ -#!/usr/bin/env python - -import sys -import bumblebee.config -import bumblebee.engine - -def main(): - config = bumblebee.config.Config(sys.argv[1:]) - - engine = bumblebee.engine.Engine(config) - engine.load_modules() - - engine.run() - -if __name__ == "__main__": - main() - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/config.py b/bumblebee/config.py index 49005ad..d9c9419 100644 --- a/bumblebee/config.py +++ b/bumblebee/config.py @@ -1,123 +1,19 @@ -import os import argparse -import textwrap -import bumblebee.theme -import bumblebee.module - -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 = " "*4 - - def __call__(self, parser, namespace, value, option_string=None): - if value == "modules": - self.print_modules() - elif value == "themes": - self.print_themes() - else: - parser.print_help() - parser.exit() - - def print_themes(self): - print(textwrap.fill(", ".join(bumblebee.theme.themes()), - 80, initial_indent = self._indent, subsequent_indent = self._indent - )) - - def print_modules(self): - for m in bumblebee.module.modules(): - print(textwrap.fill("{}: {}".format(m.name(), m.description()), - 80, initial_indent=self._indent*2, subsequent_indent=self._indent*3)) - print("{}Parameters:".format(self._indent*2)) - for p in m.parameters(): - print(textwrap.fill("* {}".format(p), - 80, initial_indent=self._indent*3, subsequent_indent=self._indent*4)) - print("") - -class ModuleConfig(object): - def __init__(self, config, name, alias): - self._prefix = alias if alias else name - self._config = config - - def prefix(self): - return self._prefix - - def set(self, name, value): - name = self._prefix + name - return self._config.set(name, value) - - def parameter(self, name, default=None): - name = self._prefix + name - return self._config.parameter(name, default) - - def increase(self, name, limit, default): - name = self._prefix + name - return self._config.increase(name, limit, default) +MODULE_HELP = "" class Config(object): - def __init__(self, args): - self._parser = self._parser() - self._store = {} - - if len(args) == 0: - self._parser.print_help() - self._parser.exit() - - self._args = self._parser.parse_args(args) - - for p in self._args.parameters: - key, value = p.split("=") - self.parameter(key, value) - - def set(self, name, value): - self._store[name] = value - - def parameter(self, name, default=None): - if not name in self._store: - self.set(name, default) - return self._store.get(name, default) - - def increase(self, name, limit, default): - if not name in self._store: - self._store[name] = default - return default - - self._store[name] += 1 - if self._store[name] >= limit: - self._store[name] = default - return self._store[name] - - def theme(self): - return self._args.theme + def __init__(self, args = []): + parser = self._create_parser() + self._args = parser.parse_args(args) def modules(self): - result = [] - for m in self._args.modules: - items = m.split(":") - result.append({ "name": items[0], "alias": items[1] if len(items) > 1 else None }) - return result + return map(lambda x: { "name": x, "module": x }, self._args.modules) - def _parser(self): + 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("-l", "--list", - help="List: 'modules', 'themes' ", - choices = [ "modules", "themes" ], - action=print_usage, - ) - parser.add_argument("-p", "--parameters", nargs="+", - help="Provide configuration parameters to individual modules.", - default=[] - ) - parser.add_argument("-t", "--theme", help="Specify which theme to use for " - "drawing the modules", - default="default", - ) - + parser.add_argument("-m", "--modules", nargs="+", default = [], + help = MODULE_HELP) return parser # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/engine.py b/bumblebee/engine.py deleted file mode 100644 index cc0b7b9..0000000 --- a/bumblebee/engine.py +++ /dev/null @@ -1,38 +0,0 @@ -import importlib -import bumblebee.theme -import bumblebee.output -import bumblebee.config -import bumblebee.modules - -class Engine: - def __init__(self, config): - self._modules = [] - self._config = config - self._theme = bumblebee.theme.Theme(config) - self._output = bumblebee.output.output(config) - - def load_module(self, modulespec): - name = modulespec["name"] - module = importlib.import_module("bumblebee.modules.{}".format(name)) - cfg = bumblebee.config.ModuleConfig(self._config, name, modulespec["alias"]) - obj = getattr(module, "Module")(self._output, cfg) - obj.register_callbacks() - return obj - - def load_modules(self): - for m in self._config.modules(): - self._modules.append(self.load_module(m)) - - def run(self): - self._output.start() - - while True: - self._theme.begin() - for m in self._modules: - self._output.draw(m.widgets(), self._theme) - self._output.flush() - self._output.wait() - - self._output.stop() - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/module.py b/bumblebee/module.py deleted file mode 100644 index 0f497a2..0000000 --- a/bumblebee/module.py +++ /dev/null @@ -1,61 +0,0 @@ -import os -import pkgutil -import importlib - -import bumblebee.modules - -def modules(): - result = [] - path = os.path.dirname(bumblebee.modules.__file__) - for mod in [ name for _, name, _ in pkgutil.iter_modules([path])]: - result.append(ModuleDescription(mod)) - return result - -class ModuleDescription(object): - def __init__(self, name): - self._name = name - self._mod =importlib.import_module("bumblebee.modules.{}".format(name)) - - def name(self): - return str(self._name) - - def description(self): - return getattr(self._mod, "description", lambda: "n/a")() - - def parameters(self): - return getattr(self._mod, "parameters", lambda: [ "n/a" ])() - -class Module(object): - def __init__(self, output, config): - self._output = output - self._config = config - - def register_callbacks(self): - buttons = [ - { "name": "left-click", "id": 1 }, - { "name": "middle-click", "id": 2 }, - { "name": "right-click", "id": 3 }, - { "name": "wheel-up", "id": 4 }, - { "name": "wheel-down", "id": 5 }, - ] - for button in buttons: - if self._config.parameter(button["name"], None): - output.add_callback( - module=self.instance(), - button=button["id"], - cmd=self._config.parameter(button["name"]) - ) - - def critical(self, widget): - return False - - def warning(self, widget): - return False - - def state(self, widget): - return "default" - - def instance(self, widget=None): - return self._config.prefix() - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/modules/__init__.py b/bumblebee/modules/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/bumblebee/modules/battery.py b/bumblebee/modules/battery.py deleted file mode 100644 index 8215693..0000000 --- a/bumblebee/modules/battery.py +++ /dev/null @@ -1,52 +0,0 @@ -import datetime -import bumblebee.module -import os.path - -def description(): - return "Displays battery status, percentage and whether it's charging or discharging." - -def parameters(): - return [ "battery.device: The device to read from (defaults to BAT0)" ] - -class Module(bumblebee.module.Module): - def __init__(self, output, config): - super(Module, self).__init__(output, config) - self._battery = config.parameter("device", "BAT0") - self._capacity = 100 - self._status = "Unknown" - - def widgets(self): - self._AC = False; - self._path = "/sys/class/power_supply/{}".format(self._battery) - if not os.path.exists(self._path): - self._AC = True; - return bumblebee.output.Widget(self,"AC") - - with open(self._path + "/capacity") as f: - self._capacity = int(f.read()) - self._capacity = self._capacity if self._capacity < 100 else 100 - - return bumblebee.output.Widget(self,"{:02d}%".format(self._capacity)) - - def warning(self, widget): - return self._capacity < self._config.parameter("warning", 20) - - def critical(self, widget): - return self._capacity < self._config.parameter("critical", 10) - - def state(self, widget): - if self._AC: - return "AC" - - with open(self._path + "/status") as f: - self._status = f.read().strip() - - if self._status == "Discharging": - status = "discharging-{}".format(min([ 10, 25, 50, 80, 100] , key=lambda i:abs(i-self._capacity))) - return status - else: - if self._capacity > 95: - return "charged" - return "charging" - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/modules/brightness.py b/bumblebee/modules/brightness.py deleted file mode 100644 index 9227ce8..0000000 --- a/bumblebee/modules/brightness.py +++ /dev/null @@ -1,33 +0,0 @@ -import bumblebee.module - -def description(): - return "Displays brightness percentage" - -def parameters(): - return [ - "brightness.step: Steps (in percent) to increase/decrease brightness on scroll (defaults to 2)", - ] - -class Module(bumblebee.module.Module): - def __init__(self, output, config): - super(Module, self).__init__(output, config) - self._brightness = 0 - self._max = 0 - self._percent = 0 - - step = self._config.parameter("step", 2) - - output.add_callback(module=self.instance(), button=4, cmd="xbacklight +{}%".format(step)) - output.add_callback(module=self.instance(), button=5, cmd="xbacklight -{}%".format(step)) - - def widgets(self): - with open("/sys/class/backlight/intel_backlight/brightness") as f: - self._brightness = int(f.read()) - with open("/sys/class/backlight/intel_backlight/max_brightness") as f: - self._max = int(f.read()) - self._brightness = self._brightness if self._brightness < self._max else self._max - self._percent = int(round(self._brightness * 100 / self._max)) - - return bumblebee.output.Widget(self, "{:02d}%".format(self._percent)) - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/modules/caffeine.py b/bumblebee/modules/caffeine.py deleted file mode 100644 index d7c2dad..0000000 --- a/bumblebee/modules/caffeine.py +++ /dev/null @@ -1,38 +0,0 @@ -import subprocess -import shlex - -import bumblebee.module - -def description(): - return "Enable/disable auto screen lock." - -class Module(bumblebee.module.Module): - def __init__(self, output, config): - super(Module, self).__init__(output, config) - self._activated = 0 - output.add_callback(module="caffeine.activate", button=1, cmd=[ 'notify-send "Consuming caffeine"', 'xset s off' ]) - output.add_callback(module="caffeine.deactivate", button=1, cmd=[ 'notify-send "Out of coffee"', 'xset s default' ]) - - def widgets(self): - output = subprocess.check_output(shlex.split("xset q")) - xset_out = output.decode().split("\n") - for line in xset_out: - if line.startswith(" timeout"): - timeout = int(line.split(" ")[4]) - if timeout == 0: - self._activated = 1; - else: - self._activated = 0; - break - - if self._activated == 0: - return bumblebee.output.Widget(self, "", instance="caffeine.activate") - elif self._activated == 1: - return bumblebee.output.Widget(self, "", instance="caffeine.deactivate") - - def state(self, widget): - if self._activated == 1: - return "activated" - else: - return "deactivated" - diff --git a/bumblebee/modules/cmus.py b/bumblebee/modules/cmus.py deleted file mode 100644 index de42ecf..0000000 --- a/bumblebee/modules/cmus.py +++ /dev/null @@ -1,78 +0,0 @@ -import string -import datetime -import subprocess -from collections import defaultdict - -import bumblebee.util -import bumblebee.module - -def description(): - return "Displays the current song and artist playing in cmus" - -def parameters(): - return [ - "cmus.format: Format of the displayed song information, arbitrary tags (as available from cmus-remote -Q) can be used (defaults to {artist} - {title} {position}/{duration})" - ] - -class Module(bumblebee.module.Module): - def __init__(self, output, config): - super(Module, self).__init__(output, config) - self._status = "default" - self._fmt = self._config.parameter("format", "{artist} - {title} {position}/{duration}") - - output.add_callback(module="cmus.prev", button=1, cmd="cmus-remote -r") - output.add_callback(module="cmus.next", button=1, cmd="cmus-remote -n") - output.add_callback(module="cmus.shuffle", button=1, cmd="cmus-remote -S") - output.add_callback(module="cmus.repeat", button=1, cmd="cmus-remote -R") - output.add_callback(module=self.instance(), button=1, cmd="cmus-remote -u") - - def _loadsong(self): - process = subprocess.Popen(["cmus-remote", "-Q"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - self._query, self._error = process.communicate() - self._query = self._query.decode("utf-8").split("\n") - self._status = "default" - - def _tags(self): - tags = defaultdict(lambda: '') - self._repeat = False - self._shuffle = False - for line in self._query: - if line.startswith("status"): - status = line.split(" ", 2)[1] - self._status = status - if line.startswith("tag"): - key, value = line.split(" ", 2)[1:] - tags.update({ key: value }) - if line.startswith("duration"): - sec = line.split(" ")[1] - tags.update({ "duration": bumblebee.util.durationfmt(int(sec)) }) - if line.startswith("position"): - sec = line.split(" ")[1] - tags.update({ "position": bumblebee.util.durationfmt(int(sec)) }) - if line.startswith("set repeat "): - self._repeat = False if line.split(" ")[2] == "false" else True - if line.startswith("set shuffle "): - self._shuffle = False if line.split(" ")[2] == "false" else True - - return tags - - def widgets(self): - self._loadsong() - tags = self._tags() - - return [ - bumblebee.output.Widget(self, "", instance="cmus.prev"), - bumblebee.output.Widget(self, string.Formatter().vformat(self._fmt, (), tags)), - bumblebee.output.Widget(self, "", instance="cmus.next"), - bumblebee.output.Widget(self, "", instance="cmus.shuffle"), - bumblebee.output.Widget(self, "", instance="cmus.repeat"), - ] - - def state(self, widget): - if widget.instance() == "cmus.shuffle": - return "on" if self._shuffle else "off" - if widget.instance() == "cmus.repeat": - return "on" if self._repeat else "off" - return self._status - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/modules/cpu.py b/bumblebee/modules/cpu.py deleted file mode 100644 index 619019b..0000000 --- a/bumblebee/modules/cpu.py +++ /dev/null @@ -1,30 +0,0 @@ -import bumblebee.module -import psutil - -def description(): - return "Displays CPU utilization across all CPUs." - -def parameters(): - return [ - "cpu.warning: Warning threshold in % of disk usage (defaults to 70%)", - "cpu.critical: Critical threshold in % of disk usage (defaults to 80%)", - ] - -class Module(bumblebee.module.Module): - def __init__(self, output, config): - super(Module, self).__init__(output, config) - self._perc = psutil.cpu_percent(percpu=False) - - output.add_callback(module=self.instance(), button=1, cmd="gnome-system-monitor") - - def widgets(self): - self._perc = psutil.cpu_percent(percpu=False) - return bumblebee.output.Widget(self, "{:05.02f}%".format(self._perc)) - - def warning(self, widget): - return self._perc > self._config.parameter("warning", 70) - - def critical(self, widget): - return self._perc > self._config.parameter("critical", 80) - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/modules/date.py b/bumblebee/modules/date.py deleted file mode 120000 index bde6404..0000000 --- a/bumblebee/modules/date.py +++ /dev/null @@ -1 +0,0 @@ -datetime.py \ No newline at end of file diff --git a/bumblebee/modules/datetime.py b/bumblebee/modules/datetime.py deleted file mode 120000 index 5a370f9..0000000 --- a/bumblebee/modules/datetime.py +++ /dev/null @@ -1 +0,0 @@ -time.py \ No newline at end of file diff --git a/bumblebee/modules/disk.py b/bumblebee/modules/disk.py deleted file mode 100644 index 67a79e1..0000000 --- a/bumblebee/modules/disk.py +++ /dev/null @@ -1,40 +0,0 @@ -import os -import bumblebee.util -import bumblebee.module - -def description(): - return "Shows free diskspace, total diskspace and the percentage of free disk space." - -def parameters(): - return [ - "disk.warning: Warning threshold in % (defaults to 80%)", - "disk.critical: Critical threshold in % (defaults to 90%)" - ] - -class Module(bumblebee.module.Module): - def __init__(self, output, config): - super(Module, self).__init__(output, config) - self._path = self._config.parameter("path", "/") - - output.add_callback(module=self.instance(), button=1, cmd="nautilus {}".format(self._path)) - - def widgets(self): - st = os.statvfs(self._path) - - self._size = st.f_frsize*st.f_blocks - self._used = self._size - st.f_frsize*st.f_bavail - self._perc = 100.0*self._used/self._size - - return bumblebee.output.Widget(self, - "{} {}/{} ({:05.02f}%)".format(self._path, - bumblebee.util.bytefmt(self._used), - bumblebee.util.bytefmt(self._size), self._perc) - ) - - def warning(self, widget): - return self._perc > self._config.parameter("warning", 80) - - def critical(self, widget): - return self._perc > self._config.parameter("critical", 90) - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/modules/dnf.py b/bumblebee/modules/dnf.py deleted file mode 100644 index 4101a8c..0000000 --- a/bumblebee/modules/dnf.py +++ /dev/null @@ -1,98 +0,0 @@ -from __future__ import absolute_import - -import time -import shlex -import threading -import subprocess - -import bumblebee.module -import bumblebee.util - -def description(): - return "Checks DNF for updated packages and displays the number of /// pending updates." - -def parameters(): - return [ "dnf.interval: Time in seconds between two checks for updates (defaults to 1800)" ] - -def get_dnf_info(obj): - loops = obj.interval() - - for thread in threading.enumerate(): - if thread.name == "MainThread": - main = thread - - while main.is_alive(): - loops += 1 - if loops < obj.interval(): - time.sleep(1) - continue - - loops = 0 - try: - res = subprocess.check_output(shlex.split("dnf updateinfo")) - except Exception as e: - break - - security = 0 - bugfixes = 0 - enhancements = 0 - other = 0 - for line in res.decode().split("\n"): - - if not line.startswith(" "): continue - elif "ecurity" in line: - for s in line.split(): - if s.isdigit(): security += int(s) - elif "ugfix" in line: - for s in line.split(): - if s.isdigit(): bugfixes += int(s) - elif "hancement" in line: - for s in line.split(): - if s.isdigit(): enhancements += int(s) - else: - for s in line.split(): - if s.isdigit(): other += int(s) - - obj.set("security", security) - obj.set("bugfixes", bugfixes) - obj.set("enhancements", enhancements) - obj.set("other", other) - -class Module(bumblebee.module.Module): - def __init__(self, output, config): - super(Module, self).__init__(output, config) - - self._counter = {} - self._thread = threading.Thread(target=get_dnf_info, args=(self,)) - self._thread.start() - - def interval(self): - return self._config.parameter("interval", 30*60) - - def set(self, what, value): - self._counter[what] = value - - def get(self, what): - return self._counter.get(what, 0) - - def widgets(self): - result = [] - for t in [ "security", "bugfixes", "enhancements", "other" ]: - result.append(str(self.get(t))) - - return bumblebee.output.Widget(self, "/".join(result)) - - def state(self, widget): - total = sum(self._counter.values()) - if total == 0: return "good" - return "default" - - def warning(self, widget): - total = sum(self._counter.values()) - return total > 0 - - def critical(self, widget): - total = sum(self._counter.values()) - return total > 50 or self._counter.get("security", 0) > 0 - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/modules/layout.py b/bumblebee/modules/layout.py deleted file mode 100644 index b317655..0000000 --- a/bumblebee/modules/layout.py +++ /dev/null @@ -1,67 +0,0 @@ -import subprocess -import shlex -import bumblebee.module -import bumblebee.util - -def description(): - return "Showws current keyboard layout and change it on click." - -def parameters(): - return [ - "layout.lang: pipe-separated list of languages to cycle through (e.g. us|rs|de). Default: en" - ] - - -class Module(bumblebee.module.Module): - def __init__(self, output, config): - super(Module, self).__init__(output, config) - - self._languages = self._config.parameter("lang", "en").split("|") - self._idx = 0 - - output.add_callback(module=self.instance(), button=1, cmd=self.next_keymap) - output.add_callback(module=self.instance(), button=3, cmd=self.prev_keymap) - - def next_keymap(self, event, widget): - self._idx = self._idx + 1 if self._idx < len(self._languages) - 1 else 0 - self.set_keymap() - - def prev_keymap(self, event, widget): - self._idx = self._idx - 1 if self._idx > 0 else len(self._languages) - 1 - self.set_keymap() - - def set_keymap(self): - tmp = self._languages[self._idx].split(":") - layout = tmp[0] - variant = "" - if len(tmp) > 1: - variant = "-variant {}".format(tmp[1]) - bumblebee.util.execute("setxkbmap -layout {} {}".format(layout, variant)) - - def widgets(self): - res = bumblebee.util.execute("setxkbmap -query") - layout = None - variant = None - for line in res.split("\n"): - if not line: - continue - if "layout" in line: - layout = line.split(":")[1].strip() - if "variant" in line: - variant = line.split(":")[1].strip() - if variant: - layout += ":" + variant - - lang = self._languages[self._idx] - - if lang != layout: - if layout in self._languages: - self._idx = self._languages.index(layout) - else: - self._languages.append(layout) - self._idx = len(self._languages) - 1 - lang = layout - - return bumblebee.output.Widget(self, lang) - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/modules/load.py b/bumblebee/modules/load.py deleted file mode 100644 index aad9dfe..0000000 --- a/bumblebee/modules/load.py +++ /dev/null @@ -1,37 +0,0 @@ -import bumblebee.module -import multiprocessing -import os - -def description(): - return "Displays system load." - -def parameters(): - return [ - "load.warning: Warning threshold for the one-minute load average (defaults to 70% of the number of CPUs)", - "load.critical: Critical threshold for the one-minute load average (defaults 80% of the number of CPUs)" - ] - -class Module(bumblebee.module.Module): - def __init__(self, output, config): - super(Module, self).__init__(output, config) - self._cpus = 1 - try: - self._cpus = multiprocessing.cpu_count() - except multiprocessing.NotImplementedError as e: - pass - - output.add_callback(module=self.instance(), button=1, cmd="gnome-system-monitor") - - def widgets(self): - self._load = os.getloadavg() - - return bumblebee.output.Widget(self, "{:.02f}/{:.02f}/{:.02f}".format( - self._load[0], self._load[1], self._load[2])) - - def warning(self, widget): - return self._load[0] > self._config.parameter("warning", self._cpus*0.7) - - def critical(self, widget): - return self._load[0] > self._config.parameter("critical", self._cpus*0.8) - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/modules/memory.py b/bumblebee/modules/memory.py deleted file mode 100644 index d38ac0f..0000000 --- a/bumblebee/modules/memory.py +++ /dev/null @@ -1,38 +0,0 @@ -import psutil -import bumblebee.module -import bumblebee.util - -def description(): - return "Shows available RAM, total amount of RAM and the percentage of available RAM." - -def parameters(): - return [ - "memory.warning: Warning threshold in % of memory used (defaults to 80%)", - "memory.critical: Critical threshold in % of memory used (defaults to 90%)", - ] - -class Module(bumblebee.module.Module): - def __init__(self, output, config): - super(Module, self).__init__(output, config) - self._mem = psutil.virtual_memory() - - output.add_callback(module=self.instance(), button=1, cmd="gnome-system-monitor") - - def widgets(self): - self._mem = psutil.virtual_memory() - - used = self._mem.total - self._mem.available - - return bumblebee.output.Widget(self, "{}/{} ({:05.02f}%)".format( - bumblebee.util.bytefmt(used), - bumblebee.util.bytefmt(self._mem.total), - self._mem.percent) - ) - - def warning(self, widget): - return self._mem.percent > self._config.parameter("warning", 80) - - def critical(self, widget): - return self._mem.percent > self._config.parameter("critical", 90) - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/modules/nic.py b/bumblebee/modules/nic.py deleted file mode 100644 index 0db9e3a..0000000 --- a/bumblebee/modules/nic.py +++ /dev/null @@ -1,62 +0,0 @@ -import netifaces -import bumblebee.module - -def description(): - return "Displays the names, IP addresses and status of each available interface." - -def parameters(): - return [ - "nic.exclude: Comma-separated list of interface prefixes to exlude (defaults to: \"lo,virbr,docker,vboxnet,veth\")" - ] - -class Module(bumblebee.module.Module): - def __init__(self, output, config): - super(Module, self).__init__(output, config) - self._exclude = tuple(filter(len, self._config.parameter("exclude", "lo,virbr,docker,vboxnet,veth").split(","))) - - def widgets(self): - result = [] - interfaces = [ i for i in netifaces.interfaces() if not i.startswith(self._exclude) ] - for intf in interfaces: - addr = [] - state = "down" - try: - if netifaces.AF_INET in netifaces.ifaddresses(intf): - for ip in netifaces.ifaddresses(intf)[netifaces.AF_INET]: - if "addr" in ip and ip["addr"] != "": - addr.append(ip["addr"]) - state = "up" - except Exception as e: - addr = [] - widget = bumblebee.output.Widget(self, "{} {} {}".format( - intf, state, ", ".join(addr) - )) - widget.set("intf", intf) - widget.set("state", state) - result.append(widget) - - return result - - def _iswlan(self, intf): - # wifi, wlan, wlp, seems to work for me - if intf.startswith("w"): return True - return False - - def _istunnel(self, intf): - return intf.startswith("tun") - - def state(self, widget): - intf = widget.get("intf") - - iftype = "wireless" if self._iswlan(intf) else "wired" - iftype = "tunnel" if self._istunnel(intf) else iftype - - return "{}-{}".format(iftype, widget.get("state")) - - def warning(self, widget): - return widget.get("state") != "up" - - def critical(self, widget): - return widget.get("state") == "down" - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/modules/pacman.py b/bumblebee/modules/pacman.py deleted file mode 100644 index 3ecb5db..0000000 --- a/bumblebee/modules/pacman.py +++ /dev/null @@ -1,58 +0,0 @@ -import bumblebee.module -import subprocess -import os - -def description(): - return "Displays available updates per repository for pacman." - -class Module(bumblebee.module.Module): - def __init__(self, output, config): - super(Module, self).__init__(output, config) - self._count = 0 - - def widgets(self): - path = os.path.dirname(os.path.abspath(__file__)) - if self._count == 0: - self._out = "?/?/?/?" - process = subprocess.Popen([ "{}/../../bin/customupdates".format(path) ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - self._query, self._error = process.communicate() - - if not process.returncode == 0: - self._out = "?/?/?/?" - else: - self._community = 0 - self._core = 0 - self._extra = 0 - self._other = 0 - - for line in self._query.splitlines(): - if line.startswith(b'http'): - if b"community" in line: - self._community += 1 - continue - if b"core" in line: - self._core += 1; - continue - if b"extra" in line: - self._extra += 1 - continue - self._other += 1 - self._out = str(self._core)+"/"+str(self._extra)+"/"+str(self._community)+"/"+str(self._other) - - self._count += 1 - self._count = 0 if self._count > 300 else self._count - return bumblebee.output.Widget(self, "{}".format(self._out)) - - def sumUpdates(self): - return self._core + self._community + self._extra + self._other - - def critical(self, widget): - #return self._sumUpdates(self) - return self.sumUpdates() > 0 - - - - - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/modules/pasink.py b/bumblebee/modules/pasink.py deleted file mode 120000 index 85ea20d..0000000 --- a/bumblebee/modules/pasink.py +++ /dev/null @@ -1 +0,0 @@ -pulseaudio.py \ No newline at end of file diff --git a/bumblebee/modules/pasource.py b/bumblebee/modules/pasource.py deleted file mode 120000 index 85ea20d..0000000 --- a/bumblebee/modules/pasource.py +++ /dev/null @@ -1 +0,0 @@ -pulseaudio.py \ No newline at end of file diff --git a/bumblebee/modules/ping.py b/bumblebee/modules/ping.py deleted file mode 100644 index b523788..0000000 --- a/bumblebee/modules/ping.py +++ /dev/null @@ -1,97 +0,0 @@ -from __future__ import absolute_import - -import re -import time -import shlex -import threading -import subprocess - -import bumblebee.module -import bumblebee.util - -def description(): - return "Periodically checks the RTT of a configurable IP" - -def parameters(): - return [ - "ping.interval: Time in seconds between two RTT checks (defaults to 60)", - "ping.address: IP address to check", - "ping.warning: Threshold for warning state, in seconds (defaults to 1.0)", - "ping.critical: Threshold for critical state, in seconds (defaults to 2.0)", - "ping.timeout: Timeout for waiting for a reply (defaults to 5.0)", - "ping.probes: Number of probes to send (defaults to 5)", - ] - -def get_rtt(obj): - loops = obj.get("interval") - - for thread in threading.enumerate(): - if thread.name == "MainThread": - main = thread - - interval = obj.get("interval") - while main.is_alive(): - loops += 1 - if loops < interval: - time.sleep(1) - continue - - loops = 0 - try: - res = subprocess.check_output(shlex.split("ping -n -q -c {} -W {} {}".format( - obj.get("rtt-probes"), obj.get("rtt-timeout"), obj.get("address") - ))) - obj.set("rtt-unreachable", False) - - for line in res.decode().split("\n"): - if not line.startswith("rtt"): continue - m = re.search(r'([0-9\.]+)/([0-9\.]+)/([0-9\.]+)/([0-9\.]+)\s+(\S+)', line) - - obj.set("rtt-min", float(m.group(1))) - obj.set("rtt-avg", float(m.group(2))) - obj.set("rtt-max", float(m.group(3))) - obj.set("rtt-unit", m.group(5)) - except Exception as e: - obj.set("rtt-unreachable", True) - - -class Module(bumblebee.module.Module): - def __init__(self, output, config): - super(Module, self).__init__(output, config) - - self._counter = {} - - self.set("address", self._config.parameter("address", "8.8.8.8")) - self.set("interval", self._config.parameter("interval", 60)) - self.set("rtt-probes", self._config.parameter("probes", 5)) - self.set("rtt-timeout", self._config.parameter("timeout", 5.0)) - - self._thread = threading.Thread(target=get_rtt, args=(self,)) - self._thread.start() - - def set(self, what, value): - self._counter[what] = value - - def get(self, what): - return self._counter.get(what, 0) - - def widgets(self): - text = "{}: {:.1f}{}".format( - self.get("address"), - self.get("rtt-avg"), - self.get("rtt-unit") - ) - - if self.get("rtt-unreachable"): - text = "{}: unreachable".format(self.get("address")) - - return bumblebee.output.Widget(self, text) - - def warning(self, widget): - return self.get("rtt-avg") > float(self._config.parameter("warning", 1.0))*1000.0 - - def critical(self, widget): - if self.get("rtt-unreachable"): return True - return self.get("rtt-avg") > float(self._config.parameter("critical", 2.0))*1000.0 - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/modules/pulseaudio.py b/bumblebee/modules/pulseaudio.py deleted file mode 100644 index 079e07c..0000000 --- a/bumblebee/modules/pulseaudio.py +++ /dev/null @@ -1,92 +0,0 @@ -import re -import shlex -import subprocess - -import bumblebee.module -import bumblebee.util - -def description(): - module = __name__.split(".")[-1] - if module == "pasink": - return "Shows volume and mute status of the default PulseAudio Sink." - if module == "pasource": - return "Shows volume and mute status of the default PulseAudio Source." - return "See 'pasource'." - -def parameters(): - return [ "none" ] - - -class Module(bumblebee.module.Module): - def __init__(self, output, config): - super(Module, self).__init__(output, config) - - self._module = self.__module__.split(".")[-1] - self._left = 0 - self._right = 0 - self._mono = 0 - self._mute = False - channel = "sink" if self._module == "pasink" else "source" - - output.add_callback(module=self.instance(), button=3, - cmd="pavucontrol") - output.add_callback(module=self.instance(), button=1, - cmd="pactl set-{}-mute @DEFAULT_{}@ toggle".format(channel, channel.upper())) - output.add_callback(module=self.instance(), button=4, - cmd="pactl set-{}-volume @DEFAULT_{}@ +2%".format(channel, channel.upper())) - output.add_callback(module=self.instance(), button=5, - cmd="pactl set-{}-volume @DEFAULT_{}@ -2%".format(channel, channel.upper())) - - def widgets(self): - res = subprocess.check_output(shlex.split("pactl info")) - channel = "sinks" if self._module == "pasink" else "sources" - name = None - for line in res.decode().split("\n"): - if line.startswith("Default Sink: ") and channel == "sinks": - name = line[14:] - if line.startswith("Default Source: ") and channel == "sources": - name = line[16:] - - res = subprocess.check_output(shlex.split("pactl list {}".format(channel))) - - found = False - for line in res.decode().split("\n"): - if "Name:" in line and found == True: - break - if name in line: - found = True - if "Mute:" in line and found == True: - self._mute = False if " no" in line.lower() else True - - if "Volume:" in line and found == True: - m = None - if "mono" in line: - m = re.search(r'mono:.*\s*\/\s*(\d+)%', line) - else: - m = re.search(r'left:.*\s*\/\s*(\d+)%.*right:.*\s*\/\s*(\d+)%', line) - if not m: continue - - if "mono" in line: - self._mono = m.group(1) - else: - self._left = m.group(1) - self._right = m.group(2) - result = "" - if int(self._mono) > 0: - result = "{}%".format(self._mono) - elif self._left == self._right: - result = "{}%".format(self._left) - else: - result="{}%/{}%".format(self._left, self._right) - return bumblebee.output.Widget(self, result) - - def state(self, widget): - return "muted" if self._mute is True else "unmuted" - - def warning(self, widget): - return self._mute - - def critical(self, widget): - return False - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/modules/spacer.py b/bumblebee/modules/spacer.py deleted file mode 100644 index f9b88d3..0000000 --- a/bumblebee/modules/spacer.py +++ /dev/null @@ -1,17 +0,0 @@ -import bumblebee.module -import bumblebee.util - -def description(): - return "Draws a widget with configurable content." - -def parameters(): - return [ "spacer.text: Text to draw (defaults to '')" ] - -class Module(bumblebee.module.Module): - def __init__(self, output, config): - super(Module, self).__init__(output, config) - - def widgets(self): - return bumblebee.output.Widget(self, self._config.parameter("text", "")) - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/modules/time.py b/bumblebee/modules/time.py deleted file mode 100644 index 68f1beb..0000000 --- a/bumblebee/modules/time.py +++ /dev/null @@ -1,34 +0,0 @@ -from __future__ import absolute_import - -import datetime -import bumblebee.module - -def description(): - return "Displays the current time, using the optional format string as input for strftime." - -def parameters(): - module = __name__.split(".")[-1] - return [ - "{}.format: strftime specification (defaults to {})".format(module, default_format(module)) - ] - -def default_format(module): - default = "%x %X" - if module == "date": - default = "%x" - if module == "time": - default = "%X" - return default - -class Module(bumblebee.module.Module): - def __init__(self, output, config): - super(Module, self).__init__(output, config) - - module = self.__module__.split(".")[-1] - - self._fmt = self._config.parameter("format", default_format(module)) - - def widgets(self): - return bumblebee.output.Widget(self, datetime.datetime.now().strftime(self._fmt)) - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/modules/xrandr.py b/bumblebee/modules/xrandr.py deleted file mode 100644 index 7817143..0000000 --- a/bumblebee/modules/xrandr.py +++ /dev/null @@ -1,89 +0,0 @@ -import bumblebee.module -import bumblebee.util -import re -import os -import sys -import subprocess - -def description(): - return "Shows all connected screens" - -def parameters(): - return [ - ] - -class Module(bumblebee.module.Module): - def __init__(self, output, config): - super(Module, self).__init__(output, config) - - self._widgets = [] - - def toggle(self, event, widget): - path = os.path.dirname(os.path.abspath(__file__)) - toggle_cmd = "{}/../../bin/toggle-display.sh".format(path) - - if widget.get("state") == "on": - bumblebee.util.execute("{} --output {} --off".format(toggle_cmd, widget.get("display"))) - else: - neighbor = None - for w in self._widgets: - if w.get("state") == "on": - neighbor = w - if event.get("button") == 1: - break - - if neighbor == None: - bumblebee.util.execute("{} --output {} --auto".format(toggle_cmd, - widget.get("display"))) - else: - bumblebee.util.execute("{} --output {} --auto --{}-of {}".format(toggle_cmd, - widget.get("display"), "left" if event.get("button") == 1 else "right", - neighbor.get("display"))) - - def widgets(self): - process = subprocess.Popen([ "xrandr", "-q" ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - output, error = process.communicate() - - widgets = [] - - for line in output.split("\n"): - if not " connected" in line: - continue - display = line.split(" ", 2)[0] - m = re.search(r'\d+x\d+\+(\d+)\+\d+', line) - - widget = bumblebee.output.Widget(self, display, instance=display) - widget.set("display", display) - - # not optimal (add callback once per interval), but since - # add_callback() just returns if the callback has already - # been registered, it should be "ok" - self._output.add_callback(module=display, button=1, - cmd=self.toggle) - self._output.add_callback(module=display, button=3, - cmd=self.toggle) - if m: - widget.set("state", "on") - widget.set("pos", int(m.group(1))) - else: - widget.set("state", "off") - widget.set("pos", sys.maxint) - - widgets.append(widget) - - widgets.sort(key=lambda widget : widget.get("pos")) - - self._widgets = widgets - - return widgets - - def state(self, widget): - return widget.get("state", "off") - - def warning(self, widget): - return False - - def critical(self, widget): - return False - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/output.py b/bumblebee/output.py deleted file mode 100644 index cfdc88b..0000000 --- a/bumblebee/output.py +++ /dev/null @@ -1,121 +0,0 @@ -import os -import inspect -import threading -import bumblebee.util - -def output(args): - import bumblebee.outputs.i3 - return bumblebee.outputs.i3.Output(args) - -class Widget(object): - def __init__(self, obj, text, instance=None): - self._obj = obj - self._text = text - self._store = {} - self._instance = instance - - obj._output.register_widget(self.instance(), self) - - def set(self, key, value): - self._store[key] = value - - def get(self, key, default=None): - return self._store.get(key, default) - - def state(self): - return self._obj.state(self) - - def warning(self): - return self._obj.warning(self) - - def critical(self): - return self._obj.critical(self) - - def module(self): - return self._obj.__module__.split(".")[-1] - - def instance(self): - return self._instance if self._instance else getattr(self._obj, "instance")(self) - - def text(self): - return self._text - -class Command(object): - def __init__(self, command, event, widget): - self._command = command - self._event = event - self._widget = widget - - def __call__(self, *args, **kwargs): - if not isinstance(self._command, list): - self._command = [ self._command ] - - for cmd in self._command: - if not cmd: continue - if inspect.ismethod(cmd): - cmd(self._event, self._widget) - else: - c = cmd.format(*args, **kwargs) - bumblebee.util.execute(c, False) - -class Output(object): - def __init__(self, config): - self._config = config - self._callbacks = {} - self._wait = threading.Condition() - self._wait.acquire() - self._widgets = {} - - def register_widget(self, identity, widget): - self._widgets[identity] = widget - - def redraw(self): - self._wait.acquire() - self._wait.notify() - self._wait.release() - - def add_callback(self, cmd, button, module=None): - if module: - module = module.replace("bumblebee.modules.", "") - - if self._callbacks.get((button, module)): return - - self._callbacks[( - button, - module, - )] = cmd - - def callback(self, event): - cb = self._callbacks.get(( - event.get("button", -1), - None, - ), None) - cb = self._callbacks.get(( - event.get("button", -1), - event.get("instance", event.get("module", None)), - ), cb) - - identity = event.get("instance", event.get("module", None)) - return Command(cb, event, self._widgets.get(identity, None)) - - def wait(self): - self._wait.wait(self._config.parameter("interval", 1)) - - def draw(self, widgets, theme): - if not type(widgets) is list: - widgets = [ widgets ] - self._draw(widgets, theme) - - def start(self): - pass - - def _draw(self, widgets, theme): - pass - - def flush(self): - pass - - def stop(self): - pass - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/outputs/__init__.py b/bumblebee/outputs/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/bumblebee/outputs/i3.py b/bumblebee/outputs/i3.py deleted file mode 100644 index d9d1894..0000000 --- a/bumblebee/outputs/i3.py +++ /dev/null @@ -1,76 +0,0 @@ -from __future__ import unicode_literals - -import os -import sys -import json -import shlex -import threading -import subprocess -import bumblebee.output - -def read_input(output): - while True: - line = sys.stdin.readline().strip(",").strip() - if line == "[": continue - if line == "]": break - - event = json.loads(line) - cb = output.callback(event) - if cb: - cb( - name=event.get("name", ""), - instance=event.get("instance", ""), - button=event.get("button", -1) - ) - output.redraw() - -class Output(bumblebee.output.Output): - def __init__(self, args): - super(Output, self).__init__(args) - self._data = [] - - self.add_callback("i3-msg workspace prev_on_output", 4) - self.add_callback("i3-msg workspace next_on_output", 5) - - self._thread = threading.Thread(target=read_input, args=(self,)) - self._thread.start() - - def start(self): - print(json.dumps({ "version": 1, "click_events": True }) + "[") - - def _draw(self, widgets, theme): - for widget in widgets: - if theme.separator(widget): - self._data.append({ - u"full_text": theme.separator(widget), - "color": theme.separator_color(widget), - "background": theme.separator_background(widget), - "separator": False, - "separator_block_width": 0, - }) - - self._data.append({ - u"full_text": " {} {} {}".format( - theme.prefix(widget), - widget.text(), - theme.suffix(widget) - ), - "color": theme.color(widget), - "background": theme.background(widget), - "name": widget.module(), - "instance": widget.instance(), - "separator": theme.default_separators(widget, False), - "separator_block_width": theme.separator_block_width(widget, 0), - }) - theme.next_widget() - - def flush(self): - data = json.dumps(self._data) - self._data = [] - print(data + ",") - sys.stdout.flush() - - def stop(self): - return "]" - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/theme.py b/bumblebee/theme.py deleted file mode 100644 index 42e6c01..0000000 --- a/bumblebee/theme.py +++ /dev/null @@ -1,129 +0,0 @@ -import os -import copy -import json -import yaml -import glob - -def getpath(): - return os.path.dirname("{}/../themes/".format(os.path.dirname(os.path.realpath(__file__)))) - -def themes(): - d = getpath() - return [ os.path.basename(f).replace(".json", "") for f in glob.iglob("{}/*.json".format(d)) ] - -class Theme: - def __init__(self, config): - self._config = config - - self._data = self.get_theme(config.theme()) - - for iconset in self._data.get("icons", []): - self.merge(self._data, self.get_theme(iconset)) - - self._defaults = self._data.get("defaults", {}) - self._cycles = self._defaults.get("cycle", []) - self.begin() - - def get_theme(self, name): - for path in [ getpath(), "{}/icons/".format(getpath()) ]: - if os.path.isfile("{}/{}.yaml".format(path, name)): - with open("{}/{}.yaml".format(path, name)) as f: - return yaml.load(f) - if os.path.isfile("{}/{}.json".format(path, name)): - with open("{}/{}.json".format(path, name)) as f: - return json.load(f) - return None - - # 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 - - def begin(self): - self._config.set("theme.cycleidx", 0) - self._cycle = self._cycles[0] if len(self._cycles) > 0 else {} - self._background = [ None, None ] - - def next_widget(self): - self._background[1] = self._background[0] - idx = self._config.increase("theme.cycleidx", len(self._cycles), 0) - self._cycle = self._cycles[idx] if len(self._cycles) > idx else {} - - def prefix(self, widget): - return self._get(widget, "prefix", "") - - def suffix(self, widget): - return self._get(widget, "suffix", "") - - def color(self, widget): - result = self._get(widget, "fg") - if widget.warning(): - result = self._get(widget, "fg-warning") - if widget.critical(): - result = self._get(widget, "fg-critical") - return result - - def background(self, widget): - result = self._get(widget, "bg") - if widget.warning(): - result = self._get(widget, "bg-warning") - if widget.critical(): - result = self._get(widget, "bg-critical") - self._background[0] = result - return result - - def separator(self, widget): - return self._get(widget, "separator") - - def default_separators(self, widget, default): - return self._get(widget, "default-separators", default) - - def separator_color(self, widget): - return self.background(widget) - - def separator_background(self, widget): - return self._background[1] - - def separator_block_width(self, widget, default): - return self._get(widget, "separator-block-width", default) - - def _get(self, widget, name, default = None): - module = widget.module() - state = widget.state() - inst = widget.instance() - inst = inst.replace("{}.".format(module), "") - module_theme = self._data.get(module, {}) - state_theme = module_theme.get("states", {}).get(state, {}) - instance_theme = module_theme.get(inst, {}) - instance_state_theme = instance_theme.get("states", {}).get(state, {}) - - value = None - value = self._defaults.get(name, value) - value = self._cycle.get(name, value) - value = module_theme.get(name, value) - value = state_theme.get(name, value) - value = instance_theme.get(name, value) - value = instance_state_theme.get(name, value) - - if type(value) is list: - key = "{}{}".format(widget.instance(), value) - idx = self._config.increase(key, len(value), 0) - value = value[idx] - - return value if value else default - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/bumblebee/util.py b/bumblebee/util.py deleted file mode 100644 index 3a6a60c..0000000 --- a/bumblebee/util.py +++ /dev/null @@ -1,33 +0,0 @@ -import shlex -import subprocess -try: - from exceptions import RuntimeError -except ImportError: - # Python3 doesn't require this anymore - pass - -def bytefmt(num): - for unit in [ "", "Ki", "Mi", "Gi" ]: - if num < 1024.0: - return "{:.2f}{}B".format(num, unit) - num /= 1024.0 - return "{:05.2f%}{}GiB".format(num) - -def durationfmt(duration): - minutes, seconds = divmod(duration, 60) - hours, minutes = divmod(minutes, 60) - res = "{:02d}:{:02d}".format(minutes, seconds) - if hours > 0: res = "{:02d}:{}".format(hours, res) - - return res - -def execute(cmd, wait=True): - args = shlex.split(cmd) - p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - - if wait: - out, err = p.communicate() - if p.returncode != 0: - raise RuntimeError("{} exited with {}".format(cmd, p.returncode)) - return out.decode("utf-8") - return None diff --git a/screenshots/battery.png b/screenshots/battery.png deleted file mode 100644 index bdbafee42fd9ce6df799d0cd95888d09fe707a75..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1733 zcmV;$20HnPP){x2YX&>x1cG^C)uYGHMs84m;QM9dEwaQWj zI+R5j*<66Ih9!X{k^~aWNNmr1O*S`K?S)Ad5L^eO}2%%1K;#?4r+iZ5Eca({V9Uej7c~z=65`xqK01hYo z^-mF~ue~$yJov7Qw8Z$mg2M3T2VB1#g#9L#}HTsI*~ps;xLru{B=rZg1-3O)97qvc0@` z0teB4DWkcI`|)uJ#O99GhQ~pa5bErbc);a~)lp1K;HR3qc%6N0zgnBQkpNv4(`IOBm{@1 ziF9}F#Q*?uGt{Mf*3fI*H<>o2%CUwbod+DJ-~|LnDR1b005WN+bY#P;`D0qei9EyVL4e?4182~Uf6Yc?*?*UiWCg|vm z$`z{*=gWPcl1Le~EwKTng%En!#q$ks6^&zA#_j=@$r7^eusEJkz%}X&gd2_VZx&7X zcFpQY-pv9b5b_PvGvRJ_4BEni4VhF@;&?`rB}A(yaw07N05;PyGe=smBMLQnr&!(4 z&aW&R!5IF1qs$Q*&HIx~avaE0c)+y^I{Kmj0I^)7?;{h_)ZZHuP;{M{J#n!=TZtg( z=B8v0%W~%3KIv4%igqHwG4G>(a5&Vv7&MCgK%U}KP2%63yz@7<=8DyPjtKz3qA%>q zoH_Sf8jo$BohOQ7o^e?gjBX5!Ez9&~E57P>(t;iFf;&!n@aQL zzto9bC}h(YQiVFN&XTJrHyYzly)hicvRSj>qrFW z>PE8_4*)3HGnJj@M+Q*B7Ec}>{_%QB;Ow-t;JRmos_G=09oZ~K26JdjH$;H?H@~KGaKQj_ zmCLf6I4liN23Bh0NhS4Ky|AK0y1M4#AZoVaKdZ~pw=+|HwkqRa zoGTDl@$P9qp^gJabLjb-TM>w+2=xbdEh!jr(wx%?+j=Ag^4S000ocp%GHl)o>Uw*zE@Zk4iyK=C9+TqA03*q)AGk{_oRB#LhP_ zz}}}II|~>CU{tHKyWm{|(WulHDoXY(Cjr9R8kh1iJ=-fgET-lbO?D@)KY@^!nMNQG zAP7>Pk)M-Smlfs%0B97-@l@Xa;e;U2A~T8wF5I&^yKG!ATVjMrOrXB^`Z<4a!)S99 z=42rVqHL6x7v>AIGfg(<=hwUN9LXfo=~78!<*BX#)ueVV9@UFA6@siZw=d9fcK}7v zQX#*oru@_PP7K3#MXj%}NQ)e}ZE4YBoz)xS`DQ4Jsx|XB`UZXe0FTWq7ZnubWW})O zBp-QKsc^z>2#QyAEQKu*u}HT=og*cOh!_vkWZzMBOPIn_mlR{FMqn@ z4{pS%I?85x`~d&}?DigIvuaDkF1JUkU)hyYEO52T4YSBjzs3A}zIx*q^Yf=2#jwrLR`deFQLV1Q>D&|=g_4!Z8=9I?$f~~T z>fMzyH`DWK<5FbpY-e>=Z$MErc9ij1oyX^Q!fw6Q7S&)efCu~~l`OlJIM`Aj}6L?Uj56951;;zBx&7CVYB5WGD&VqIIuGjO;b2RAow z_Wu#jaf(LTcKAeGZtAse;bw@4i~6L& z))h$zgy;`|N$vd41H*c&?X@O36mjsAXbCNKQnhxzy}N%McJCFcLRR(rs5+I)5$9!p z{LPOig$k_V@$Wdhb14SPq55d&0@jOiSgkRMQ#&Krj?S5X9~E5%AjU^P;yLx%C@=N7LAO z-Ou21PYJ_n-F%Ed#re6yZOVzAm)Rvi~# zX$Bb9qZ*6TU9-fx^JliAetX73%1a+avC|v<8ym|JbA>`8HP=aJ7WHPk^TRjWcx=|t zgP9)Hm?$@!#Ynn8IlbR5{q+@A=8?^^LMH%#D3;blTJTs*Duo=0ilC^@V1hkf1VNY0 zs~J3Q$K8R@R(N&Ig*R{iTQOQ0{vf$b{@Arvd7+6`QM}Nc} hU^zsn(Bb(x`VRs*2Jffwcy<5)002ovPDHLkV1oRXbDIDF diff --git a/screenshots/caffeine.png b/screenshots/caffeine.png deleted file mode 100644 index 54447779afbf96b58344d131d7c390685fd770b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1143 zcmV--1c>{IP)6c$KL}; zVOS9n4u}XiRHV{rp@wQZjWsr|-I8V5VzMpEk|n!Xvb!bQUGI0hCEG66rA?D&YqQkV z8SU&O6q&1E6Qod)4>=q~D2RL&1*gPXn3J|W@cdEWD$^Lx+xf1c-s#yp12`r&c5$F^K?Bd7F~|bhY|ax191jKtT@J%lkn;Jw(Xz&2ojCeDG#c%K=2Rk; z{?}7J2nWDyvj@VFqt62Ya89j)8+cVV-jc)V3k1n#8PuNU*K^6Du|(49bfcj#^{X&z zY9Od|U;LTP{a2(j9ZD%IsG=pS%e#*FDP|ebYfo}spcruZeD95)XBKQv%0n$8;b@<( zMI@}N<&;N5yU`6~Yr;4miNz1X)72_#YnD_=4^BU7b$kBzHhA#+vSHcs(VMTmH8Qa5 z*vRFIR(HA~XC+@Fp zc&VSIlr(iIMO z-G_d4`<}y#y!YxQ2!e9C9I_J{H<+)DPrdWX#fqPC-=wfWr)ncj7=^z;WY=u7KNHDH z1bhI%UIHUJhkJV_jPp;UdqsH&$M4S033>H0v2fpM_xRSFp8l8AWb?zk`g3X(RSx`H zLT*n!pFbo_yR7+x*GF~g_LV2DI97xt7YiMm6(pL?WW zQkhH@Bmh7yn?2C2sbSEmk?zbGcfz|^CR6lFr|ll!!xbypUDLlUj`p1uHq;k?4d{)b z^Jpl%NhpIFrMyEXHIYvR0ElClVZ}mL$DooWjQKQNRrT@ z6zoEG*Oiy`_ve@F?#*}-lfaF`y*(T@`5G2FW>g`{Q<^HC|hD&|A7Ll;A ztpCX4`1aF?3qdDMkMr|ja=?=Imw2i(E}kJQ+p1P{sQQ|s$03vvpfI*002ov JPDHLkV1iwhDMA1M diff --git a/screenshots/cmus.png b/screenshots/cmus.png deleted file mode 100644 index 52c0b5159e2d2eb8dece597c177b523109319651..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5031 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 LNkvXXu0mjfW)Onx diff --git a/screenshots/disk.png b/screenshots/disk.png deleted file mode 100644 index 7a659b8fcdfeb1468d05e49f29f1c98fe3098c53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3721 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 diff --git a/screenshots/dnf.png b/screenshots/dnf.png deleted file mode 100644 index 49924168f31d1a081be9a94ab4063993d73d31ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1113 zcmV-f1g86mP)*HlGt&bp1w4y`s&)?Z*BoZ%eLrdRf6Mp1HxTG@04|M= z%mP7l`s~YB?n&6=U>RYzCI!DZ#pa_#ObuUniDhBICQgYM8z5?EaHZXt5j;Blc!VHu z(G}|MNU_5e0-Ahe^1eV3d1dhQdbcI@uY6NF10!`6nUvryRjZF~N7#8X#tHwjV0hxy z0RRfylG~H*x({$o!#3MTXJvP$&7p|GXvklFd-bTYNEgH*wX-L7 z#u;W|z8$x2B#<50-kIFFdTgm2E&~8OoHsmP)K^mk34J$VZPDgG{b;F0o4OUvk~uK3RV#Lvel0G_WlIC}Q29#{r`7HGUN{FJv;P2=&5BPd`6 zbrzT2{IT=;kWYb>nSimW);ZQyWAv*x0019f_P4d{t372hGMYrDo-})0A-x(8hL6ak zqlT#GKxTk19POlk}MX3SPBG4{iIXIDo@X5T*_VA=wGeq(lYWcGlG0013| z-@SkAcpGN7B>@0f7DiS7R29XNcxFlGIu+q9_1bk$B#zv=+d;6Ve7zc{eczDEMAJ~h)EiPby*PK6Z$dc3H2^=6NvYPy32xzMF%@UB%+SDVO~G_({DzKg07tl z>=thGK5Zmc?->YI_YF@dCQZ-0at~rZe{?${N0r6C6Y&Gv!3JfKb~jxipos^q&Xb!4 zhKWzB<&cUbq0X8o(SJ{IonW fP%Zzt1aaywgMS}|9}1IZ00000NkvXXu0mjfah(r0 diff --git a/screenshots/load.png b/screenshots/load.png deleted file mode 100644 index e136e7e9e1f0e88f5d84e7f4fc2a1b98686f19d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2005 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 diff --git a/screenshots/nic.png b/screenshots/nic.png deleted file mode 100644 index d1512c0772b4b3bc2f09f274af9a215af3b366ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2474 zcmV;b303xqP)X0ssI2ND$sx00003b3#c}2nYz< z;ZNWI000nlMObuGZ)S9NVRB^vQ)qQ`bY*g5g3t*700~A(L_t(|+U;9wP*Z0b{?5t$ zN-pF=Aaad>fFK}(h+suPTM^wZXx(*f-R*Q{-Py6T({*=$bY}l_W@oxH+t$^+^kTPL zt1zn~R76w+xkT;+!X-dRVnRqDAtVqIAZLHXVv2GSLN}#5=b7{4e3$o}=X>&=?|aYt zoj@QV17N_giGjx?z_8hHe1EQI5ylk3fX$;AF!=0_cwB@)fcYqfO$r!>bCMF~796YV zF=;St20#F0ZHp6d*c)2wAqWx+cspXFVZ9RyN#w!o3_gc7F=eW1XdN8a_&ACag?Uk-A>%szmv_@Q1e5iJ(I zeey>l9v1*$G+Sz=op)Q>Yo%TC(Q&iYCg8A1L_$P}AT?gnJ3O}Fbo%~lX^qo0&25kS z2lu5X*LU>T9X{E{h(k}kl3!8RSk=&qAjnS+zSOT&&D!SCt#B~>tK%gj8tvukIu4V5 zcyDHNkKBbI0d`Ps5c4;uUZs*rECx+Jrq&s!H^?xMRw&BTsnnO!lYf8V(|eD*+{cJU z=W@Bc|C*tq6iM_-(QLJ`8T9q}=oTUWY-urxNN~Aa*B>-}UR|fuPR!WmTrStdw0TJN zq_I;*r%<*C`BX9~F($HWXvDF&zS)#QCaudyXRJ1vVqB@yFE|&+b(3L29yf?Npj4w< zWhTXof;pF~>YR&`*qV}ckyW6Zb2~T zQbiRyLln3WWUYwEKZb#{LQ$SdA~_t+bv>>EHY@Af4*KGRl-C};3gyM}Te>OJp5%nW ztTY&gJ(C6DA%gG_!GT?=U)9#X|F3cYfPTv4X|C2AQsX7=c;(#5WAA->b<$*}QOHKq zjMrOdZBO{?wVS#r6OSGA%hF;BnN(5NxT+6{NJy4MUAx=hE(*EqH;M}{T&q-QbSwt_ z)%={)_?U)H832IKWgE;h0D!FR+a%#(<#i2*_hxQzQuKwP@9>XdAgxf8r;?3)*-}~e%yJK~7OEYN{a##dBJ|ctS51j7J=+zZoZm9;Aq8=XRS zIGkYuUP<2W53XE?V3CYKRty`p`gw8+ai68Jf2i;E&2_t2h<^124C zaXMNoa{3ZCLy+GL*Bz?*#W0XoXv(Xe{OR&F_j!+E>`|vIH#G^}M;DyV`Yu_1dJ36H zTr(#X7qN~UzEV4(o-mv{d2IXEC@Pr*0AMlb*(nKUN{Sl0`^;7V@IQLaHB0 z!}wfLFvm1&^(CP8^bZ^i0RUF4UQiK3-vAoh#Tm(U`KWO^Hh0p4wT_S$)?_NKi z8Ygi#O&Cq32XbX2h zqRC<%)#&!7CTR^*zz6RLW<48Z%$Csk1;?~y)?Iu#XBUG;{m1p&tA@v*QQaeNl?_}h zza{M(+_NLm-PAoi3IM2l*y1iGZ;kFBRe2Y2et}7&t`t2fp)>RY{xJ-s6^imO40}4I zFqmWUSY%LOw%QtdWhl?~y7xj=6O&)uzMmQ|Ie)s0&177zx@+;4m{jYH$y=k8Iz0eD zKBnH85Uce_xS;Jl#7WZPB`gL#Enf0U&aV4y-R_kogvZTGPyYAU_aF$6hy)Um;GWk3 z0LS)azfoKmAreqXr0@_yWN65UTI+6V>6Ke-wz7g;K8JlMJ3}nwJ?ifB%0V`wOo@#N zW(5HN(&8m?5n^8$`UkHJ3o_IG_|_>mneW94Mfv?ZQ_hwZ$3=+gR7zUBWKT+BV^^P# z12>p0&3%I}ly2FD`1wtVv~N%>r3Z4^OuErD^JUHb z&OwFmV}D{ab`0UuAet(A#K@jr4+@yKuRB6}n=-t*1uvxMB8UEmq5E)J* zlUMD9`v2V%67XF_4FC7&SE|Nz`i;h;fdjPZ6@@UT`tC7hu{~lqpVE_OC07*qoM6N<$f`yF3^Z)<= diff --git a/screenshots/pacman.png b/screenshots/pacman.png deleted file mode 100644 index 8f4169e3f1b7eeb12ff9a5947b4386ff071d929a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 860 zcmV-i1Ec(jP)q%SB`UCnqYCUSL&8;=pY7SZ=CAy(9LFNyT zLj(CG#|;eR^z4B*5{?pF4{np!v+sRBuif_E_w&8)_gIgfzW{}J|J4l6F%T$Ihzk0n zgM&jf6e{PE14)t=#|odzIp?|L^wALjR@Z7MhL!s$Czr)F_jV}qe_v237IF|aldV(w z$hqm;_~|d+l!%0n?-`owE~A0qyQyz6JW;T0d`Q0&jeVS+WvoR<)!ay}7q>s)^rFRw z0z=T#2g6&z@XJ?kw}RnkVJB3Sn`pYqiw&>r%8@ z9h5b8N5?t>npSyUjZ`e^>}WC0FEQ52qgryYUrA*LIlU-JlBMQSC6$D+H~^quqik!e zpD@kT%A|QUw|lit4|?+J#xyH`Tahc=}E?y8g diff --git a/screenshots/pasink.png b/screenshots/pasink.png deleted file mode 100644 index 2fd6359522b9984ea4e8df7aed4d5465f718163f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1486 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 Hu0mjfCfMGn diff --git a/screenshots/ping.png b/screenshots/ping.png deleted file mode 100644 index 1c8bf2bec8065882dc2306424b8bafe161b1f309..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1655 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.Hwr|tlrd|)1 z?h>xX(oHT7S}eviGxyKM9vfop^+@&gz%+@BxVF?20=r)Y)Z)Y~Xe38M;aqeSv5{iM ziUhspcwsYiMRLa2>Z?t!bWU$p!9^VDfjRB=zNfgf3j=9QdL%$l$Vk;ELf}`Pu~$^c z2n_IcwR40RnbM8BY23xZh+Qyi9f&p+myMDjskgv6$H#Cj{qiX~Ft0OeWcyFy zfYDm>Q8!f?X|DDJB4KD08fuqU>)LBxPFDe1K)Og-c|lccaSH>JNag=}k=bsHZ2FBf z^8z|B!`m8%A6x&QtaFyXuAniOuneXrxU&F~cELTHDrI+d`b++&E97=tsOEQxKS_ z6biYQ!LujA;#zPaR=;s>8b^_gQ@ZSjVTN)J3>Td)#N|D9zy4wPS|QF)iH&+WqHf;L zhNJoDQzz%ub%wm<%1HSMX}ymKqWvfz-GlqV*Fov*HdSlSFfEIXV9xqp!kcCv|ACz{ zN3EVZE_jf1EYi^3na~&eo)@r*!u6Phpwf8TREPDy5ZOv4rca^%&@5BN}Q z?ZuCGrV5kfcCZq2`>tZzOnOl1E*z$!><+h3A!y9a*@(NT@|7hH8+jNzR=V-9sgI*z z*&*r(o9Q=d0N)aSUn6s2oZYFn4aJ?^lskGq(~=+{#`QbXzs) zOQ$TG5875K2H&}mxfv%5aePWv3SerkykG)@vyHdg8KOs=RqxT}F5BRt$x80*9nspI z`&&N!=l|!#C(qt%bekAKgag3=_~v?Wqb4Fs;sp-Zr!pV@uG=M!6Lvsy3^bsFa@-b* z&75W4&QWb>eicPCpc+4;BafY|gf6h}0*&<>*t7 zZ+&Vy_30cDfXl1;MtbaLwq9>S2MJ>)4cnrcinBxM0@Y5}#`9(mLVrAH(li3RtLo*_ zwqXy1v4$5D=9L%G`GD{%;E_%t}BgsyF0<6fQ;8(nh9uw4psY)oG+U+I*YwK$3 zbMn8=NGZ=_cl?P@LVRydL~%%xoi2@xnJY1!HM(w@znCTBqFuk{Z*KMobkHzy^L+Zj z%jt2d_r^@oXIkGvTx6DFk+5@R8qB~FrZ}I|y{A&97@wIapzPN+Q@%L>L#u8!%t*Lg z%KxV=Vt#SN>n>xMsALU7iLu4`jZ}&-FPdB+K>t{lf9z)&UQ+RW-@3Ac?cHd38@v;Q zLujbvb<#QYBU@_xUHv<=DZMWFMJ1NVa00%|1N-+{5u=^;`i}&+l43?Ck&d>S_1pVV(L;Rrbg}UkElzDfpPi|NUe4)0-M@kuH854adP(Ysu zF=xiijKy5CX4#y=9;2ftgrOG#6U#Ml@^?W3CNR@Sw46@hSuq-=EL}9qggMY8AR%pE z=d6S%{=E%-6D%rXqo=qL=(u{fb1 zJP3x4GFM+R18QkQLbszKI8n($N_Y9XB)6dc5uNPR;DA{IeYZb<(%OhszaW>BHEujb zU3osE*+!doJ+_AGrU7z%rAx>Z!!d2chWm$I-A~fm_LM1B)3fgmahsM{vds`b^f;tfQp>>N*MZj z_hffNXwF`--&H(!lGXW=Hlji%&78nAP@-v-0kLwLoUsr+#JIU?&%nGyP1o5oryHZ>_53Mj}t0m;8{C?lCE ze}Qj9$!o%8DYYe=qxiYP=3=7L;G)umcU)~pyLyfRut z))(pqjx#1w#koTVO#1!SSD&Scr=4^|0(~#)FEJ&Q8zzyW}3O!7L@izY5|Lxo~vOg!VJ>2SkIg`5a_q?et@W+KP zidpbw2Ka7s4P$Mxr$Zhbu8rBMi@3@^Kf?Qd9cYLUD6c1jVy~gfzHU7|66VZv;OM~2 zg*|2aLPe}z{t|dol7!98G`s{hAjXyM5wov=B zUiz=Z_Pz~bM;^QJs1Rd^aZW=ega?I~OY@o0NQ{82hQG*_da-@|!!_TRzL06t zq5?ng&&iGtzA5OIpc-PfyIgc=v^36zP4GE-YN?*xN|^JHVT3=_e7t$cPmF+kVSGm- zx{_>ZsELQ=IVa77Kq1?vc|SL%?Z<98KpUHgf1a0vuQj`5-u#oCHGIH@vC@XO16BYe z#;i@KJ%&sC7BUJ3aaB)Ji6<8I6Hm;nr!-S?>@O|&VI!em@%n-eZBR^k0xNY`u7WFiO+cMCj z`@YgiXHAiC(orxU&eSLckP_pC&9&gz)J(+;pNmvISWIvUQ0Lcl`$7up)S;f+!Tm4B ztSO4}2*|%9Vwr2~jEY}^t%5{Z)hiRJB34^@c!M(QBd6hJr(Yvj>^r1Tz07#K80-w-u@;~=EFwTm-sS`R} zuy2YTr7$>w722RNY&2v=yjf;a_=~R1BtkWnzPX>VV)FOYCuwf{ibKoVK$#O&B*IHb zEE)y?$u3gR_e1RJKBz|YW43SSmQmCnfY0W1RldKD@G_{*bTXW+4~9S2K!5@2!_7uY zXV>kUZH#7jUmm)}ptM&<1BBUIET+vgUP;e*J&%Ux^9VJUKhY2QOF)&Zt&^I9o|A$; zSv>bw0-D#7)|jn|2l>>-Zl%*>@9Sc-C)0xZ$I9BUDbiT2m)&QGIn~qiJZ%-dyv?g1 zfqhg6<$vfbnX<&zTE*SE?5?E=2<(himR%vsrkb?5gA~isBj%uPyVYlh+U>nWAI8YX ziBgnQtQ4`LQ{%knRYQLKPruvZK8SsxbHoPN`DoQDxXpQpZLI{>eZ?vB{v4KmT0v~g zn`|x$yVqSRJ?~li@wq5b5dj&ATR)QJr_F?t+@)D3G++k$H(>-3P?+m%rC_Q zUf@|w_Ww&znd)4=$wzN*b{~jPlEVOc9XXv|(bm0~1F)YO?#;f}eo>sLy(K0nquvzd zR4$WAS#WK@lu5H^tXgUUD>JLV?TqeKGhyXzwu_S*j{yKI@qcCkFkwG~x0Z(b_2w1? zAM_;r*B@#X(ik+g6^M{3ORJ?cU2Bm+&*5c@a=VpKZ<4zHcv%+Rd2Ry#tVSF~+A03U z!}C7GB8cz@sC$bhx^*_-0GETA8nijg=yLH!EY&tAzU=og{iYn{@F3g=J)e5~+vE9i z{}Z)Pv!{xzl)Z=PxDWe5XHiAbG@u6_Msod|b|Y zX3pF5Tqgkd54=LKyP2P4mRQN_Uh6b|@B4nE3IM!aZucr-g=y!lnHs=hjN`bUt%J|) z@^(kjo2BR2!KG~!1(erx?5{0gdJ&Vs91kQPhKDthl9xx_wl~qf%(AgcE2n9 zSe{a{7-S<+t^EEpopxV6`DQ$Qz8@RoAHX=hI}f3SJdVDF8r5EqZKK7+_12lg1m!CX z;gs4VdaVsl><0VZ`E(cg^3Pb4t8euR5QT|}ZGTU)o3r}(F%mIj=0sI$;oSSFN3pCT zR<|qU@(6yfHpQz}nP||2oK@z0OzYK+0UxLnfNbg)kBXrzk6@gGSeDS7YcFLs*kO+enOKNpG_)k3hOrU<+!JrKU_pN@dw%8uv-h^Y`Kg&2Hys zt=S|Zt?uXDIMo6O>0A9o6DqG%^aIo-^mt?ZFh_*q?K%EXqig!AvpQQ1LOGdBYN?jR ziYPfil4r~$wH(ji~r_*{P%o8*HO6DN{vy_xv0+5Yd!(R^ebr( z>}h$JzZP0BiW}q6LK&Fg_KQE=g`e1+#DL$&D)=M{fShs^IeuWujwnl`=K1pQ?u-cw z(jp-MX6A(-w`c8!soEC^9qcaZuE+&JeKQ-Pwj!Y|T%5x1gez927tJ0G__x~k4oQs3 zFt1k)VOsb9@&;KP?cEC#jn|qHq4P_^Jv%E|_ut~=@v%(Y`6lr2G2A81*~n1{_j2$& z@i%+jov?tdltALS<2x-w8HHb7KJkC7^e<~dO#5D#IK=;RV7=&3&|k{)yuACZ?c#4J zHA$nniI)}w-dZ*fMyT3}pIld0E9^4&jK4gmseQx@yt_urGnFs*BE)A!4IlOtR z8sNpiqAtYO5m(N4);|bwSmy_^!zP)XFK=_-h(Xf5U7l5n1<$k>0!?npD0MbkAV}ZZ zhneu-UdFf&5$W2~%S9zRKkwCjnOyJZw1O`e@8?@GBU3E%8?qm~PFv~_BCez)u`#kn z=3_jrvr*tQ$|s3dN&OkCJP2aT;X-Jn>^6S|Zhb%m@_F%l+MU)1V%@F5w1gSAZ5peS z8CS<|XKqMOSzRa3B~A@c!Kk~X)Edoh$ih4uKR!4*!^t5I<%tNU!s~|p#LMmG<6?Kc}dLU zgMzmBAmrJs9c;X6=s2O?46 f4*Gvd%&REey2YZelV<^BYzdH)QkJX{Hwpef>6*Dg diff --git a/screenshots/time.png b/screenshots/time.png deleted file mode 100644 index 39d5210fde31641aef160d774e958f9220bd2ab3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2456 zcmV;J31{|+P)X0ssI2x3c@Y00003b3#c}2nYz< z;ZNWI000nlMObuGZ)S9NVRB^vQ)qQ`bY*g5g3t*700}fnL_t(&-tAgzP*eF8|KHr3 z7kQBcNWvq8R}vlpqESRaR1k`&v)a}5(OO48wB4@L&TgGf+v&C+cKW4LcRRbS)9JKR zcW~Fb)|L8L7I#HKdC8lA;gtj-2_bKikZ_aS+YeC;5RwAQ_7XELaKLmkAJYHN!FCqN?fYxY?WIqCdP$?^P zdza(Ndf9+sSo_E*jY0+hgpZ#P0ObWz9)}%Q*2@MQfX*?M(Q1nnKQ~BnGkD1nsBl>H zO1VUomP{ohR)WMXmksWw>qpL+l2h2!?k5XKF92EHMRB)O+5Za z@|-zRYje69Z+5KAK~iGu#w(NM1#{WhJ@6rAz@A;GnHfh5G#cDy`0B%Mr#}@zSZ3z1!vEGxMw6OQO-4?mQf` zIo+SNbfbQ3Q(;b2QhTf9I-|9zwQm{qyS>X7Z{F`#s$l{&Z+7sxObCKt0wfU$#6ms* zAc@T|TI?^(p~s6_9IoIcN=x>5(BX;MsHA3%re4)#m@;$a7muA-ULcK3rLJ5?rI5aS zFs#v;p88j|kjKR^?CPC|R)=egEO-3_q$m(|3_bbpH|jP+5GcvZ2o6owMJkz?C*%ho z9Uh0NGg@P`-|M?KxAu(L7TuwfJPuQDdXn3599OAzS?MWJNo|md+6N|9h5-z}-8Hg| z`px!52!gmQnkX%qgus%lQ~*E{o4H_Fd|?hlQ7IR94o^j`8;mx4=a?$|G2vO-%MuX? zQI7KkIcWfZ_JQ&BOQ4*jgeMXQp0m=}AlB1edIf?xwo~ zZyv5`s4RWwM8mzl@fFVqqM=g$ySI<>IIQ)Y@VLyoeQTxiEc@6jT8JeuW&$~~P$VME zpi$=L!}v`A!_9UlkDDkJ33^5~Qjq{AKx87~T=GUW-t#zIK{}5u>>8ZCxl zQSA3XIp*?sA`{{;Y0f3@qRRsSAi^-2gusMn*+p-%006iw`noVe_M*NFKKDTN#y?;A zT4%CRpVmGA0KLiPSw@R;(-Y|l>*JEo??Zil498Y$964OO<>IZ5^-}dH)x~0=R3rcZ z6z64BY>*%@94+}#005}ZA9mGXw)2x%Vv(S^W0=FFWu>KLN1<hnYeOj!2`{ro zXO>Ha={(Ntyyb(&<~6I5Og;cWy*dB_0Q4sN;kvSpp~;7%Y5)K?k-qS>eyiSG*fl(* zU$6lHh9(}j^{T2iNJMhbCu1 zY@k!ARi&~!{ewP#AX5L+=5)0WkL)Nd4x0-HR9d-Ic&vWw?=Rf+uZ|448NBk6Jcn~h zGq=`$gDP#NfZNpC9~_oSGDoN9p2QghfgtFaDlv>iLZWt$etrIGXpP_x1g_ob3yoBM z4D)-Ii7=cm5?r_u{b)5j@p$K^{2rwm$8i7v1VPDcM$pL&W;+pvRT={TU|c)@+D)C+X~E{`P^yBGtU=!+O}|Q;Dd3(x*^rZw z0uvwr0F^?jE-QTNNG$|G7jE45qP{hEJs6sFxR#FAm-9HRhDy0mz+DNs-OA|-xui^% z!)DMF1=%|l`CY@)q4$1kYw>$;9ZF_1LMK=1Z;QjVjQW>R-%8(rNl!SqOTp)|(s}Gt z2dWGfhf1T5s+t@32kBJG_x4qAS@c8(?f9PZA0Da>N@uhXP+~f`oK{rvQPjo$Q!Pg<6q`rX4(H3AcA%Vo#v%guJz zKU%swhbC8_{UIU(Lxfo0bKy9~q*LEMQI7@i!HJpAW9yPEx;*C^n-A{V_>0r~0RSUY zv*#MW2$uC;)HkNq1q)6L!&F*>*}e$=GZf~flZZ&{!E;sBnw-2*;_p>WJnd9J|NVPm zRwj)?$xh|3Uy|jfZz{?b^0-V!g3f50F_><5k2;)7@&4rh2BVr8x7VxI&qI;FpGab{ zY80h$eZ7P*I~-s24ichnifiiSL=uYyp7;JQj#mY7`@PzL;@=Ox(m=>GdRz;yF8&SL W#66KzXm6kZ0000VL_t(&-tAg@P*YbPK6#P= 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 diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/modules/__init__.py b/tests/modules/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/modules/test_cpu.py b/tests/modules/test_cpu.py deleted file mode 100644 index 3b3fa65..0000000 --- a/tests/modules/test_cpu.py +++ /dev/null @@ -1,26 +0,0 @@ -import unittest - -import bumblebee.config -import bumblebee.modules.cpu - -class FakeOutput(object): - def add_callback(self, cmd, button, module=None): - pass - -class TestCpuModule(unittest.TestCase): - def setUp(self): - output = FakeOutput() - config = bumblebee.config.Config(["-m", "cpu"]) - self.cpu = bumblebee.modules.cpu.Module(output, config, None) - - def test_documentation(self): - self.assertTrue(hasattr(bumblebee.modules.cpu, "description")) - self.assertTrue(hasattr(bumblebee.modules.cpu, "parameters")) - - def test_warning(self): - self.assertTrue(hasattr(self.cpu, "warning")) - - def test_critical(self): - self.assertTrue(hasattr(self.cpu, "critical")) - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/tests/test_config.py b/tests/test_config.py index 6891eab..66fd1d8 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,10 +1,18 @@ import unittest -import bumblebee.config +from bumblebee.config import Config -class TestConfigCreation(unittest.TestCase): +class TestConfig(unittest.TestCase): def setUp(self): - pass + self.defaultConfig = Config() + self.someSimpleModules = [ "foo", "bar", "baz" ] + def test_no_modules_by_default(self): + self.assertEquals(self.defaultConfig.modules(), []) + + def test_load_simple_modules(self): + cfg = Config([ "-m" ] + self.someSimpleModules) + self.assertEquals(cfg.modules(), + map(lambda x: { "name": x, "module": x }, self.someSimpleModules)) # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/themes/default.json b/themes/default.json deleted file mode 100644 index ddda5fe..0000000 --- a/themes/default.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "icons": [ "ascii" ], - "defaults": { - "urgent": true, - "fg": "#aabbcc" - } -} diff --git a/themes/gruvbox-powerline.json b/themes/gruvbox-powerline.json deleted file mode 100644 index f04bbc7..0000000 --- a/themes/gruvbox-powerline.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "icons": [ "paxy97", "awesome-fonts" ], - "defaults": { - "prefix": " ", - "suffix" : " ", - "cycle": [ - { - "fg": "#ebdbb2", - "bg": "#1d2021" - }, - { - "fg": "#fbf1c7", - "bg": "#282828" - } - ], - "fg-critical": "#fbf1c7", - "bg-critical": "#cc241d", - "fg-warning": "#1d2021", - "bg-warning": "#d79921", - - "default-separators": false, - "separator-block-width": 0 - }, - "dnf": { - "states": { - "good": { - "fg": "#002b36", - "bg": "#859900" - } - } - }, - "battery": { - "states": { - "charged": { - "fg": "#1d2021", - "bg": "#b8bb26" - }, - "AC": { - "fg": "#1d2021", - "bg": "#b8bb26" - } - } - } -} diff --git a/themes/icons/ascii.json b/themes/icons/ascii.json deleted file mode 100644 index bd051ce..0000000 --- a/themes/icons/ascii.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "memory": { - "prefix": "ram" - }, - "cpu": { - "prefix": "cpu" - }, - "disk": { - "prefix": "hdd" - }, - "dnf": { - "prefix": "dnf" - }, - "brightness": { - "prefix": "o" - }, - "cmus": { - "states": { - "playing": { - "prefix": ">" - }, - "paused": { - "prefix": "||" - }, - "stopped": { - "prefix": "[]" - } - }, - "prev": { - "prefix": "|<" - }, - "next": { - "prefix": ">|" - }, - "shuffle": { - "states": { "on": { "prefix": "S" }, "off": { "prefix": "[s]" } } - }, - "repeat": { - "states": { "on": { "prefix": "R" }, "off": { "prefix": "[r]" } } - } - }, - "pasink": { - "states": { - "muted": { - "prefix": "audio(mute)" - }, - "unmuted": { - "prefix": "audio" - } - } - }, - "pasource": { - "states": { - "muted": { - "prefix": "mic(mute)" - }, - "unmuted": { - "prefix": "mic" - } - } - }, - "nic": { - "states": { - "wireless-up": { - "prefix": "wifi" - }, - "wireless-down": { - "prefix": "wifi" - }, - "wired-up": { - "prefix": "lan" - }, - "wired-down": { - "prefix": "lan" - }, - "tunnel-up": { - "prefix": "tun" - }, - "tunnel-down": { - "prefix": "tun" - } - } - }, - "battery": { - "states": { - "charged": { - "suffix": "full" - }, - "charging": { - "suffix": "chr" - }, - "AC": { - "suffix": "ac" - }, - "discharging-10": { - "prefix": "!", - "suffix": "dis" - }, - "discharging-25": { - "suffix": "dis" - }, - "discharging-50": { - "suffix": "dis" - }, - "discharging-80": { - "suffix": "dis" - }, - "discharging-100": { - "suffix": "dis" - } - } - }, - "caffeine": { - "states": { "activated": {"prefix": "caf-on" }, "deactivated": { "prefix": "caf-off " } } - }, - "xrandr": { - "states": { "on": { "prefix": " off "}, "off": { "prefix": " on "} } - } -} diff --git a/themes/icons/awesome-fonts.json b/themes/icons/awesome-fonts.json deleted file mode 100644 index 62d9294..0000000 --- a/themes/icons/awesome-fonts.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "defaults": { - "separator": "" - }, - "date": { - "prefix": "" - }, - "time": { - "prefix": "" - }, - "memory": { - "prefix": "" - }, - "cpu": { - "prefix": "" - }, - "disk": { - "prefix": "" - }, - "dnf": { - "prefix": "" - }, - "brightness": { - "prefix": "" - }, - "cmus": { - "states": { - "playing": { - "prefix": "" - }, - "paused": { - "prefix": "" - }, - "stopped": { - "prefix": "" - } - }, - "prev": { - "prefix": "" - }, - "next": { - "prefix": "" - }, - "shuffle": { - "states": { "on": { "prefix": "" }, "off": { "prefix": "" } } - }, - "repeat": { - "states": { "on": { "prefix": "" }, "off": { "prefix": "" } } - } - }, - "pasink": { - "states": { - "muted": { - "prefix": "" - }, - "unmuted": { - "prefix": "" - } - } - }, - "pasource": { - "states": { - "muted": { - "prefix": "" - }, - "unmuted": { - "prefix": "" - } - } - }, - "nic": { - "states": { - "wireless-up": { - "prefix": "" - }, - "wireless-down": { - "prefix": "" - }, - "wired-up": { - "prefix": "" - }, - "wired-down": { - "prefix": "" - }, - "tunnel-up": { - "prefix": "" - }, - "tunnel-down": { - "prefix": "" - } - } - }, - "battery": { - "states": { - "charged": { - "prefix": "", - "suffix": "" - }, - "AC": { - "suffix": "" - }, - "charging": { - "prefix": [ "", "", "", "", "" ], - "suffix": "" - }, - "discharging-10": { - "prefix": "", - "suffix": "" - }, - "discharging-25": { - "prefix": "", - "suffix": "" - }, - "discharging-50": { - "prefix": "", - "suffix": "" - }, - "discharging-80": { - "prefix": "", - "suffix": "" - }, - "discharging-100": { - "prefix": "", - "suffix": "" - } - } - }, - "caffeine": { - "states": { "activated": {"prefix": " " }, "deactivated": { "prefix": " " } } - }, - "xrandr": { - "states": { "on": { "prefix": " "}, "off": { "prefix": " "} } - } -} diff --git a/themes/icons/paxy97.json b/themes/icons/paxy97.json deleted file mode 100644 index 9a889ab..0000000 --- a/themes/icons/paxy97.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "memory": { - "prefix": "  " - } -} diff --git a/themes/powerline.json b/themes/powerline.json deleted file mode 100644 index bfec776..0000000 --- a/themes/powerline.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "icons": [ "awesome-fonts" ], - "defaults": { - "cycle": [ - { - "fg": "#ffd700", - "bg": "#d75f00" - }, - { - "fg": "#ffffff", - "bg": "#0087af" - } - ], - "fg-critical": "#ffffff", - "bg-critical": "#ff0000", - "fg-warning": "#d75f00", - "bg-warning": "#ffd700", - - "default_separators": false - }, - "dnf": { - "states": { - "good": { - "fg": "#494949", - "bg": "#41db00" - } - } - }, - "battery": { - "states": { - "charged": { - "fg": "#494949", - "bg": "#41db00" - }, - "AC": { - "fg": "#494949", - "bg": "#41db00" - } - } - } -} diff --git a/themes/solarized-powerline.json b/themes/solarized-powerline.json deleted file mode 100644 index 998b7f4..0000000 --- a/themes/solarized-powerline.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "icons": [ "awesome-fonts" ], - "defaults": { - "cycle": [ - { - "fg": "#93a1a1", - "bg": "#002b36" - }, - { - "fg": "#eee8d5", - "bg": "#586e75" - } - ], - "fg-critical": "#002b36", - "bg-critical": "#dc322f", - "fg-warning": "#002b36", - "bg-warning": "#b58900", - - "default-separators": false, - "separator-block-width": 0 - }, - "dnf": { - "states": { - "good": { - "fg": "#002b36", - "bg": "#859900" - } - } - }, - "battery": { - "states": { - "charged": { - "fg": "#002b36", - "bg": "#859900" - }, - "AC": { - "fg": "#002b36", - "bg": "#859900" - } - } - } -} diff --git a/themes/solarized.json b/themes/solarized.json deleted file mode 100644 index 5cc8f86..0000000 --- a/themes/solarized.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "icons": [ "ascii" ], - "defaults": { - "cycle": [ - { - "fg": "#93a1a1", - "bg": "#002b36" - }, - { - "fg": "#eee8d5", - "bg": "#586e75" - } - ], - "fg-critical": "#002b36", - "bg-critical": "#dc322f", - "fg-warning": "#002b36", - "bg-warning": "#b58900", - - "default_separators": false, - "separator": "" - }, - "dnf": { - "states": { - "good": { - "fg": "#002b36", - "bg": "#859900" - } - } - }, - "battery": { - "states": { - "charged": { - "fg": "#002b36", - "bg": "#859900" - }, - "AC": { - "fg": "#002b36", - "bg": "#859900" - } - } -}