Compare commits
7 commits
Author | SHA1 | Date | |
---|---|---|---|
9db20eb942 | |||
7ad72a2914 | |||
a3ea319051 | |||
005fd42823 | |||
841218a6b7 | |||
90bbfcd7fe | |||
09be7cd6da |
7 changed files with 150 additions and 122 deletions
27
README.md
27
README.md
|
@ -24,6 +24,15 @@ cd easyconf-lemonbar
|
|||
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
|
||||
### Config File
|
||||
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.
|
||||
|
||||
```yaml
|
||||
...
|
||||
# Display a random number, and only update when we recieve the RTMIN+1 signal.
|
||||
- name: "random"
|
||||
command: "python -c 'from random import randrange; print(randrange(1000))'"
|
||||
refresh: 0
|
||||
signal: 1
|
||||
format:
|
||||
align: left
|
||||
random:
|
||||
command: "python -c 'from random import randrange; print(randrange(1000))'"
|
||||
refresh: 0
|
||||
signal: 1
|
||||
format:
|
||||
align: left
|
||||
...
|
||||
```
|
||||
|
||||
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
|
||||
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
|
||||
have to read the PID from eclb's pidfile. I would recommend creating an alias in
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
# where indicated.
|
||||
bar:
|
||||
# Global configuration options. These are mostly flags passed to lemonbar at
|
||||
# runtime.
|
||||
config:
|
||||
# runtime. These are all optional.
|
||||
#config:
|
||||
# Define a custom size of the bar. By default, this is different for every
|
||||
# screen, so the format is shown below.
|
||||
#geometry: "widthxheight+x+y"
|
||||
|
@ -51,65 +51,68 @@ bar:
|
|||
|
||||
# Text to be placed on both ends of the bar, before and after all text.
|
||||
#margin: ""
|
||||
|
||||
# Modules are organized by monitor number, starting at 0 and increasing to 9.
|
||||
monitor:
|
||||
0:
|
||||
# Within each monitor is where you can define a your individual modules.
|
||||
# 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:
|
||||
# The top field is the name of the module. This can be whatever you
|
||||
# want, it doesn't matter. Because this is an example module, we will
|
||||
# call it 'example.'
|
||||
#example:
|
||||
# # 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
|
||||
# # example. THIS IS A REQUIRED FIELD.
|
||||
# command: "date"
|
||||
# # How often (in milliseconds) to re-run the command and display the
|
||||
# # updated text. If this value is 0, then the module will not be
|
||||
# # refreshed. THIS IS A REQUIRED FIELD.
|
||||
# refresh: 1000
|
||||
# # Prefix to be printed before the text of the command.
|
||||
# prefix: "DATE: "
|
||||
# # Linux real-time signal that, when received, will refresh the module
|
||||
# # instantly. See the README for more info.
|
||||
# signal: 0
|
||||
# # Formatting options. These will only affect the text and padding of this
|
||||
# # module.
|
||||
# format:
|
||||
# # Where the text should be placed on the bar. `left`, `right`, or
|
||||
# # `center`. THIS IS A REQUIRED FIELD.
|
||||
# align: left
|
||||
# # Background color of the bar.
|
||||
# bg_color: "#000"
|
||||
# # Text color
|
||||
# fg_color: "#FFF"
|
||||
# # INDEX of the font for this module to be displayed in (see above).
|
||||
# font: 1
|
||||
# # Horizontal offset of the module text in pixels (can be negative).
|
||||
# offset: 0
|
||||
# # Set an underline or overline
|
||||
# line:
|
||||
# # Self-explanatory. `underline` or `overline`. IF you set a line, then
|
||||
# # this is a required field.
|
||||
# type: underline
|
||||
# # Set a custom color for the line.
|
||||
# color: "#000"
|
||||
# # Make this module act like a button. Both of these fields are required
|
||||
# # if you are making a button. You may also define multiple buttons with
|
||||
# # different activators for a single module.
|
||||
# button:
|
||||
# # What mouse click you have to make to activate the button. Can be
|
||||
# # `left`, `center`, or `right`. You can also set it to activate when
|
||||
# # you scroll up or down with `scrup` and `scrdown.`
|
||||
# activator: left
|
||||
# # Command to be executed upon activation. Will be run with `sh -c`.
|
||||
# command: "echo 'hello' > ~/file.txt"
|
||||
|
||||
# Here is where you can define a list your individual modules. 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:
|
||||
# This is an example module. You can name it whatever you want, it doesn't
|
||||
# matter. Notice the `-` before the name. Each module must be a list item!
|
||||
# THIS IS A REQUIRED FIELD.
|
||||
#- name: "time"
|
||||
# # 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
|
||||
# # example. THIS IS A REQUIRED FIELD.
|
||||
# command: "date"
|
||||
# # How often (in milliseconds) to re-run the command and display the
|
||||
# # updated text. If this value is 0, then the module will not be
|
||||
# # refreshed. THIS IS A REQUIRED FIELD.
|
||||
# refresh: 1000
|
||||
# # Prefix to be printed before the text of the command.
|
||||
# prefix: "DATE: "
|
||||
# # Linux real-time signal that, when received, will refresh the module
|
||||
# # instantly. See the README for more info.
|
||||
# signal: 0
|
||||
# # Formatting options. These will only affect the text and padding of this
|
||||
# # module.
|
||||
# format:
|
||||
# # Where the text should be placed on the bar. `left`, `right`, or
|
||||
# # `center`. THIS IS A REQUIRED FIELD.
|
||||
# align: left
|
||||
# # Background color of the bar.
|
||||
# bg_color: "#000"
|
||||
# # Text color
|
||||
# fg_color: "#FFF"
|
||||
# # INDEX of the font for this module to be displayed in (see above).
|
||||
# font: 1
|
||||
# # Horizontal offset of the module text in pixels (can be negative).
|
||||
# offset: 0
|
||||
# # Set an underline or overline
|
||||
# line:
|
||||
# # Self-explanatory. `underline` or `overline`. IF you set a line, then
|
||||
# # this is a required field.
|
||||
# type: underline
|
||||
# # Set a custom color for the line.
|
||||
# color: "#000"
|
||||
# # Make this module act like a button. Both of these fields are required
|
||||
# # if you are making a button. You may also define multiple buttons with
|
||||
# # different activators for a single module.
|
||||
# button:
|
||||
# # What mouse click you have to make to activate the button. Can be
|
||||
# # `left`, `center`, or `right`. You can also set it to activate when
|
||||
# # you scroll up or down with `scrup` and `scrdown.`
|
||||
# activator: left
|
||||
# # Command to be executed upon activation. Will be run with `sh -c`.
|
||||
# command: "echo 'hello' > ~/file.txt"
|
||||
|
||||
# Here is a simpler example to more clearly show only the required fields.
|
||||
- name: "bare_minimum"
|
||||
command: "whoami"
|
||||
refresh: 1000
|
||||
format:
|
||||
align: right
|
||||
# Here is a simpler example to more clearly show only the required fields.
|
||||
bare_minimum:
|
||||
command: "whoami"
|
||||
refresh: 1000
|
||||
format:
|
||||
align: right
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
class Bar:
|
||||
def __init__(self, seperator, margin):
|
||||
self.left = []
|
||||
self.center = []
|
||||
self.right = []
|
||||
|
||||
self.monitors = {}
|
||||
self.seperator = seperator
|
||||
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:
|
||||
case "left":
|
||||
self.left.append(module)
|
||||
self.monitors[monitor]["left"].append(module)
|
||||
case "center":
|
||||
self.center.append(module)
|
||||
self.monitors[monitor]["center"].append(module)
|
||||
case "right":
|
||||
self.right.append(module)
|
||||
self.monitors[monitor]["right"].append(module)
|
||||
|
||||
def __print_alignment_group(self, alignment_group):
|
||||
for index, module in enumerate(alignment_group):
|
||||
|
@ -26,13 +26,17 @@ class Bar:
|
|||
break
|
||||
|
||||
def print(self):
|
||||
print("%{l}" + self.margin, end='')
|
||||
self.__print_alignment_group(self.left)
|
||||
for monitor in self.monitors:
|
||||
print("%{S" + str(monitor) + "}", end='')
|
||||
print("%{l}" + self.margin, end='')
|
||||
self.__print_alignment_group(self.monitors[monitor]["left"])
|
||||
|
||||
print("%{c}", end='')
|
||||
self.__print_alignment_group(self.center)
|
||||
print("%{c}", end='')
|
||||
self.__print_alignment_group(self.monitors[monitor]["center"])
|
||||
|
||||
print("%{r}", end='')
|
||||
self.__print_alignment_group(self.right)
|
||||
print("%{r}", end='')
|
||||
self.__print_alignment_group(self.monitors[monitor]["right"])
|
||||
|
||||
print(self.margin, flush=True)
|
||||
print(self.margin, end='')
|
||||
|
||||
print(flush=True)
|
||||
|
|
|
@ -6,8 +6,9 @@ class SignalRouter:
|
|||
self.signal_thread_dictionary = {}
|
||||
|
||||
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):
|
||||
self.signal_thread_dictionary[signal] = thread_ident
|
||||
self.signal_thread_dictionary.setdefault(signal, []).append(thread_ident)
|
||||
sigsignal(signal, self.__route_signal)
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
from parse_config_file import get_bar_config_and_module_config_list
|
||||
from os import getenv
|
||||
from os.path import exists
|
||||
|
||||
from easyconf_lemonbar.parse_config_file import get_bar_config_and_monitor_list
|
||||
|
||||
def generate_flags(bar_config):
|
||||
flags = ""
|
||||
for option in bar_config:
|
||||
|
@ -33,6 +34,6 @@ if exists("./data/testing_config.yml"):
|
|||
else:
|
||||
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))
|
||||
|
|
|
@ -5,7 +5,7 @@ from os.path import exists
|
|||
from SignalRouter import SignalRouter
|
||||
from Bar import Bar
|
||||
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):
|
||||
delete_pidfile(pidfile_name())
|
||||
|
@ -17,7 +17,7 @@ def main():
|
|||
else:
|
||||
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"]
|
||||
seperator = bar_config["seperator"]
|
||||
margin = bar_config["margin"]
|
||||
|
@ -26,12 +26,15 @@ def main():
|
|||
|
||||
bar = Bar(seperator, margin)
|
||||
|
||||
for module_config in module_config_list:
|
||||
module = Module(module_config, padding, bar)
|
||||
bar.add_module(module)
|
||||
module.start_thread()
|
||||
if module.signal != 0:
|
||||
signal_router.register_signal_thread(module.signal, module.ident)
|
||||
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)
|
||||
bar.add_module(monitor, module)
|
||||
module.start_thread()
|
||||
if module.signal != 0:
|
||||
signal_router.register_signal_thread(module.signal, module.ident)
|
||||
|
||||
create_pidfile(pidfile_name())
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ from yaml import safe_load
|
|||
from schema import And, Optional, Regex, Schema, SchemaError, Or
|
||||
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({
|
||||
"bar": {
|
||||
Optional("config"): {
|
||||
|
@ -20,32 +20,35 @@ def get_bar_config_and_module_config_list(filename):
|
|||
Optional("seperator", default="|"): str,
|
||||
Optional("margin", default=""): str
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"name": str,
|
||||
"command": str,
|
||||
"refresh": And(int, lambda n : n >= 0),
|
||||
Optional("prefix"): str,
|
||||
Optional("signal"): And(int, lambda n : SIGRTMIN <= SIGRTMIN+n <= SIGRTMAX),
|
||||
"format": {
|
||||
"align": Or("left", "center", "right"),
|
||||
Optional("bg_color"): Regex(r'^#[0-9a-fA-F]{3}$|^#[0-9a-fA-F]{6}$|^#[0-9a-fA-F]{8}$'),
|
||||
Optional("fg_color"): Regex(r'^#[0-9a-fA-F]{3}$|^#[0-9a-fA-F]{6}$|^#[0-9a-fA-F]{8}$'),
|
||||
Optional("font"): And(int, lambda n: 1 <= n <= 5),
|
||||
Optional("offset"): int,
|
||||
Optional("line"): {
|
||||
"type": Or("underline", "overline"),
|
||||
Optional("color"): Regex(r'^#[0-9a-fA-F]{3}$|^#[0-9a-fA-F]{6}$|^#[0-9a-fA-F]{8}$')
|
||||
"monitor": {
|
||||
And(int, lambda n: 0 <= n <= 9): {
|
||||
"modules": {
|
||||
str: {
|
||||
"command": str,
|
||||
"refresh": And(int, lambda n : n >= 0),
|
||||
Optional("prefix"): str,
|
||||
Optional("signal"): And(int, lambda n : SIGRTMIN <= SIGRTMIN+n <= SIGRTMAX),
|
||||
"format": {
|
||||
"align": Or("left", "center", "right"),
|
||||
Optional("bg_color"): Regex(r'^#[0-9a-fA-F]{3}$|^#[0-9a-fA-F]{6}$|^#[0-9a-fA-F]{8}$'),
|
||||
Optional("fg_color"): Regex(r'^#[0-9a-fA-F]{3}$|^#[0-9a-fA-F]{6}$|^#[0-9a-fA-F]{8}$'),
|
||||
Optional("font"): And(int, lambda n: 1 <= n <= 5),
|
||||
Optional("offset"): int,
|
||||
Optional("line"): {
|
||||
"type": Or("underline", "overline"),
|
||||
Optional("color"): Regex(r'^#[0-9a-fA-F]{3}$|^#[0-9a-fA-F]{6}$|^#[0-9a-fA-F]{8}$')
|
||||
}
|
||||
# Not yet implemented.
|
||||
#Optional("button"): {
|
||||
# "activator": Or("left", "center", "right", "scrup", "scrdown"),
|
||||
# "command": str
|
||||
#}
|
||||
|
||||
}
|
||||
}
|
||||
# Not yet implemented.
|
||||
#Optional("button"): {
|
||||
# "activator": Or("left", "center", "right", "scrup", "scrdown"),
|
||||
# "command": str
|
||||
#}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -54,6 +57,6 @@ def get_bar_config_and_module_config_list(filename):
|
|||
|
||||
try:
|
||||
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:
|
||||
raise se
|
||||
|
|
Loading…
Reference in a new issue