Compare commits

...

7 commits
v0.0.2 ... main

7 changed files with 150 additions and 122 deletions

View file

@ -24,6 +24,15 @@ cd easyconf-lemonbar
sudo sh install.sh sudo sh install.sh
``` ```
To uninstall from your system:
```sh
sudo sh uninstall.sh
```
This will leave your config file in place, should you ever reinstall eclb.
**To update: uninstall, then follow the installation instructions again.**
## Configuration and Usage ## Configuration and Usage
### Config File ### Config File
After installing, you will need to copy the example config file to your After installing, you will need to copy the example config file to your
@ -49,18 +58,22 @@ easyconf-lemonbar process. First, in the module configuration, specify which
signal to listen for, e.g. signal to listen for, e.g.
```yaml ```yaml
...
# Display a random number, and only update when we recieve the RTMIN+1 signal. # Display a random number, and only update when we recieve the RTMIN+1 signal.
- name: "random" random:
command: "python -c 'from random import randrange; print(randrange(1000))'" command: "python -c 'from random import randrange; print(randrange(1000))'"
refresh: 0 refresh: 0
signal: 1 signal: 1
format: format:
align: left align: left
...
``` ```
In the example above, the refresh is `0`. This means that the module *will never In the example above, the refresh is `0`. This means that the module *will never
refresh on its own*; it will wait for the RTMIN+1 signal. You may also configure refresh on its own*; it will wait for the RTMIN+1 signal. You may also configure
your module to both refresh on a time interval AND listen for a signal. your module to both refresh on a time interval AND listen for a signal. Also
note: multiple modules may listen for the same signal. They will all be
refreshed when the signal is recieved.
Unfortunately, to send the signal, you cant just `pkill easyconf-lemonbar`. You Unfortunately, to send the signal, you cant just `pkill easyconf-lemonbar`. You
have to read the PID from eclb's pidfile. I would recommend creating an alias in have to read the PID from eclb's pidfile. I would recommend creating an alias in

View file

@ -2,8 +2,8 @@
# where indicated. # where indicated.
bar: bar:
# Global configuration options. These are mostly flags passed to lemonbar at # Global configuration options. These are mostly flags passed to lemonbar at
# runtime. # runtime. These are all optional.
config: #config:
# Define a custom size of the bar. By default, this is different for every # Define a custom size of the bar. By default, this is different for every
# screen, so the format is shown below. # screen, so the format is shown below.
#geometry: "widthxheight+x+y" #geometry: "widthxheight+x+y"
@ -52,16 +52,19 @@ bar:
# Text to be placed on both ends of the bar, before and after all text. # Text to be placed on both ends of the bar, before and after all text.
#margin: "" #margin: ""
# Here is where you can define a list your individual modules. You can define # Modules are organized by monitor number, starting at 0 and increasing to 9.
# as many modules as you want. Some fields are required; these will be monitor:
# indicated. If a field doesn't say its required, you can safely omit it in 0:
# your own configuration. A "bare minimum" configuration is shown below for # Within each monitor is where you can define a your individual modules.
# your convience. # You can define as many modules as you want. Some fields are required;
# these will be indicated. If a field doesn't say its required, you can
# safely omit it in your own configuration. A "bare minimum" configuration
# is shown below for your convience.
modules: modules:
# This is an example module. You can name it whatever you want, it doesn't # The top field is the name of the module. This can be whatever you
# matter. Notice the `-` before the name. Each module must be a list item! # want, it doesn't matter. Because this is an example module, we will
# THIS IS A REQUIRED FIELD. # call it 'example.'
#- name: "time" #example:
# # This command is run by `sh -c`, and whatever is sent to stdout is the # # This command is run by `sh -c`, and whatever is sent to stdout is the
# # text that will be displayed for this module. `date` here is used as an # # text that will be displayed for this module. `date` here is used as an
# # example. THIS IS A REQUIRED FIELD. # # example. THIS IS A REQUIRED FIELD.
@ -108,7 +111,7 @@ bar:
# command: "echo 'hello' > ~/file.txt" # command: "echo 'hello' > ~/file.txt"
# Here is a simpler example to more clearly show only the required fields. # Here is a simpler example to more clearly show only the required fields.
- name: "bare_minimum" bare_minimum:
command: "whoami" command: "whoami"
refresh: 1000 refresh: 1000
format: format:

View file

@ -1,20 +1,20 @@
class Bar: class Bar:
def __init__(self, seperator, margin): def __init__(self, seperator, margin):
self.left = [] self.monitors = {}
self.center = []
self.right = []
self.seperator = seperator self.seperator = seperator
self.margin = margin self.margin = margin
def add_module(self, module): def add_monitor(self, monitor):
self.monitors[monitor] = { "left": [], "center": [], "right": [] }
def add_module(self, monitor, module):
match module.alignment: match module.alignment:
case "left": case "left":
self.left.append(module) self.monitors[monitor]["left"].append(module)
case "center": case "center":
self.center.append(module) self.monitors[monitor]["center"].append(module)
case "right": case "right":
self.right.append(module) self.monitors[monitor]["right"].append(module)
def __print_alignment_group(self, alignment_group): def __print_alignment_group(self, alignment_group):
for index, module in enumerate(alignment_group): for index, module in enumerate(alignment_group):
@ -26,13 +26,17 @@ class Bar:
break break
def print(self): def print(self):
for monitor in self.monitors:
print("%{S" + str(monitor) + "}", end='')
print("%{l}" + self.margin, end='') print("%{l}" + self.margin, end='')
self.__print_alignment_group(self.left) self.__print_alignment_group(self.monitors[monitor]["left"])
print("%{c}", end='') print("%{c}", end='')
self.__print_alignment_group(self.center) self.__print_alignment_group(self.monitors[monitor]["center"])
print("%{r}", end='') print("%{r}", end='')
self.__print_alignment_group(self.right) self.__print_alignment_group(self.monitors[monitor]["right"])
print(self.margin, flush=True) print(self.margin, end='')
print(flush=True)

