[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
82
README.md
|
@ -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 = <path to bumblebee-status/bumblebee-status> -m <list of modules> -p <list of module parameters> -t <theme>
|
||||
}
|
||||
```
|
||||
|
||||
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)
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
18
bumblebee-status
Executable file → Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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"
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -1 +0,0 @@
|
|||
datetime.py
|
|
@ -1 +0,0 @@
|
|||
time.py
|
|
@ -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
|
|
@ -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 <security>/<bugfixes>/<enhancements>/<other> 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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -1 +0,0 @@
|
|||
pulseaudio.py
|
|
@ -1 +0,0 @@
|
|||
pulseaudio.py
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 860 B |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 521 B |
Before Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.6 KiB |
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"icons": [ "ascii" ],
|
||||
"defaults": {
|
||||
"urgent": true,
|
||||
"fg": "#aabbcc"
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 "} }
|
||||
}
|
||||
}
|
|
@ -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": " "} }
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"memory": {
|
||||
"prefix": " "
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|