From bd0719e4f9137d34e1bc9b2c82582079d0c9d1ed Mon Sep 17 00:00:00 2001 From: Sheppy Date: Wed, 25 Oct 2017 16:55:34 +0200 Subject: [PATCH] panel improvements --- herbstluftwm/hl_panel_content.py | 79 +++------------------- herbstluftwm/hl_status_deamon.py | 80 ++++++++++++++++------ herbstluftwm/panel.sh | 110 +++++++++++++------------------ 3 files changed, 113 insertions(+), 156 deletions(-) diff --git a/herbstluftwm/hl_panel_content.py b/herbstluftwm/hl_panel_content.py index a724f48..517a991 100755 --- a/herbstluftwm/hl_panel_content.py +++ b/herbstluftwm/hl_panel_content.py @@ -1,74 +1,14 @@ #!/usr/bin/python3 - import hl_utils +from hl_constants import * import string import re -sep = " | " - -RED = 0xff0000 -GREEN = 0x32CD32 -GREY = 0x909090 -WHITE = 0xefefef -DEFAULT_FG = 0x476243 -COLOR_BORDER = 5.0 -BAT_COLOR_OFFSET = 10 - -def color_panel(s,hex_code,seper=True): - if type(hex_code)==int: - hex_code = hex(hex_code) - hex_code = hex_code.lstrip('0x') - if seper: - sep=color_panel('|',DEFAULT_FG,False) - else: - sep = "" - return "^fg(#" + hex_code + ") " + s + "^bg()"+sep - -def get_color(nr,start,end): - if nr == 88: - return hex(GREEN) - elif end == start or nr >= end: - return hex(GREEN) - elif nr <= 0: - return hex(RED) - else: - r,g,b = 0,0,0 - interval = 256 + 256 - custom_interval = abs(start-end) - div = float(interval)/float(custom_interval) - if div >= interval: - hl_utils.error("Interval for coloring too small, using default") - return WHITE - nr = nr*div - if custom_interval > interval: - custom_interval = interval - if nr >= 256: - g = 0xFF - r = int(abs(nr - (256+256))) #counts down reverse to nr - #aaah fuck my life - if r == 0x100: - r = 0xFF - b = 0 - elif nr >= 0: - g = int(nr) - r = 0xFF - b = 0 - else: - hl_utils.error("Negative interval value???") - return(WHITE) - r = r << 16 - g = g << 8 - tmp_col = r + g + b - if tmp_col > 0xFFFF00: - hl_utils.error("color value too high") - return hex(tmp_col) - - def guthaben(): guthaben = '' if hl_utils.is_cip(): raw = "" - with open(hl_utils.hlpath("pracct.log")) as f: + with open(hl_utils.hlpath(PRINT_LOG)) as f: raw = f.read(); guthaben = "Druckerguthaben: " + raw + " Euro" col = get_color(float(raw),0,COLOR_BORDER) @@ -80,14 +20,13 @@ def vpn(): if hl_utils.is_cip(): return '' else: - tmp = -1 - with open(hl_utils.hlpath("vpn_status.log")) as f: + with open(hl_utils.hlpath(VPN_LOG)) as f: tmp = f.read() tmp = ' '+tmp - return tmp; + return tmp; def ip(): - with open(hl_utils.hlpath("ip.log")) as f: + with open(hl_utils.hlpath(IP_LOG)) as f: tmp = f.read() tmp = ' '+tmp return tmp; @@ -95,15 +34,17 @@ def ip(): def battery(): if hl_utils.is_laptop(): try: - with open(hl_utils.hlpath("battery.log")) as f: + with open(hl_utils.hlpath(BATTERY_LOG)) as f: tmp = f.read() - tmp = ' '+tmp+' | ' + tmp = ' '+tmp return tmp; except Exception as e: return color_panel(str(e),RED) else: return "" +def date(): + return hl_utils.shexec("date +' ^fg(#efefef)%H:%M^fg(#909090), %Y-%m-^fg(#efefef)%d'") if __name__ == "__main__": - print(ip(),vpn(),guthaben(),battery(),sep='',end='') + print(ip(),vpn(),guthaben(),battery(),date(),sep='',end='') diff --git a/herbstluftwm/hl_status_deamon.py b/herbstluftwm/hl_status_deamon.py index db23e54..876d4fe 100755 --- a/herbstluftwm/hl_status_deamon.py +++ b/herbstluftwm/hl_status_deamon.py @@ -6,9 +6,15 @@ import sys import subprocess import re import hl_utils +import signal from hl_constants import * battery_average=[] +bat_prev = -1 + +def sigusr1_handler(signum, frame): + save() + def battery(): try: @@ -24,36 +30,66 @@ def battery(): return hl_utils.color_panel("On Supply and fully charged",GREEN) ## calculate average time remaining ## + sph = 60*60 + spm = 60 + cur_time = bat.split('%, ')[1].split(' ')[0].split(':') - cur = int(cur_time[0]) + int(cur_time[1]) * 60 + int(cur_time[2]) * 60 * 60 + cur = int(cur_time[0]) * sph + int(cur_time[1]) * spm + int(cur_time[2]) + global battery_average - battery_average+=[int(cur)] + global bat_prev + battery_average += [int(cur)] if len(battery_average) == 0: bat_avg = "unkown" else: bat_avg=int(sum(battery_average) / float(len(battery_average))) + ## keep max 10 items in queue ## + if len(battery_average) > VALUES_KEPT: + battery_average = battery_average[1:] + ## color fine tuning ## if plain > 10: plain += BAT_COLOR_OFFSET ## build string ## - tmp=hl_utils.color_panel(bat.lstrip("Charging ,").lstrip("Discharging ,").split(",")[0],hl_utils.get_color(plain,0,100),False) - bat_avg=hl_utils.color_panel(str(bat_avg),RED,False) + color=hl_utils.get_color(plain,0,100) + tmp=hl_utils.color_panel(bat.lstrip("Charging ,").lstrip("Discharging ,").split(",")[0],color,False) + + dez_count = 2 + avg_h = str(int(bat_avg/sph)).zfill(dez_count) + avg_m = str(int((bat_avg%sph)/spm)).zfill(dez_count) + avg_s = str(int(bat_avg%spm)).zfill(dez_count) + + #print(cur_time) + #print(bat_avg,avg_h,avg_m,avg_s) + #print(battery_average) + + ## prevent "flickering" + if(abs(int(avg_m))-abs(int(bat_prev))<5 and int(avg_h) >= 1): + avg_m = bat_prev + else: + bat_prev = avg_m + + bat_str = "{}:{}:{}".format(avg_h,avg_m,"00") + bat_avg=hl_utils.color_panel(bat_str,color,False) + ## conditional coloring ## if bat.startswith("Charging"): - return hl_utils.color_panel("Charging, ",GREEN,False) + str(tmp) + str(bat_avg) + stat = hl_utils.color_panel("Charging, ",GREEN,False) + str(tmp) + str(bat_avg) + stat += hl_utils.color_panel("until charged",color,True) elif plain <= BATTERY_CRITICAL: - return hl_utils.color_panel(">>>>>>>>>>>>>>>> ------------ WARNING BATTER FAILURE IMMINENT ------------ <<<<<<<<<<<<<",RED) + stat = hl_utils.color_panel(BAT_WARNING_STR,RED) elif bat.startswith("Discharging"): - return hl_utils.color_panel("Discharging, ",RED,False) + str(tmp) + str(bat_avg) + stat = hl_utils.color_panel("Discharging, ",RED,False) + str(tmp) + str(bat_avg) + stat += hl_utils.color_panel("remaining",color,True) else: - return hl_utils.color_panel(bat.strip('\n'),hl_utils.get_color(plain,0,100)) + stat = hl_utils.color_panel(bat.strip('\n'),hl_utils.get_color(plain,0,100)) + return stat except ValueError as e: return hl_utils.color_panel(str(e),RED) - def pr_acct_status(): if hl_utils.is_cip(): out = hl_utils.color_remove(hl_utils.shexec(PRINT_LOG).split("\n")[0]).split(' ')[-1] @@ -62,14 +98,12 @@ def pr_acct_status(): def vpn_status(): if not hl_utils.is_cip(): - out_vpn = hl_utils.shexec("ps -ef") - #out_vpn = subprocess.check_output(["ps","-ef"]).decode().split('\n') + out_vpn = hl_utils.shexec("ps -ef").split("\n") ret = 0 for l in out_vpn: if 'openvpn' in l and not 'sudo' in l and not 'grep' in l and not 'cip.sh' in l: ret += 1; - if ret == 0: out_vpn = hl_utils.color_panel("VPN: Link Down",RED) elif ret == 1: @@ -77,7 +111,7 @@ def vpn_status(): elif ret > 1: out_vpn = hl_utils.color_panel("multiple VPNs connected",YELLOW) else: - out_vpn = hl_utils.color_panel("VPN: ret was "+str(ret)+" ??",RED) + out_vpn = hl_utils.color_panel("VPN: STATUS UNKOWN ??",RED) with open(hl_utils.hlpath(VPN_LOG),'w+') as g: g.write(out_vpn) @@ -91,18 +125,22 @@ def ip_status(): with open(hl_utils.hlpath(IP_LOG),'w') as g: p="Public IP: " try: - tmp=hl_utils.color_panel(p+hl_utils.shexec("wget --timeout=3 -O- --quiet https://atlantishq.de/ipcheck"),GREEN) + tmp = hl_utils.color_panel(p+hl_utils.shexec("wget --timeout=3 -O- --quiet https://atlantishq.de/ipcheck"),GREEN) except: - tmp=hl_utils.color_panel("Offline",RED) + tmp = hl_utils.color_panel("Offline",RED) g.write(tmp) +def save(): + vpn_status() + pr_acct_status() + battery_status() + ip_status() if __name__ == '__main__': + signal.signal(signal.SIGUSR1,sigusr1_handler) + signal.siginterrupt(signal.SIGUSR1, True) while(True): - vpn_status() - pr_acct_status() - battery_status() - ip_status() - if sys.argv[-1]=='--refresh': + if sys.argv[-1] in ['--refresh','-r']: break - time.sleep(5) + save() + time.sleep(10) diff --git a/herbstluftwm/panel.sh b/herbstluftwm/panel.sh index 9bc95d1..39c73f3 100755 --- a/herbstluftwm/panel.sh +++ b/herbstluftwm/panel.sh @@ -1,13 +1,12 @@ #!/usr/bin/env bash +####################################################################################### +########################### CONSTANTS AND SHORTCUTS ################################### +####################################################################################### + hc() { "${herbstclient_command[@]:-herbstclient}" "$@" ;} monitor=${1:-0} geometry=( $(herbstclient monitor_rect "$monitor") ) -if [ -z "$geometry" ] ;then - echo "Invalid monitor $monitor" - exit 1 -fi -# geometry has the format W H X Y x=${geometry[0]} y=${geometry[1]} panel_width=${geometry[2]} @@ -16,10 +15,22 @@ font="-*-fixed-medium-*-*-*-12-*-*-*-*-*-*-*" bgcolor=$(hc get frame_border_normal_color) selbg=$(hc get window_border_active_color) selfg='#101010' +bordercolor="#26221C" +separator="^bg()^fg($selbg)|" +visible=true +date="" +pystat= +windowtitle="" -#### -# Try to find textwidth binary. -# In e.g. Ubuntu, this is named dzen2-textwidth. + +####################################################################################### +############################# BASIC SANITY CHECKS ##################################### +####################################################################################### + +if [ -z "$geometry" ] ;then + echo "Invalid monitor $monitor" + exit 1 +fi if which textwidth &> /dev/null ; then textwidth="textwidth"; elif which dzen2-textwidth &> /dev/null ; then @@ -28,70 +39,49 @@ else echo "This script requires the textwidth tool of the dzen2 project." exit 1 fi -#### -# true if we are using the svn version of dzen2 -# depending on version/distribution, this seems to have version strings like -# "dzen-" or "dzen-x.x.x-svn" if dzen2 -v 2>&1 | head -n 1 | grep -q '^dzen-\([^,]*-svn\|\),'; then dzen2_svn="true" else dzen2_svn="" fi - if awk -Wv 2>/dev/null | head -1 | grep -q '^mawk'; then - # mawk needs "-W interactive" to line-buffer stdout correctly - # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=593504 uniq_linebuffered() { awk -W interactive '$0 != l { print ; l=$0 ; fflush(); }' "$@" } else - # other awk versions (e.g. gawk) issue a warning with "-W interactive", so - # we don't want to use it there. uniq_linebuffered() { awk '$0 != l { print ; l=$0 ; fflush(); }' "$@" } fi +####################################################################################### +############################# EVENT LOOP/INPUT ######################################## +####################################################################################### + + hc pad $monitor $panel_height - { - ### Event generator ### - # based on different input data (mpc, date, hlwm hooks, ...) this generates events, formed like this: - # \t [...] - # e.g. - # date ^fg(#efefef)18:33^fg(#909090), 2013-10-^fg(#efefef)29 - - #mpc idleloop player & - while true ; do - # "date" output is checked once a second, but an event is only - # generated if the output changed compared to the previous run. - date +$'date\t^fg(#efefef)%H:%M^fg(#909090), %Y-%m-^fg(#efefef)%d' - sleep 1 || break - done > >(uniq_linebuffered) & - while true ; do printf 'pystat\t%s\n' "$($HOME/.config/herbstluftwm/hl_panel_content.py)" sleep 1 || break done > >(uniq_linebuffered) & + ## save pid and wait for signal ## childpid=$! hc --idle kill $childpid + } 2> /dev/null | { + + +####################################################################################### +################################## TAGS ############################################## +####################################################################################### + + ### GET AND PARSE OUTPUT FOR TAGS FROM HERBSTCLIENT ### + IFS=$'\t' read -ra tags <<< "$(hc tag_status $monitor)" - visible=true - date="" - pystat= - windowtitle="" while true ; do - - ### Output ### - # This part prints dzen data based on the _previous_ data handling run, - # and then waits for the next event to happen. - - bordercolor="#26221C" - separator="^bg()^fg($selbg)|" - # draw tags for i in "${tags[@]}" ; do case ${i:0:1} in '#') @@ -110,40 +100,30 @@ hc pad $monitor $panel_height echo -n "^bg()^fg(#ababab)" ;; esac + + ### MAKE TAGS CLICKABLE IF DZEN VERSION SUPPORTS IT ## if [ ! -z "$dzen2_svn" ] ; then - # clickable tags if using SVN dzen echo -n "^ca(1,\"${herbstclient_command[@]:-herbstclient}\" " echo -n "focus_monitor \"$monitor\" && " echo -n "\"${herbstclient_command[@]:-herbstclient}\" " echo -n "use \"${i:1}\") ${i:1} ^ca()" else - # non-clickable tags if using older dzen echo -n " ${i:1} " fi done echo -n "$separator" echo -n "^bg()^fg() ${windowtitle//^/^^}" - ####################### Interface to python layer ######################### - #right="$($HOME/.config/herbstluftwm/hl_panel_content.py) $date" - - right="${pystat}${date}" + ### PADDING FOR PANEL TEXT ### + + right="${pystat}" right_text_only=$(echo -n "$right" | sed 's.\^[^(]*([^)]*)..g') - # get width of right aligned text.. and add some space.. width=$($textwidth "$font" "$right_text_only ") - len=$(expr $(echo -n "$right" | wc -c) / 3) - echo -n "^pa($(($panel_width - $width - $len + 10)))$right" + echo -n "^pa($(($panel_width - $width)))$right" echo - ### Data handling ### - # This part handles the events generated in the event loop, and sets - # internal variables based on them. The event and its arguments are - # read into the array cmd, then action is taken depending on the event - # name. - # "Special" events (quit_panel/togglehidepanel/reload) are also handled - # here. + ### WAIT FOR INPUT DATA FROM EVENT LOOP ### - # wait for next event IFS=$'\t' read -ra cmd || break # find out event origin case "${cmd[0]}" in @@ -184,14 +164,12 @@ hc pad $monitor $panel_height focus_changed|window_title_changed) windowtitle="${cmd[@]:2}" ;; - #player) - # ;; esac done - ### dzen2 ### - # After the data is gathered and processed, the output of the previous block - # gets piped to dzen2. +####################################################################################### +############################ PIPE ALL THAT SHIT TO DZEN ############################## +####################################################################################### } 2> /dev/null | dzen2 -w $panel_width -x $x -y $y -fn "$font" -h $panel_height \ -e 'button3=;button4=exec:herbstclient use_index -1;button5=exec:herbstclient use_index +1' \