Skip to content

Commit

Permalink
implemented all output_format settings supported by i3status
Browse files Browse the repository at this point in the history
  • Loading branch information
oaken-source committed Mar 6, 2022
1 parent 1ac4141 commit af97140
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 31 deletions.
14 changes: 12 additions & 2 deletions py3status/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,18 @@
"output_format": "i3bar",
}

DEFAULT_SEPARATORS = {
"tmux": "#[fg={color_separator}]|#[default]",
OUTPUT_FORMAT_NEEDS_SEPARATOR = [
"dzen2",
"xmobar",
"lemonbar",
"tmux",
"term",
"none",
]

DEFAULT_SEPARATOR = {
"dzen2": "^p(5;-2)^ro(2)^p()^p(5)",
# if it's not listed here, it defaults to " | "
}

MAX_NESTING_LEVELS = 4
Expand Down
93 changes: 69 additions & 24 deletions py3status/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from traceback import extract_tb, format_tb, format_stack

from py3status.command import CommandServer
from py3status.constants import DEFAULT_SEPARATORS
from py3status.constants import OUTPUT_FORMAT_NEEDS_SEPARATOR, DEFAULT_SEPARATOR
from py3status.events import Events
from py3status.formatter import expand_color
from py3status.helpers import print_stderr
Expand Down Expand Up @@ -681,17 +681,18 @@ def setup(self):
# determine the target output format
self.output_format = self.config["py3_config"]["general"]["output_format"]

# determine the separator between status entries, if needed
default_separator = DEFAULT_SEPARATORS.get(self.output_format, None)
self.output_format_separator = self.config["py3_config"]["py3status"].get(
"output_format_separator", default_separator
)

# inject the value of color_separator into the separator string
if self.output_format_separator is not None:
self.output_format_separator = self.output_format_separator.format(
color_separator=self.config["py3_config"]["general"]["color_separator"]
# determine the output separator, if needed
self.separator = None
if self.output_format in OUTPUT_FORMAT_NEEDS_SEPARATOR:
default_separator = DEFAULT_SEPARATOR.get(self.output_format, " | ")
self.separator = self.config["py3_config"]["general"].get(
"separator", default_separator
)
if self.config["py3_config"]["general"]["colors"]:
self.separator = self.format_separator(
self.separator,
self.config["py3_config"]["general"]["color_separator"],
)

def notify_user(
self,
Expand Down Expand Up @@ -970,6 +971,53 @@ def create_mappings(self, config):
# Store mappings for later use.
self.mappings_color = mappings

def format_color(self, output):
"""
Format the output of a module according to the value of output_format.
"""
full_text = output["full_text"]
if "color" in output:
if self.output_format == "dzen2":
full_text = f"^fg({output['color']})" + output["full_text"]
if self.output_format == "xmobar":
full_text = f"<fc={output['color']}>{output['full_text']}</fc>"
if self.output_format == "lemonbar":
full_text = f"%{{F{output['color']}}}" + output["full_text"]
if self.output_format == "tmux":
full_text = f"#[fg={output['color'].lower()}]" + output["full_text"]
if self.output_format == "term":
col = int(output["color"][1:], 16)
r = (col & (0xFF << 0)) // 0x80
g = (col & (0xFF << 8)) // 0x8000
b = (col & (0xFF << 16)) // 0x800000
col = (r << 2) | (g << 1) | b
full_text = f"\033[3{col};1m" + output["full_text"]
if self.output_format == "none":
pass # colors are ignored
return full_text

def format_separator(self, separator, color_separator):
"""
Format the output separator according to the value of output_format.
"""
if self.output_format == "dzen2":
return f"^fg({color_separator}){separator}^fg()"
if self.output_format == "xmobar":
return f"<fc={color_separator}>{separator}</fc>"
if self.output_format == "lemonbar":
return f"%{{F{color_separator}}}{separator}%{{F-}}"
if self.output_format == "tmux":
return f"#[fg={color_separator}]{separator}#[default]"
if self.output_format == "term":
col = int(color_separator[1:], 16)
r = (col & (0xFF << 0)) // 0x80
g = (col & (0xFF << 8)) // 0x8000
b = (col & (0xFF << 16)) // 0x800000
col = (r << 2) | (g << 1) | b
return f"\033[3{col};1m{separator}\033[0m"
else: # output_format == "none"
return separator # color_separator is ignored

def process_module_output(self, module):
"""
Process the output for a module and return a json string representing it.
Expand All @@ -986,15 +1034,13 @@ def process_module_output(self, module):
# Color: substitute the config defined color
if "color" not in output:
output["color"] = color
# Create the tmux string output.
if self.output_format == "tmux":
for output in outputs:
if "color" in output:
output[
"full_text"
] = f"#[fg={output['color'].lower()}]{output['full_text']}#[default]"
return "".join(x["full_text"] for x in outputs)
# Create the json string output.
# concatenate string output, if needed.
if self.output_format in OUTPUT_FORMAT_NEEDS_SEPARATOR:
# FIXME: `output_format = none` in config will default to i3bar.
# `output_format = "none"` is required instead. this is different
# in i3status, which behaves correctly for `output_status = none`
return "".join(self.format_color(x) for x in outputs)
# otherwise create the json string output.
else:
return ",".join(dumps(x) for x in outputs)

Expand Down Expand Up @@ -1066,7 +1112,7 @@ def run(self):
"click_events": self.config["click_events"],
"stop_signal": self.stop_signal or 0,
}
if self.output_format != "tmux":
if self.output_format not in OUTPUT_FORMAT_NEEDS_SEPARATOR:
write(dumps(header))
write("\n[[]\n")

Expand Down Expand Up @@ -1096,9 +1142,8 @@ def run(self):
output[index] = out

# build output string and dump to stdout
out = ""
if self.output_format == "tmux":
out = self.output_format_separator.join(x for x in output if x)
if self.output_format in OUTPUT_FORMAT_NEEDS_SEPARATOR:
out = self.separator.join(x for x in output if x)
write(f"{out}\n")
else:
out = ",".join(x for x in output if x)
Expand Down
16 changes: 11 additions & 5 deletions py3status/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,11 +337,17 @@ def set_module_options(self, module):

separator = fn(self.module_full_name, "separator")
if not hasattr(separator, "none_setting"):
if not isinstance(separator, bool):
err = "Invalid `separator` attribute, should be a boolean. "
err += f"Got `{separator}`."
raise TypeError(err)
self.i3bar_module_options["separator"] = separator
# HACK: separator is a valid setting in the general section
# of the configuration. but it's a string, not a boolean.
# revisit how i3status and py3status differ in this regard.
# if not isinstance(separator, bool):

# err = "Invalid `separator` attribute, should be a boolean. "
# err += f"Got `{separator}`."
# raise TypeError(err)
# self.i3bar_module_options["separator"] = separator
if isinstance(separator, bool):
self.i3bar_module_options["separator"] = separator

separator_block_width = fn(self.module_full_name, "separator_block_width")
if not hasattr(separator_block_width, "none_setting"):
Expand Down

0 comments on commit af97140

Please sign in to comment.