From f20c2a1d7669e8dcd8a6b76fc76cbe2684eaf081 Mon Sep 17 00:00:00 2001 From: Noah Swerhun Date: Sat, 11 Mar 2023 16:51:30 -0600 Subject: [PATCH] class groundwork laid --- easyconf-lemonbar/Module.py | 103 ++++++++++++++ easyconf-lemonbar/main.py | 131 +++++++++--------- ...config_parsing.py => parse_config_file.py} | 14 +- poetry.lock | 83 +++++++++++ poetry.toml | 2 + pyproject.toml | 18 +++ requirements.txt | 2 + 7 files changed, 283 insertions(+), 70 deletions(-) create mode 100644 easyconf-lemonbar/Module.py rename easyconf-lemonbar/{config_parsing.py => parse_config_file.py} (92%) create mode 100644 poetry.lock create mode 100644 poetry.toml create mode 100644 pyproject.toml create mode 100644 requirements.txt diff --git a/easyconf-lemonbar/Module.py b/easyconf-lemonbar/Module.py new file mode 100644 index 0000000..c3215c0 --- /dev/null +++ b/easyconf-lemonbar/Module.py @@ -0,0 +1,103 @@ +from threading import Thread +from subprocess import run +from time import sleep + +class Module: + # All text that the module contains. Will be re-generated every time the + # module refreshes. + text = "" + + # Parse the raw module configuration + def __init__(self, module_config, padding): + # Attributes that will be extracted from the config + self.name = "" + self.alignment = "" + self.pre = "" + self.prefix = "" + self.command = "" + self.refresh = 0 + self.post ="" + self.padding = padding + + for option in module_config: + match option: + case "name": + self.name = module_config[option] + case "command": + self.command = module_config[option] + case "refresh": + self.refresh = module_config[option] + case "prefix": + self.prefix = module_config[option] + + format_options = module_config["format"] + for option in format_options: + match option: + case "align": + self.alignment = format_options[option] + case "offset": + self.pre = ("%{O" + str(format_options[option]) + "}") + self.pre + case "bg_color": + self.pre = ("%{B" + format_options[option] + "}") + self.pre + self.post += "%{B-}" + case "fg_color": + self.pre = ("%{F" + format_options[option] + "}") + self.pre + self.post += "%{F-}" + case "font": + self.pre = ("%{T" + format_options[option] + "}") + self.pre + self.post += "%{T-}" + case "line": + line_options = format_options[option] + for line_option in line_options: + match line_option: + case "type": + if line_options[line_option] == "underline": + self.pre = ("%{+u}") + self.pre + self.post += ("%{-u}") + elif line_options[line_option] == "overline": + self.pre = ("%{+o}") + self.pre + self.post += ("%{-o}") + case "color": + self.pre = ("%{U" + line_options[line_option] + "}") + self.pre + self.post += "%{U-}" + case "button": + button_options = format_options[option] + button = 1 + match button_options["activator"]: + case "left": + button = 1 + case "middle": + button = 2 + case "right": + button = 3 + case "scrup": + button = 4 + case "scrdown": + button = 5 + self.pre = ("%{A" + str(button)+ ":" + button_options["command"] + ":}") + self.pre + self.post += "%{A}" + + def get_text(self): + return self.text + + def generate_text(self): + text = self.pre + self.padding + self.prefix + text += run(self.command, shell=True, capture_output=True, text=True).stdout.strip() + text += self.padding + self.post + self.text = text + + def thread_callback(self): + self.generate_text() + print(self.text) + #while True: + # self.text = self.generate_text() + # #print_bar() + # if self.refresh == 0: + # break + # sleep(self.refresh/1000) + + def start_thread(self): + thread = Thread(target=self.thread_callback) + thread.start() + + diff --git a/easyconf-lemonbar/main.py b/easyconf-lemonbar/main.py index d4ee27e..2ea0f1a 100644 --- a/easyconf-lemonbar/main.py +++ b/easyconf-lemonbar/main.py @@ -1,73 +1,76 @@ -from threading import Thread -from subprocess import run -from time import sleep -from config_parsing import get_validated_config, parse_module - -running_modules_dict = {"left": {}, "center": {}, "right": {}} - -def print_bar(): - for alignment in running_modules_dict: - match alignment: - case "left": - print("%{l}" + margin, end="") - case "center": - print("%{c}", end="") - case "right": - print("%{r}", end="") - # convert group to list so we can access subsequent items - group = list(running_modules_dict[alignment].values()) - for index, module in enumerate(group): - print(module, end="") - # IF module is not the last AND it has text - if index != (len(group) - 1) and len(module) > 0: - # THEN only print seperator if the module is eventually followed - # by a module with text - for i in range(index + 1, len(group)): - if len(group[i]) > 0: - print(seperator, end="") - break; - if alignment == "right": - print(margin, end="") - - print(flush=True) - -def create_module_string(pre, prefix, command, post): - cmd_output = run(command, shell=True, capture_output=True, text=True).stdout.strip() - if cmd_output != "": - return (pre + padding + prefix + cmd_output + padding + post) - else: - return cmd_output - - -def new_module_thread(alignment, pre, name, prefix, command, post, refresh): - running_modules_dict[alignment][name] = "" - while True: - module_string = create_module_string(pre, prefix, command, post) - running_modules_dict[alignment][name] = module_string - print_bar() - if refresh == 0: - break - sleep(refresh/1000) +from Module import Module +from parse_config_file import get_bar_config_and_module_config_list +#from threading import Thread +#from subprocess import run +#from time import sleep +#from config_parsing import get_validated_config, parse_module +# +#running_modules_dict = {"left": {}, "center": {}, "right": {}} +# +#def print_bar(): +# for alignment in running_modules_dict: +# match alignment: +# case "left": +# print("%{l}" + margin, end="") +# case "center": +# print("%{c}", end="") +# case "right": +# print("%{r}", end="") +# # convert group to list so we can access subsequent items +# group = list(running_modules_dict[alignment].values()) +# for index, module in enumerate(group): +# print(module, end="") +# # IF module is not the last AND it has text +# if index != (len(group) - 1) and len(module) > 0: +# # THEN only print seperator if the module is eventually followed +# # by a module with text +# for i in range(index + 1, len(group)): +# if len(group[i]) > 0: +# print(seperator, end="") +# break; +# if alignment == "right": +# print(margin, end="") +# +# print(flush=True) +# +#def create_module_string(pre, prefix, command, post): +# cmd_output = run(command, shell=True, capture_output=True, text=True).stdout.strip() +# if cmd_output != "": +# return (pre + padding + prefix + cmd_output + padding + post) +# else: +# return cmd_output +# +# +#def new_module_thread(alignment, pre, name, prefix, command, post, refresh): +# running_modules_dict[alignment][name] = "" +# while True: +# module_string = create_module_string(pre, prefix, command, post) +# running_modules_dict[alignment][name] = module_string +# print_bar() +# if refresh == 0: +# break +# sleep(refresh/1000) def main(): - global padding - global seperator - global margin + bar_config, module_config_list = get_bar_config_and_module_config_list("/home/noah/src/easyconf-lemonbar/data/testing_config.yml") + padding = bar_config["padding"] + left_modules = [] + center_modules = [] + right_modules = [] - config = get_validated_config("./testing_config.yml") - padding = config["bar"]["config"]["padding"] - seperator = config["bar"]["config"]["seperator"] - margin = config["bar"]["config"]["margin"] + for module_config in module_config_list: + module = Module(module_config, padding) + match module.alignment: + case "left": + left_modules.append(module) + case "center": + center_modules.append(module) + case "right": + right_modules.append(module) + module.start_thread() - modules = config["bar"]["modules"] - for module in modules: - parameters = parse_module(module) - # print(parameters) - - x = Thread(target=new_module_thread, args=parameters) - x.start() if __name__ == "__main__": main() diff --git a/easyconf-lemonbar/config_parsing.py b/easyconf-lemonbar/parse_config_file.py similarity index 92% rename from easyconf-lemonbar/config_parsing.py rename to easyconf-lemonbar/parse_config_file.py index f4afc90..a223f0e 100644 --- a/easyconf-lemonbar/config_parsing.py +++ b/easyconf-lemonbar/parse_config_file.py @@ -1,7 +1,7 @@ from yaml import safe_load from schema import And, Optional, Regex, Schema, SchemaError, Or -def get_validated_config(filename): +def get_bar_config_and_module_config_list(filename): config_schema = Schema({ "bar": { Optional("config"): { @@ -34,11 +34,12 @@ def get_validated_config(filename): 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}$') - }, - 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 + #} } } ] @@ -50,7 +51,8 @@ def get_validated_config(filename): config_file = safe_load(file) try: - return config_schema.validate(config_file) + validated_config = config_schema.validate(config_file) + return validated_config["bar"]["config"], validated_config["bar"]["modules"] except SchemaError as se: raise se diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..d334738 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,83 @@ +# This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand. + +[[package]] +name = "contextlib2" +version = "21.6.0" +description = "Backports and enhancements for the contextlib module" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "contextlib2-21.6.0-py2.py3-none-any.whl", hash = "sha256:3fbdb64466afd23abaf6c977627b75b6139a5a3e8ce38405c5b413aed7a0471f"}, + {file = "contextlib2-21.6.0.tar.gz", hash = "sha256:ab1e2bfe1d01d968e1b7e8d9023bc51ef3509bba217bb730cee3827e1ee82869"}, +] + +[[package]] +name = "pyyaml" +version = "6.0" +description = "YAML parser and emitter for Python" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, + {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, + {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +] + +[[package]] +name = "schema" +version = "0.7.5" +description = "Simple data validation library" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "schema-0.7.5-py2.py3-none-any.whl", hash = "sha256:f3ffdeeada09ec34bf40d7d79996d9f7175db93b7a5065de0faa7f41083c1e6c"}, + {file = "schema-0.7.5.tar.gz", hash = "sha256:f06717112c61895cabc4707752b88716e8420a8819d71404501e114f91043197"}, +] + +[package.dependencies] +contextlib2 = ">=0.5.5" + +[metadata] +lock-version = "2.0" +python-versions = "^3.10" +content-hash = "1d5f331a8e059d3c178cae193c847ca08eb8682aa32651ab7829863453ec08da" diff --git a/poetry.toml b/poetry.toml new file mode 100644 index 0000000..ab1033b --- /dev/null +++ b/poetry.toml @@ -0,0 +1,2 @@ +[virtualenvs] +in-project = true diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..fe9cf1f --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,18 @@ +[tool.poetry] +name = "easyconf-lemonbar" +version = "0.1.0" +description = "A python script to easily configure lemonbar." +authors = ["Noah Swerhun "] +license = "GPL-3.0-or-later" +readme = "README.md" +packages = [{include = "easyconf_lemonbar"}] + +[tool.poetry.dependencies] +python = "^3.10" +PyYAML = "^6.0" +schema = "^0.7.5" + + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..99451b8 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +pyyaml==6.0 +schema==0.7.5