Merge branch 'tobi-wan-kenobi:main' into main
This commit is contained in:
commit
3de6f9f4b9
16 changed files with 468 additions and 13 deletions
70
.github/workflows/codeql-analysis.yml
vendored
Normal file
70
.github/workflows/codeql-analysis.yml
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ main ]
|
||||
schedule:
|
||||
- cron: '31 0 * * 4'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'python' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
|
@ -8,6 +8,7 @@
|
|||
[![Code Climate](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status/badges/gpa.svg)](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status)
|
||||
[![Test Coverage](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status/badges/coverage.svg)](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status/coverage)
|
||||
[![Issue Count](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status/badges/issue_count.svg)](https://codeclimate.com/github/tobi-wan-kenobi/bumblebee-status)
|
||||
[![CodeQL](https://github.com/tobi-wan-kenobi/bumblebee-status/actions/workflows/codeql-analysis.yml/badge.svg?branch=main)](https://github.com/tobi-wan-kenobi/bumblebee-status/actions/workflows/codeql-analysis.yml)
|
||||
![License](https://img.shields.io/github/license/tobi-wan-kenobi/bumblebee-status)
|
||||
|
||||
**Many, many thanks to all contributors! I am still amazed by and deeply grateful for how many PRs this project gets.**
|
||||
|
|
|
@ -54,8 +54,11 @@ def register(obj, button=None, cmd=None, wait=False):
|
|||
event_id = __event_id(obj.id if obj is not None else "", button)
|
||||
logging.debug("registering callback {}".format(event_id))
|
||||
core.event.unregister(event_id) # make sure there's always only one input event
|
||||
|
||||
if callable(cmd):
|
||||
core.event.register_exclusive(event_id, cmd)
|
||||
elif obj and hasattr(obj, cmd) and callable(getattr(obj, cmd)):
|
||||
core.event.register_exclusive(event_id, lambda event: getattr(obj, cmd)(event))
|
||||
else:
|
||||
core.event.register_exclusive(event_id, lambda event: __execute(event, cmd, wait))
|
||||
|
||||
|
|
141
bumblebee_status/modules/contrib/pactl.py
Normal file
141
bumblebee_status/modules/contrib/pactl.py
Normal file
|
@ -0,0 +1,141 @@
|
|||
# pylint: disable=C0111,R0903
|
||||
|
||||
""" Displays the current default sink.
|
||||
|
||||
Left click opens a popup menu that lists all available sinks and allows to change the default sink.
|
||||
|
||||
Per default, this module uses the sink names returned by "pactl list sinks short"
|
||||
|
||||
sample output of "pactl list sinks short":
|
||||
|
||||
2 alsa_output.pci-0000_00_1f.3.analog-stereo module-alsa-card.c s16le 2ch 44100Hz SUSPENDED
|
||||
3 alsa_output.usb-Logitech_Logitech_USB_Headset-00.analog-stereo module-alsa-card.c s16le 2ch 44100Hz SUSPENDE
|
||||
|
||||
As "alsa_output.usb-Logitech_Logitech_USB_Headset-00.analog-stereo" is not a particularly nice name, its possible to map the name to more a
|
||||
user friendly name. e.g to map "alsa_output.usb-Logitech_Logitech_USB_Headset-00.analog-stereo" to the name "Headset", add the following
|
||||
bumblebee-status config entry: pactl.alsa_output.usb-Logitech_Logitech_USB_Headset-00.analog-stereo=Headset
|
||||
|
||||
The module also allows to specify individual (unicode) icons for all the sinks. e.g in order to use the icon 🎧 for the
|
||||
"alsa_output.usb-Logitech_Logitech_USB_Headset-00.analog-stereo" sink, add the following bumblebee-status config entry:
|
||||
pactl.icon.alsa_output.usb-Logitech_Logitech_USB_Headset-00.analog-stereo=🎧
|
||||
|
||||
Requirements:
|
||||
* pulseaudio
|
||||
* pactl
|
||||
"""
|
||||
|
||||
import logging
|
||||
import functools
|
||||
|
||||
import core.module
|
||||
import core.widget
|
||||
import core.input
|
||||
|
||||
import util.cli
|
||||
import util.popup
|
||||
|
||||
|
||||
class Sink(object):
|
||||
def __init__(self, id, internal_name, friendly_name, icon):
|
||||
super().__init__()
|
||||
self.__id = id
|
||||
self.__internal_name = internal_name
|
||||
self.__friendly_name = friendly_name
|
||||
self.__icon = icon
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self.__id
|
||||
|
||||
@property
|
||||
def internal_name(self):
|
||||
return self.__internal_name
|
||||
|
||||
@property
|
||||
def friendly_name(self):
|
||||
return self.__friendly_name
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
return self.__icon
|
||||
|
||||
@property
|
||||
def display_name(self):
|
||||
display_name = (
|
||||
self.__icon + " " + self.__friendly_name
|
||||
if self.__icon != ""
|
||||
else self.__friendly_name
|
||||
)
|
||||
return display_name
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.default_sink))
|
||||
|
||||
self.__default_sink = None
|
||||
|
||||
res = util.cli.execute("pactl list sinks short")
|
||||
lines = res.splitlines()
|
||||
|
||||
self.__sinks = []
|
||||
for line in lines:
|
||||
info = line.split("\t")
|
||||
try:
|
||||
friendly_name = self.parameter(info[1], info[1])
|
||||
icon = self.parameter("icon." + info[1], "")
|
||||
self.__sinks.append(Sink(info[0], info[1], friendly_name, icon))
|
||||
except:
|
||||
logging.exception("Couldn't parse sink")
|
||||
pass
|
||||
|
||||
core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.popup)
|
||||
|
||||
def __sink(self, internal_sink_name):
|
||||
for sink in self.__sinks:
|
||||
if internal_sink_name == sink.internal_name:
|
||||
return sink
|
||||
return None
|
||||
|
||||
def update(self):
|
||||
try:
|
||||
res = util.cli.execute("pactl info")
|
||||
lines = res.splitlines()
|
||||
self.__default_sink = None
|
||||
for line in lines:
|
||||
if not line.startswith("Default Sink:"):
|
||||
continue
|
||||
internal_sink_name = line.replace("Default Sink: ", "")
|
||||
self.__default_sink = self.__sink(internal_sink_name)
|
||||
break
|
||||
except Exception as e:
|
||||
logging.exception("Could not get pactl info")
|
||||
self.__default_sink = None
|
||||
|
||||
def default_sink(self, widget):
|
||||
if self.__default_sink is None:
|
||||
return "unknown"
|
||||
return self.__default_sink.display_name
|
||||
|
||||
def __on_sink_selected(self, sink):
|
||||
try:
|
||||
util.cli.execute("pactl set-default-sink {}".format(sink.id))
|
||||
self.__default_sink = sink
|
||||
except Exception as e:
|
||||
logging.exception("Couldn't set default sink")
|
||||
|
||||
def popup(self, widget):
|
||||
menu = util.popup.menu()
|
||||
|
||||
for sink in self.__sinks:
|
||||
menu.add_menuitem(
|
||||
sink.friendly_name,
|
||||
callback=functools.partial(self.__on_sink_selected, sink),
|
||||
)
|
||||
menu.show(widget)
|
||||
|
||||
def state(self, widget):
|
||||
return []
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
45
bumblebee_status/modules/contrib/persian_date.py
Normal file
45
bumblebee_status/modules/contrib/persian_date.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
# pylint: disable=C0111,R0903
|
||||
|
||||
"""Displays the current date and time in Persian(Jalali) Calendar.
|
||||
|
||||
Requires the following python packages:
|
||||
* jdatetime
|
||||
|
||||
Parameters:
|
||||
* datetime.format: strftime()-compatible formatting string. default: "%A %d %B" e.g., "جمعه ۱۳ اسفند"
|
||||
* datetime.locale: locale to use. default: "fa_IR"
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
import jdatetime
|
||||
import locale
|
||||
|
||||
import core.module
|
||||
import core.widget
|
||||
import core.input
|
||||
|
||||
|
||||
class Module(core.module.Module):
|
||||
def __init__(self, config, theme):
|
||||
super().__init__(config, theme, core.widget.Widget(self.full_text))
|
||||
|
||||
l = ("fa_IR", "UTF-8")
|
||||
lcl = self.parameter("locale", ".".join(l))
|
||||
try:
|
||||
locale.setlocale(locale.LC_ALL, lcl.split("."))
|
||||
except Exception as e:
|
||||
locale.setlocale(locale.LC_ALL, ("fa_IR", "UTF-8"))
|
||||
|
||||
def default_format(self):
|
||||
return "%A %d %B"
|
||||
|
||||
def full_text(self, widget):
|
||||
enc = locale.getpreferredencoding()
|
||||
fmt = self.parameter("format", self.default_format())
|
||||
retval = jdatetime.datetime.now().strftime(fmt)
|
||||
if hasattr(retval, "decode"):
|
||||
return retval.decode(enc)
|
||||
return retval
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
@ -16,13 +16,13 @@ class Module(core.module.Module):
|
|||
self.__ip = ""
|
||||
|
||||
def public_ip(self, widget):
|
||||
return self.__ip
|
||||
return self.__ip or "n/a"
|
||||
|
||||
def update(self):
|
||||
try:
|
||||
self.__ip = util.location.public_ip()
|
||||
except Exception:
|
||||
self.__ip = "n/a"
|
||||
self.__ip = None
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -55,7 +55,7 @@ class Module(core.module.Module):
|
|||
|
||||
self._state = []
|
||||
|
||||
self._newspaper_filename = tempfile.mktemp(".html")
|
||||
self._newspaper_file = tempfile.NamedTemporaryFile(mode="w", suffix=".html")
|
||||
|
||||
self._last_refresh = 0
|
||||
self._last_update = 0
|
||||
|
@ -308,10 +308,11 @@ class Module(core.module.Module):
|
|||
|
||||
while newspaper_items:
|
||||
content += self._create_news_section(newspaper_items)
|
||||
open(self._newspaper_filename, "w").write(
|
||||
self._newspaper_file.write(
|
||||
HTML_TEMPLATE.replace("[[CONTENT]]", content)
|
||||
)
|
||||
webbrowser.open("file://" + self._newspaper_filename)
|
||||
self._newspaper_file.flush()
|
||||
webbrowser.open("file://" + self._newspaper_file.name)
|
||||
self._update_history("newspaper")
|
||||
self._save_history()
|
||||
|
||||
|
|
|
@ -39,7 +39,11 @@ class Module(core.module.Module):
|
|||
self.__sun = None
|
||||
|
||||
if not lat or not lon:
|
||||
try:
|
||||
lat, lon = util.location.coordinates()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if lat and lon:
|
||||
self.__sun = Sun(float(lat), float(lon))
|
||||
|
||||
|
@ -55,6 +59,10 @@ class Module(core.module.Module):
|
|||
return "n/a"
|
||||
|
||||
def __calculate_times(self):
|
||||
if not self.__sun:
|
||||
self.__sunset = self.__sunrise = None
|
||||
return
|
||||
|
||||
self.__isup = False
|
||||
|
||||
order_matters = True
|
||||
|
|
|
@ -13,7 +13,9 @@ Parameters:
|
|||
* nic.exclude: Comma-separated list of interface prefixes (supporting regular expressions) to exclude (defaults to 'lo,virbr,docker,vboxnet,veth,br,.*:avahi')
|
||||
* nic.include: Comma-separated list of interfaces to include
|
||||
* nic.states: Comma-separated list of states to show (prefix with '^' to invert - i.e. ^down -> show all devices that are not in state down)
|
||||
* nic.format: Format string (defaults to '{intf} {state} {ip} {ssid}')
|
||||
* nic.format: Format string (defaults to '{intf} {state} {ip} {ssid} {strength}')
|
||||
* nic.strength_warning: Integer to set the threshold for warning state (defaults to 50)
|
||||
* nic.strength_critical: Integer to set the threshold for critical state (defaults to 30)
|
||||
"""
|
||||
|
||||
import re
|
||||
|
@ -28,7 +30,7 @@ import util.format
|
|||
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(seconds=10)
|
||||
@core.decorators.every(seconds=5)
|
||||
def __init__(self, config, theme):
|
||||
widgets = []
|
||||
super().__init__(config, theme, widgets)
|
||||
|
@ -45,7 +47,15 @@ class Module(core.module.Module):
|
|||
self._states["exclude"].append(state[1:])
|
||||
else:
|
||||
self._states["include"].append(state)
|
||||
self._format = self.parameter("format", "{intf} {state} {ip} {ssid}")
|
||||
self._format = self.parameter("format", "{intf} {state} {ip} {ssid} {strength}")
|
||||
|
||||
self._strength_threshold_critical = self.parameter("strength_critical", 30)
|
||||
self._strength_threshold_warning = self.parameter("strength_warning", 50)
|
||||
|
||||
# Limits for the accepted dBm values of wifi strength
|
||||
self.__strength_dbm_lower_bound = -110
|
||||
self.__strength_dbm_upper_bound = -30
|
||||
|
||||
self.iw = shutil.which("iw")
|
||||
self._update_widgets(widgets)
|
||||
|
||||
|
@ -64,6 +74,14 @@ class Module(core.module.Module):
|
|||
iftype = "wireless" if self._iswlan(intf) else "wired"
|
||||
iftype = "tunnel" if self._istunnel(intf) else iftype
|
||||
|
||||
# "strength" is none if interface type is not wlan
|
||||
strength = widget.get("strength")
|
||||
if self._iswlan(intf) and strength:
|
||||
if strength < self._strength_threshold_critical:
|
||||
states.append("critical")
|
||||
elif strength < self._strength_threshold_warning:
|
||||
states.append("warning")
|
||||
|
||||
states.append("{}-{}".format(iftype, widget.get("state")))
|
||||
|
||||
return states
|
||||
|
@ -116,6 +134,9 @@ class Module(core.module.Module):
|
|||
):
|
||||
continue
|
||||
|
||||
strength_dbm = self.get_strength_dbm(intf)
|
||||
strength_percent = self.convert_strength_dbm_percent(strength_dbm)
|
||||
|
||||
widget = self.widget(intf)
|
||||
if not widget:
|
||||
widget = self.add_widget(name=intf)
|
||||
|
@ -126,12 +147,14 @@ class Module(core.module.Module):
|
|||
ip=", ".join(addr),
|
||||
intf=intf,
|
||||
state=state,
|
||||
strength=str(strength_percent) + "%" if strength_percent else "",
|
||||
ssid=self.get_ssid(intf),
|
||||
).split()
|
||||
)
|
||||
)
|
||||
widget.set("intf", intf)
|
||||
widget.set("state", state)
|
||||
widget.set("strength", strength_percent)
|
||||
|
||||
def get_ssid(self, intf):
|
||||
if not self._iswlan(intf) or self._istunnel(intf) or not self.iw:
|
||||
|
@ -145,5 +168,23 @@ class Module(core.module.Module):
|
|||
|
||||
return ""
|
||||
|
||||
def get_strength_dbm(self, intf):
|
||||
if not self._iswlan(intf) or self._istunnel(intf) or not self.iw:
|
||||
return None
|
||||
|
||||
with open("/proc/net/wireless", "r") as file:
|
||||
for line in file:
|
||||
if intf in line:
|
||||
# Remove trailing . by slicing it off ;)
|
||||
strength_dbm = line.split()[3][:-1]
|
||||
return util.format.asint(strength_dbm,
|
||||
minimum=self.__strength_dbm_lower_bound,
|
||||
maximum=self.__strength_dbm_upper_bound)
|
||||
|
||||
return None
|
||||
|
||||
def convert_strength_dbm_percent(self, signal):
|
||||
return int(100 * ((signal + 100) / 70.0)) if signal else None
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -54,7 +54,7 @@ def get_redshift_value(module):
|
|||
for line in res.split("\n"):
|
||||
line = line.lower()
|
||||
if "temperature" in line:
|
||||
widget.set("temp", line.split(" ")[2])
|
||||
widget.set("temp", line.split(" ")[2].upper())
|
||||
if "period" in line:
|
||||
state = line.split(" ")[1]
|
||||
if "day" in state:
|
||||
|
|
|
@ -9,7 +9,7 @@ Parameters:
|
|||
import core.module
|
||||
import core.widget
|
||||
import core.decorators
|
||||
|
||||
import core.input
|
||||
|
||||
class Module(core.module.Module):
|
||||
@core.decorators.every(minutes=60)
|
||||
|
@ -20,5 +20,8 @@ class Module(core.module.Module):
|
|||
def text(self, _):
|
||||
return self.__text
|
||||
|
||||
def update_text(self, event):
|
||||
self.__text = core.input.button_name(event["button"])
|
||||
|
||||
|
||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||
|
|
|
@ -59,11 +59,11 @@ def __load():
|
|||
__next = time.time() + 60 * 30 # error - try again every 30m
|
||||
|
||||
|
||||
def __get(name, default=None):
|
||||
def __get(name):
|
||||
global __data
|
||||
if not __data or __expired():
|
||||
__load()
|
||||
return __data.get(name, default)
|
||||
return __data[name]
|
||||
|
||||
|
||||
def reset():
|
||||
|
|
|
@ -26,6 +26,15 @@ class PublicIPTest(TestCase):
|
|||
|
||||
assert widget(module).full_text() == '5.12.220.2'
|
||||
|
||||
@mock.patch('util.location.public_ip')
|
||||
def test_public_ip(self, public_ip_mock):
|
||||
public_ip_mock.return_value = None
|
||||
|
||||
module = build_module()
|
||||
module.update()
|
||||
|
||||
assert widget(module).full_text() == 'n/a'
|
||||
|
||||
@mock.patch('util.location.public_ip')
|
||||
def test_public_ip_with_exception(self, public_ip_mock):
|
||||
public_ip_mock.side_effect = Exception
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
"default-separators": false
|
||||
},
|
||||
"date": { "prefix": "" },
|
||||
"persian_date": { "prefix": "" },
|
||||
"time": { "prefix": "" },
|
||||
"datetime": { "prefix": "" },
|
||||
"datetz": { "prefix": "" },
|
||||
|
|
54
themes/rose-pine.json
Normal file
54
themes/rose-pine.json
Normal file
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"icons": ["awesome-fonts"],
|
||||
"defaults": {
|
||||
"separator-block-width": 0,
|
||||
"warning": {
|
||||
"fg": "#232136",
|
||||
"bg": "#f6c177"
|
||||
},
|
||||
"critical": {
|
||||
"fg": "#232136",
|
||||
"bg": "#eb6f92"
|
||||
}
|
||||
},
|
||||
"cycle": [
|
||||
{ "fg": "#232136", "bg": "#ea9a97" },
|
||||
{ "fg": "#e0def4", "bg": "#393552" }
|
||||
],
|
||||
"dnf": {
|
||||
"good": {
|
||||
"fg": "#232136",
|
||||
"bg": "#9ccfd8"
|
||||
}
|
||||
},
|
||||
"pacman": {
|
||||
"good": {
|
||||
"fg": "#232136",
|
||||
"bg": "#9ccfd8"
|
||||
}
|
||||
},
|
||||
"battery": {
|
||||
"charged": {
|
||||
"fg": "#232136",
|
||||
"bg": "#9ccfd8"
|
||||
},
|
||||
"AC": {
|
||||
"fg": "#232136",
|
||||
"bg": "#9ccfd8"
|
||||
}
|
||||
},
|
||||
"pomodoro": {
|
||||
"paused": {
|
||||
"fg": "#232136",
|
||||
"bg": "#f6c177"
|
||||
},
|
||||
"work": {
|
||||
"fg": "#232136",
|
||||
"bg": "#9ccfd8"
|
||||
},
|
||||
"break": {
|
||||
"fg": "#232136",
|
||||
"bg": "#c4a7e7"
|
||||
}
|
||||
}
|
||||
}
|
78
themes/zengarden-powerline-light.json
Normal file
78
themes/zengarden-powerline-light.json
Normal file
|
@ -0,0 +1,78 @@
|
|||
{
|
||||
"icons": [ "paxy97", "awesome-fonts" ],
|
||||
"defaults": {
|
||||
"warning": {
|
||||
"fg": "#353839",
|
||||
"bg": "#b38a32"
|
||||
},
|
||||
"critical": {
|
||||
"fg": "#353839",
|
||||
"bg": "#d94070"
|
||||
},
|
||||
"default-separators": false,
|
||||
"separator-block-width": 0
|
||||
},
|
||||
"fg": "#353839",
|
||||
"bg": "#c4b6a3",
|
||||
"dnf": {
|
||||
"good": {
|
||||
"fg": "#353839",
|
||||
"bg": "#378c5d"
|
||||
}
|
||||
},
|
||||
"apt": {
|
||||
"good": {
|
||||
"fg": "#353839",
|
||||
"bg": "#378c5d"
|
||||
}
|
||||
},
|
||||
"battery": {
|
||||
"charged": {
|
||||
"fg": "#353839",
|
||||
"bg": "#378c5d"
|
||||
},
|
||||
"AC": {
|
||||
"fg": "#353839",
|
||||
"bg": "#378c5d"
|
||||
}
|
||||
},
|
||||
"bluetooth": {
|
||||
"ON": {
|
||||
"fg": "#353839",
|
||||
"bg": "#378c5d"
|
||||
}
|
||||
},
|
||||
"git": {
|
||||
"modified": { "bg": "#174572" },
|
||||
"deleted": { "bg": "#ba1d58" },
|
||||
"new": { "bg": "#967117" }
|
||||
},
|
||||
"pomodoro": {
|
||||
"paused": {
|
||||
"fg": "#353839",
|
||||
"bg": "#d79921"
|
||||
},
|
||||
"work": {
|
||||
"fg": "#353839",
|
||||
"bg": "#378c5d"
|
||||
},
|
||||
"break": {
|
||||
"fg": "#353839",
|
||||
"bg": "#378c5d"
|
||||
}
|
||||
},
|
||||
"keys": {
|
||||
"Key.cmd": {
|
||||
"bg": "#477ab7"
|
||||
},
|
||||
"Key.shift": {
|
||||
"bg": "#b38a32"
|
||||
},
|
||||
"Key.ctrl": {
|
||||
"bg": "#377c8b"
|
||||
},
|
||||
"Key.alt": {
|
||||
"bg": "#e05b1f"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue