Files
dotfiles/.i3/lemonbar/i3_lemonbar_parser.py

293 lines
11 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import sys
from enum import Enum
import i3_lemonbar_config as conf
import i3_lemonbar_common as common
displays = ''
workspaces = ''
win_title = ''
sys_load = ''
net_load = ''
volume = ''
brightness = ''
battery = ''
date = ''
language = ''
time = ''
response = '%{r}'
blank = ' '
sr = conf.sep_right
slr = conf.sep_l_right
sl = conf.sep_left
sll = conf.sep_l_left
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])
reset = block(fg='-', bg='-')
reset_power = block(fg='-', bg=conf.color_poweropts)
class COLOR_SCHEME(Enum):
A1 = (conf.color_sec_b1, conf.color_fore, conf.color_icon)
A2 = (conf.color_sec_b2, conf.color_fore, conf.color_icon)
A1_INA = (conf.color_sec_b1, conf.color_disable, conf.color_disable)
A2_INA = (conf.color_sec_b2, conf.color_disable, conf.color_disable)
CPU_ALERT= (conf.color_cpu, conf.color_back, conf.color_back)
NET_ALERT= (conf.color_net, conf.color_back, conf.color_back)
SPECIAL = (conf.color_head, conf.color_back, conf.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 single_sect(icon='', text='', click=None, alt=COLOR_SCHEME.A1):
# If there is an action we need to close the block
close = block(click='') if click is not None else ''
if icon != '':
icon = ' ' + icon
return ' '.join([block(fg=alt.back_color, append=sl)
, block(click=click, fg=alt.icon_color, bg=alt.back_color
, font='2', append=icon)
, block(fg=alt.text_color, font='1', append=text)
, close])
def double_sect(text1 = '', text2 = '', icon1 = '', icon2 = '', click = None
, alt=COLOR_SCHEME.A1):
# If text_color None then icon_color will apply
close = block(click='') if click is not None else ''
return ''.join([block(fg=alt.back_color, append=sl), ' '
, block(click=click, fg=alt.icon_color, bg=alt.back_color, font='2')
, ' ', icon1, block(fg=alt.text_color, font='1'), ' ', text1
, block(fg=alt.icon_color), sll, block(font='2')
, icon2, block(fg=alt.text_color, font='1'), ' ', text2, ' ', close])
def control_sect(sec_color=None, head='', buttons=[], actions=[]):
rtn = head
for button, action in zip(buttons, actions):
# If there is an action we need to close the block
close = block(click='') if action is not None else ''
rtn += ' '.join([block(click=action), button, close])
return rtn
# Constants
power_opts = ''.join([block(fg=conf.color_fore, bg=conf.color_poweropts)
, ' Abort (Esc) | System (l) lock, (e) logout, (s) suspend, (h) hibernate'
, ', (r) reboot, (Shift+s) shutdown %{r}'])
controls = ' '.join([block(fg=conf.color_head, bg=conf.color_sec_b2)
, conf.sep_right, block(fg=conf.color_head, bg=conf.color_sec_b2, click='mode cycle')
, conf.icon_prog
, block(fg=conf.color_sec_b2, bg='-', click='')
, control_sect(head='', buttons=['on', 'off']
, actions=['bluetooth power on', 'bluetooth power off'])
, control_sect(head='PXC 550', buttons=['conn.', 'disc.']
, actions=['bluetooth connect pxc550', 'bluetooth disconnect pxc550'])
])
def update_response(data):
global response
resp = ' '.join(data)
#common.logger.debug('Got response {}'.format(resp))
response= ''.join(['%{r}', single_sect(text=resp)])
def update_displays(data):
global displays
dsp_array = data[0].split(':')
parsed_list = [block(click='displays', font='2')]
for dsp in dsp_array[1:]:
if dsp == 'eDP1':
col_head = conf.color_head
elif dsp == 'DP1':
col_head = conf.color_vga
elif dsp == 'HDMI2':
col_head = conf.color_hdmi
else:
col_head = '#00000000' # Undefined
parsed_list.append(block(fg=conf.color_back, bg=col_head))
parsed_list.append(conf.icon_wsp)
parsed_list.append(block(click=''))
displays = ' '.join(parsed_list)
def update_workspaces(data):
global workspaces
prefix = block(font='1', fg=conf.color_back, bg=conf.color_head)
prefix_foc = ''.join([block(fg = conf.color_head, bg=conf.color_wsp)
, conf.sep_right
, block(fg=conf.color_back, bg=conf.color_wsp, font='1')])
prefix_ina = block(fg=conf.color_back, bg=conf.color_head, font='1')
wspces = []
for entry in data: # entry for example FOC5___terms
status = entry[0:3] # FOC or INA
num = entry[3]
name = entry[7:]
full_name = ' '.join(['', num, name])
current = ''.join([block(click=('i3-msg workspace' + full_name))
, full_name, block(click='')])
if status == "FOC":
wspces.append(''.join([prefix_foc, current]))
else:
wspces.append(''.join([prefix_ina, current]))
workspaces = ''.join([prefix, ' '.join(wspces)])
def update_conky_slow(data):
global sys_load, battery
# System load
if int(data[0]) > int(conf.cpu_alert):
cpu_alt = COLOR_SCHEME.CPU_ALERT
else:
cpu_alt = COLOR_SCHEME.A2
sys_load = ''.join(['%{r}'
, double_sect(text1 = (data[0] + '%'), text2 = data[1], icon1 = conf.icon_cpu
, icon2 = conf.icon_mem, alt=cpu_alt , click = 'load')
, double_sect(text1 = (data[2] + '%'), text2 = (data[3] + '%')
, icon1 = conf.icon_hd, icon2 = conf.icon_home, alt=COLOR_SCHEME.A1)
]) # cpu mem disk_r disk_home
#sec_color = conf.color_sec_b1 if (b == 1) else conf.color_sec_b2
(batt_stat, batt) = (data[4][0], int(data[4][1:]))
icon_batt = conf.icon_charging if batt_stat == 'C' else \
conf.icon_charged if batt_stat == 'F' else \
conf.icon_batt_0 if batt < 20 else \
conf.icon_batt_1 if batt < 40 else \
conf.icon_batt_2 if batt < 60 else \
conf.icon_batt_3 if batt < 80 else \
conf.icon_batt_4
battery = single_sect(icon=icon_batt, click='dpms', text=(str(batt)+'%')
, alt=COLOR_SCHEME.A2)
update_bright([data[5]])
update_lang([data[6]])
def update_lang(data):
global language
language = single_sect(icon=conf.icon_lang, click='lang', text=data[0]
, alt=COLOR_SCHEME.A2)
def update_bright(data):
global brightness
brtxt = str(int(float(data[0])))
brightness = single_sect(icon=conf.icon_bright, click='adj_br'
, text=(brtxt+'%'), alt=COLOR_SCHEME.A1)
def update_conky_fast(data):
global date, time, volume
mute = data[4] == 'MUTE' or data[4] == 'NONE'
(vol,vols) = (-1,'×') if mute else (int(data[4]), data[4]+'%')
icon_v = conf.icon_vol_mute if vol == 0 else \
conf.icon_vol_low if vol < 50 else conf.icon_vol
volume = single_sect(icon=icon_v, click='pavu', text=vols
, alt=COLOR_SCHEME.A2)
tme = data[3] if common.show_secs else data[3][:-3]
date = single_sect(icon=conf.icon_clock, click='date'
, text=' '.join(data[0:3]), alt=COLOR_SCHEME.A1)
time = single_sect(click='toggle_secs', text=tme, alt=COLOR_SCHEME.SPECIAL)
update_net(data[5:9])
def update_net(data):
global net_load
if data[0] == 'down': # wlan
(wland_v, wlanu_v) = ('x', 'x')
wlan_alt = COLOR_SCHEME.A2_INA
else:
(wland_v, wlanu_v) = (data[0],data[1])
if max(float(wland_v), float(wlanu_v)) > float(conf.net_alert):
wlan_alt = COLOR_SCHEME.NET_ALERT
else:
wlan_alt = COLOR_SCHEME.A2
if data[2] == 'down': # eth
(ethd_v, ethu_v) = ('x', 'x')
eth_alt = COLOR_SCHEME.A1_INA
else:
(ethd_v, ethu_v) = (data[2],data[3])
if max(float(ethd_v), float(ethu_v)) > float(conf.net_alert):
eth_alt = COLOR_SCHEME.NET_ALERT
else:
eth_alt = COLOR_SCHEME.A1
net_load = ''.join([
double_sect(click = 'wlan', alt=wlan_alt, text1 = wland_v, text2 = wlanu_v,
icon1 = (conf.icon_wlan + conf.icon_dl), icon2 = conf.icon_ul)
, double_sect(click = 'eth', alt=eth_alt, text1 = ethd_v, text2 = ethu_v,
icon1 = (conf.icon_eth + conf.icon_dl), icon2 = conf.icon_ul)
]) # wlan_d wlan_u eth_d eth_u
def update_title(data):
global win_title
win_title = ' '.join([block(fg=conf.color_head, bg=conf.color_sec_b2)
, conf.sep_right, block(fg=conf.color_head, bg=conf.color_sec_b2, click='mode cycle')
, conf.icon_prog
, block(fg=conf.color_sec_b2, bg='-')
, ' '.join(data)])
def format_line():
# Need to end with a reset block, otherwise the color fills the %{r} spacer
if common.mode == common.bar_mode.normal:
return ''.join(['%{l}', reset, displays, workspaces, win_title, sys_load, net_load
, volume, brightness, battery, date, language, time, reset])
elif common.mode == common.bar_mode.power:
return ''.join(['%{l}', reset, power_opts, sys_load, net_load
, volume, brightness, battery, date, language, time, reset_power])
elif common.mode == common.bar_mode.control:
return ''.join(['%{l}', reset, displays, workspaces, controls, response, time, reset])
else:
return ''.join(['%{l}', reset, displays, workspaces, 'Not normal' , time, reset])
parsers_dict = { 'CNK_FAST':update_conky_fast
,'CNK_SLOW':update_conky_slow
,'WSP':update_workspaces
,'LANG':update_lang
,'BRIGHT':update_bright
,'WIN':update_title
,'DISP':update_displays
,'RESP':update_response
}
def parse_line(line_in):
''' Lines are
CNK_FAST Fri 21 Sep 19:45:18 VolXXX wlan_d wlan_u eth_d eth_u
CNK_SLOW cpu mem disk_root disk_home batt bri lang disp
WSPINA1___main INA2___web FOC5___terms INA6___stats
'''
try:
for key,func in parsers_dict.items():
l = len(key)
if line_in[:l] == key:
func(line_in[l:].split())
break
except:
print('Exception occured\n Line in: {}\n Data: {}'.format(line_in, line_in[l:].split()))
raise
formatted_line = format_line()
return formatted_line
if __name__ == "__main__":
for line in sys.stdin:
print(parse_line(line))