205 lines
7.2 KiB
Python
Executable File
205 lines
7.2 KiB
Python
Executable File
import sys
|
|
import bisect # Sorting of list
|
|
from enum import Enum
|
|
import i3_lemonbar_config as config
|
|
import i3_lemonbar_common as common
|
|
|
|
sr = config.sep_right
|
|
slr = config.sep_l_right
|
|
sl = config.sep_left
|
|
sll = config.sep_l_left
|
|
|
|
class IconTextUnit:
|
|
def __init__(self, name, order, action = None, alt_scheme=None, external=None):
|
|
self.name = name
|
|
self.action = action
|
|
self.order = order
|
|
self.alt_scheme = alt_scheme # None means default
|
|
self.external = external
|
|
self.items = [] # List of tuples (icon, text)
|
|
self.modes = [common.bar_mode.normal]
|
|
|
|
def format(self):
|
|
close = block(click='') if self.action is not None else ''
|
|
|
|
b_color = self.alt_scheme.back_color
|
|
i_color = self.alt_scheme.icon_color
|
|
t_color = self.alt_scheme.text_color
|
|
|
|
# Start with a major separator. Keep previous background color, set foreground color
|
|
# of separator to background color of this unit
|
|
blocks = []
|
|
blocks.append(block(fg=b_color, append=sl))
|
|
blocks.append(' ') # TODO perhaps more nice solution than manual spacing
|
|
if len(self.items) >= 1:
|
|
(icon, text) = self.items[0]
|
|
blocks.append(block(click=self.action, fg=i_color, bg=b_color, font='2'
|
|
, append=' ' + icon))
|
|
blocks.append(' ')
|
|
blocks.append(block(fg=t_color, font='1', append=text))
|
|
if len(self.items) >= 2:
|
|
for item in self.items[1:]:
|
|
(icon, text) = item
|
|
# Append minor separator
|
|
blocks.append(' ')
|
|
blocks.append(sll)
|
|
|
|
blocks.append(block(fg=i_color, bg=b_color, font='2', append=' ' + icon))
|
|
blocks.append(' ')
|
|
blocks.append(block(fg=t_color, font='1', append=text))
|
|
|
|
if len(self.items) >= 1:
|
|
blocks.append(close)
|
|
return ''.join(blocks)
|
|
|
|
def __lt__(self, other):
|
|
return self.order < other.order
|
|
|
|
class ButtonsUnit:
|
|
def __init__(self, name, order, alt_scheme=None, external=None):
|
|
self.name = name
|
|
self.order = order
|
|
self.alt_scheme = alt_scheme # None means default
|
|
self.external = external
|
|
self.items = [] # List of tuples (icon, text, action)
|
|
self.modes = [common.bar_mode.normal]
|
|
|
|
def format(self):
|
|
b_color = self.alt_scheme.back_color
|
|
i_color = self.alt_scheme.icon_color
|
|
t_color = self.alt_scheme.text_color
|
|
|
|
# Start with a major separator. Keep previous background color, set foreground color
|
|
# of separator to background color of this unit
|
|
blocks = []
|
|
blocks.append(block(fg=b_color, append=sl))
|
|
blocks.append(' ')
|
|
for item in self.items:
|
|
(icon, text, action) = item
|
|
close = block(click='') if action is not None else ''
|
|
|
|
blocks.append(block(click=action, fg=i_color, bg=b_color, font='2'
|
|
, append=' ' + icon))
|
|
blocks.append(' ')
|
|
blocks.append(block(fg=t_color, font='1', append=text))
|
|
blocks.append(close)
|
|
|
|
return ''.join(blocks)
|
|
|
|
def __lt__(self, other):
|
|
return self.order < other.order
|
|
|
|
class CustomUnit:
|
|
def __init__(self, name, format_function, order, action = None, alt_scheme=None, external=None):
|
|
self.name = name
|
|
self.action = action
|
|
self.order = order
|
|
self.alt_scheme = alt_scheme # None means default
|
|
self.external = external
|
|
self.format = format_function
|
|
self.items = [] # List of tuples (icon, text)
|
|
self.modes = [common.bar_mode.normal]
|
|
|
|
def __lt__(self, other):
|
|
return self.order < other.order
|
|
|
|
class LemonParser:
|
|
# Handle parsing of units
|
|
# Apply alternating colors
|
|
# Contains list of units
|
|
|
|
def __init__(self):
|
|
self.units = []
|
|
|
|
def register_unit(self, unit):
|
|
# Keep the list sorted
|
|
bisect.insort_left(self.units, unit)
|
|
|
|
def remove_unit(self, unit):
|
|
self.units.remove(unit)
|
|
|
|
def format(self):
|
|
formatted = ['%{l}'] # Start left-justified
|
|
previously_left_justified = True
|
|
# Iterate over all units. Apply alternating color schemes
|
|
alt = 1
|
|
for unit in self.units:
|
|
# Show only units appropriate for the current mode
|
|
if common.mode not in unit.modes:
|
|
continue
|
|
|
|
# Negative order means left justified, positive means right justified
|
|
if previously_left_justified and unit.order > 0:
|
|
# Switch to right justified
|
|
formatted.append(block(fg='-', bg='-')) # Reset so the color doesn't fill
|
|
formatted.append('%{r}')
|
|
previously_left_justified = False
|
|
|
|
if unit.alt_scheme is None:
|
|
# Apply default color scheme, which is alternating
|
|
unit.alt_scheme = COLOR_SCHEME.A1 if alt == 1 else COLOR_SCHEME.A2
|
|
else:
|
|
# Keep alternate color scheme
|
|
# INA is a special case
|
|
if unit.alt_scheme == COLOR_SCHEME.INA:
|
|
unit.alt_scheme = COLOR_SCHEME.A1_INA if alt == 1 else COLOR_SCHEME.A2_INA
|
|
|
|
formatted.append(unit.format())
|
|
alt = alt + 1 if alt + 1 <= 2 else 1
|
|
|
|
formatted.append(block(fg='-', bg='-')) # Not sure if needed
|
|
return ' '.join(formatted)
|
|
|
|
g_parser = LemonParser()
|
|
|
|
def block(fg = None, bg = None, font = None, click = None, append=''):
|
|
# Remeber that clickable blocks need to be closed
|
|
rtn = []
|
|
if click is not None:
|
|
if click == '':
|
|
rtn.append('A')
|
|
else:
|
|
rtn.append('A:'+click+':')
|
|
if fg is not None:
|
|
rtn.append('F'+fg)
|
|
if bg is not None:
|
|
rtn.append('B'+bg)
|
|
if font is not None:
|
|
rtn.append('T'+font)
|
|
return ''.join(['%{', ' '.join(rtn), '}', append])
|
|
|
|
class COLOR_SCHEME(Enum):
|
|
A1 = (config.color_sec_b1, config.color_fore, config.color_icon)
|
|
A2 = (config.color_sec_b2, config.color_fore, config.color_icon)
|
|
INA = (None, None, None) # This one is special, dynamically changed to A1_INA or A2_INA
|
|
A1_INA = (config.color_sec_b1, config.color_disable, config.color_disable)
|
|
A2_INA = (config.color_sec_b2, config.color_disable, config.color_disable)
|
|
CPU_ALERT= (config.color_cpu, config.color_back, config.color_back)
|
|
NET_ALERT= (config.color_net, config.color_back, config.color_back)
|
|
SPECIAL = (config.color_head, config.color_back, config.color_back)
|
|
def __init__(self, back_color, text_color, icon_color):
|
|
self.back_color = back_color
|
|
self.text_color = text_color
|
|
self.icon_color = icon_color
|
|
|
|
def format_line():
|
|
return g_parser.format()
|
|
|
|
def parse_line(line_in):
|
|
# Parse lines that external programs have written to fifo
|
|
|
|
for unit in g_parser.units:
|
|
if unit.external is not None:
|
|
for key,func in unit.external.items():
|
|
l = len(key)
|
|
if line_in[:l] == key:
|
|
func(line_in[l:].split())
|
|
break
|
|
|
|
formatted_line = format_line()
|
|
return formatted_line
|
|
|
|
if __name__ == "__main__":
|
|
for line in sys.stdin:
|
|
print(parse_line(line))
|