View file

@ -6,8 +6,9 @@ class SignalRouter:
self.signal_thread_dictionary = {} self.signal_thread_dictionary = {}
def __route_signal(self, signal, frame): def __route_signal(self, signal, frame):
pthread_kill(self.signal_thread_dictionary[signal], signal) for thread_ident in self.signal_thread_dictionary[signal]:
pthread_kill(thread_ident, signal)
def register_signal_thread(self, signal, thread_ident): def register_signal_thread(self, signal, thread_ident):
self.signal_thread_dictionary[signal] = thread_ident self.signal_thread_dictionary.setdefault(signal, []).append(thread_ident)
sigsignal(signal, self.__route_signal) sigsignal(signal, self.__route_signal)

View file

@ -1,7 +1,8 @@
from parse_config_file import get_bar_config_and_module_config_list
from os import getenv from os import getenv
from os.path import exists from os.path import exists
from easyconf_lemonbar.parse_config_file import get_bar_config_and_monitor_list
def generate_flags(bar_config): def generate_flags(bar_config):
flags = "" flags = ""
for option in bar_config: for option in bar_config:
@ -33,6 +34,6 @@ if exists("./data/testing_config.yml"):
else: else:
config_file = str(getenv("HOME")) + "/.config/easyconf-lemonbar.yml" config_file = str(getenv("HOME")) + "/.config/easyconf-lemonbar.yml"
bar_config, module_config_list = get_bar_config_and_module_config_list(config_file) bar_config, monitor_list = get_bar_config_and_monitor_list(config_file)
print(generate_flags(bar_config)) print(generate_flags(bar_config))

View file

@ -5,7 +5,7 @@ from os.path import exists
from SignalRouter import SignalRouter from SignalRouter import SignalRouter
from Bar import Bar from Bar import Bar
from Module import Module from Module import Module
from parse_config_file import get_bar_config_and_module_config_list from parse_config_file import get_bar_config_and_monitor_list
def sigterm_handler(signal, frame): def sigterm_handler(signal, frame):
delete_pidfile(pidfile_name()) delete_pidfile(pidfile_name())
@ -17,7 +17,7 @@ def main():
else: else:
config_file = str(getenv("HOME")) + "/.config/easyconf-lemonbar.yml" config_file = str(getenv("HOME")) + "/.config/easyconf-lemonbar.yml"
bar_config, module_config_list = get_bar_config_and_module_config_list(config_file) bar_config, monitor_list = get_bar_config_and_monitor_list(config_file)
padding = bar_config["padding"] padding = bar_config["padding"]
seperator = bar_config["seperator"] seperator = bar_config["seperator"]
margin = bar_config["margin"] margin = bar_config["margin"]
@ -26,9 +26,12 @@ def main():
bar = Bar(seperator, margin) bar = Bar(seperator, margin)
for module_config in module_config_list: for monitor in monitor_list:
bar.add_monitor(monitor)
module_config_list = monitor_list[monitor]["modules"]
for module_config in module_config_list.values():
module = Module(module_config, padding, bar) module = Module(module_config, padding, bar)
bar.add_module(module) bar.add_module(monitor, module)
module.start_thread() module.start_thread()
if module.signal != 0: if module.signal != 0:
signal_router.register_signal_thread(module.signal, module.ident) signal_router.register_signal_thread(module.signal, module.ident)

View file

@ -2,7 +2,7 @@ from yaml import safe_load
from schema import And, Optional, Regex, Schema, SchemaError, Or from schema import And, Optional, Regex, Schema, SchemaError, Or
from signal import SIGRTMIN, SIGRTMAX from signal import SIGRTMIN, SIGRTMAX
def get_bar_config_and_module_config_list(filename): def get_bar_config_and_monitor_list(filename):
config_schema = Schema({ config_schema = Schema({
"bar": { "bar": {
Optional("config"): { Optional("config"): {
@ -20,9 +20,10 @@ def get_bar_config_and_module_config_list(filename):
Optional("seperator", default="|"): str, Optional("seperator", default="|"): str,
Optional("margin", default=""): str Optional("margin", default=""): str
}, },
"modules": [ "monitor": {
{ And(int, lambda n: 0 <= n <= 9): {
"name": str, "modules": {
str: {
"command": str, "command": str,
"refresh": And(int, lambda n : n >= 0), "refresh": And(int, lambda n : n >= 0),
Optional("prefix"): str, Optional("prefix"): str,
@ -42,11 +43,13 @@ def get_bar_config_and_module_config_list(filename):
# "activator": Or("left", "center", "right", "scrup", "scrdown"), # "activator": Or("left", "center", "right", "scrup", "scrdown"),
# "command": str # "command": str
#} #}
}
}
]
} }
}
}
}
}
}
}) })
with open(filename, "r", encoding="utf8") as file: with open(filename, "r", encoding="utf8") as file:
@ -54,6 +57,6 @@ def get_bar_config_and_module_config_list(filename):
try: try:
validated_config = config_schema.validate(config_file) validated_config = config_schema.validate(config_file)
return validated_config["bar"]["config"], validated_config["bar"]["modules"] return validated_config["bar"]["config"], validated_config["bar"]["monitor"]
except SchemaError as se: except SchemaError as se:
raise se raise se