420 lines
9.9 KiB
Bash
420 lines
9.9 KiB
Bash
|
#!/usr/bin/env bash
|
||
|
|
||
|
hostname=$(hostname)
|
||
|
|
||
|
hc() { herbstclient "$@" ;}
|
||
|
panel_height=20
|
||
|
|
||
|
for monitor in $(hc list_monitors | cut -d: -f1); do
|
||
|
hc pad "$monitor" "$panel_height" 0 0 0
|
||
|
done
|
||
|
|
||
|
{ sleep 1; exec trayer --SetPartialStrut false --edge top --height 20 --widthtype request --align right --tint 0x080808 --transparent true --alpha 0; } &
|
||
|
|
||
|
fggreen='%{F#95e454}'
|
||
|
fgblue='%{F#88b8f6}'
|
||
|
fgred='%{F#e5796d}'
|
||
|
fgdark='%{F#080808}'
|
||
|
fgend='%{F-}'
|
||
|
|
||
|
bggreen='%{B#95e454}'
|
||
|
bgblue='%{B#88b8f6}'
|
||
|
bgred='%{B#e5796d}'
|
||
|
bglight='%{B#333333}'
|
||
|
bgend='%{B-}'
|
||
|
|
||
|
ulblue='%{U#88b8f6+u}'
|
||
|
ulend='%{-u}'
|
||
|
|
||
|
handle_signal() {
|
||
|
FORCE_REFRESH=1
|
||
|
}
|
||
|
|
||
|
handle_kill() {
|
||
|
kill 0
|
||
|
rm "$fifo"
|
||
|
exit 0
|
||
|
}
|
||
|
|
||
|
trap handle_signal SIGUSR1
|
||
|
trap handle_kill SIGINT
|
||
|
|
||
|
fifo="/tmp/panel_text"
|
||
|
if [ ! -p "$fifo" ]; then
|
||
|
mkfifo "$fifo"
|
||
|
fi
|
||
|
|
||
|
msgfifo="/tmp/panel_msg"
|
||
|
if [ ! -p "$msgfifo" ]; then
|
||
|
mkfifo "$msgfifo"
|
||
|
fi
|
||
|
|
||
|
# process to handle lemonbar clicks
|
||
|
{
|
||
|
while IFS= read -r line; do
|
||
|
IFS="-" read -r -a command <<< "$line"
|
||
|
if [ "${command[0]}" = "tag" ]; then
|
||
|
# not sure how to specify a monitor, but probably don't need to anyway
|
||
|
monitor="${command[1]}"
|
||
|
index=$(( "${command[2]}" - 1 ))
|
||
|
if [ "$index" -eq -1 ]; then
|
||
|
index=9
|
||
|
fi
|
||
|
herbstclient chain , lock , focus_monitor "$monitor" , use_index "$index" , spawn stickyctl get-sticky , unlock
|
||
|
fi
|
||
|
done < "$msgfifo"
|
||
|
} &
|
||
|
|
||
|
tail -f "$fifo" | stdbuf -oL lemonbar -d -p -a 100 -g "x${panel_height}" -f "Drafting* Mono:pixelsize=18:antialias=true" -f "Unifont:pixelsize=18:antialias=true" -B "#080808" -F "#e3e0d7" > "$msgfifo" &
|
||
|
|
||
|
append_segment() {
|
||
|
local seconds=$1
|
||
|
local name=$2
|
||
|
local param=$3
|
||
|
shift
|
||
|
local now=$SECONDS
|
||
|
local escparam
|
||
|
segment_text=''
|
||
|
|
||
|
escparam="${param//\//_}"
|
||
|
eval "local lastrun=\$${name}${escparam}_lastrun"
|
||
|
if [ -z "$lastrun" ]; then
|
||
|
lastrun=0
|
||
|
fi
|
||
|
if [ -n "$FORCE_REFRESH" ] || [ "$lastrun" -eq 0 ] || (( SECONDS - lastrun >= seconds )); then
|
||
|
"$@"
|
||
|
eval "${name}${escparam}_lastrun=\$now"
|
||
|
eval "${name}${escparam}_lastoutput=\"$segment_text\""
|
||
|
panel_text="$panel_text$segment_text"
|
||
|
else
|
||
|
eval "panel_text=\"\$panel_text\$${name}${escparam}_lastoutput\""
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
append_separator() {
|
||
|
panel_text="$panel_text "
|
||
|
}
|
||
|
|
||
|
append_percent_icon() {
|
||
|
local pct=$1
|
||
|
segment_text="$segment_text$bglight"
|
||
|
if (( pct < 12 )); then
|
||
|
segment_text="$segment_text▁"
|
||
|
elif (( pct < 25 )); then
|
||
|
segment_text="$segment_text▂"
|
||
|
elif (( pct < 38 )); then
|
||
|
segment_text="$segment_text▃"
|
||
|
elif (( pct < 51 )); then
|
||
|
segment_text="$segment_text▄"
|
||
|
elif (( pct < 64 )); then
|
||
|
segment_text="$segment_text▅"
|
||
|
elif (( pct < 77 )); then
|
||
|
segment_text="$segment_text▆"
|
||
|
elif (( pct < 90 )); then
|
||
|
segment_text="$segment_text▆"
|
||
|
else
|
||
|
segment_text="$segment_text█"
|
||
|
fi
|
||
|
segment_text="$segment_text$bgend%{O5}"
|
||
|
}
|
||
|
|
||
|
segment_tags() {
|
||
|
local monitor=$1
|
||
|
local tags
|
||
|
local prefix
|
||
|
local tagclass
|
||
|
|
||
|
IFS=$'\t' read -ra tags <<< "$(hc tag_status "$monitor")"
|
||
|
segment_text=''
|
||
|
for i in "${tags[@]}"; do
|
||
|
prefix=${i:0:1}
|
||
|
case $prefix in
|
||
|
'.') tagclass=$fgend$bgend ;;
|
||
|
'+') tagclass=$bgblue$fgdark ;;
|
||
|
'#') tagclass=$bggreen$fgdark ;;
|
||
|
'!') tagclass=$bgred$fgdark ;;
|
||
|
'-') tagclass=$ulblue$bglight$fgblue ;;
|
||
|
'%') tagclass=$ulblue$bglight$fgblue ;;
|
||
|
*) tagclass=$bglight ;;
|
||
|
esac
|
||
|
segment_text="$segment_text%{A:tag-$monitor-${i:1}:}$tagclass%{O8}${i:1}%{O8}%{A}$fgend$bgend$ulend"
|
||
|
done
|
||
|
}
|
||
|
|
||
|
segment_timew() {
|
||
|
local curday
|
||
|
local active
|
||
|
local twclass
|
||
|
local twicon
|
||
|
|
||
|
if hash timew 2>/dev/null; then
|
||
|
active=$(timew get dom.active)
|
||
|
if [ "$active" = "1" ]; then
|
||
|
twicon=""
|
||
|
twclass=$fggreen
|
||
|
else
|
||
|
twicon=""
|
||
|
twclass=$fgred
|
||
|
fi
|
||
|
|
||
|
curday=$(timew summary | tail -n2 | head -n1 | awk '{ print $1 }')
|
||
|
if [ "$curday" = "No" ]; then
|
||
|
curday='0:00'
|
||
|
else
|
||
|
curday="${curday%:*}"
|
||
|
fi
|
||
|
|
||
|
segment_text="${twclass}${twicon}${fgend}%{O5}$curday"
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
segment_keyboard() {
|
||
|
local kblayout
|
||
|
local kbclass
|
||
|
local kbicon
|
||
|
|
||
|
kblayout=$(setxkbmap -query | grep variant | awk '{ print $2 }' | tr -d ',')
|
||
|
if [ "$kblayout" = "dvorak" ]; then
|
||
|
kbclass=$fgred
|
||
|
kbicon=""
|
||
|
else
|
||
|
kbclass=$fggreen
|
||
|
kbicon=""
|
||
|
fi
|
||
|
segment_text="$kbclass$kbicon$fgend"
|
||
|
}
|
||
|
|
||
|
segment_network() {
|
||
|
local net
|
||
|
local neticon
|
||
|
local btpower
|
||
|
local btconn
|
||
|
local bticon
|
||
|
local nasavpn
|
||
|
local nasaicon
|
||
|
|
||
|
# network device
|
||
|
net=$(ip route get 1.1.1.1 | grep -Po '(?<=dev\s)\w+' | cut -f1 -d ' ')
|
||
|
if ! [ "$net" ]; then
|
||
|
neticon="%{O3}$fgred$fgend"
|
||
|
else
|
||
|
neticon="%{O3}$fggreenﯱ$fgend"
|
||
|
fi
|
||
|
|
||
|
if hash bluetoothctl 2>/dev/null; then
|
||
|
# bluetooth status
|
||
|
btpower=$(bluetoothctl show | grep Powered | awk '{ print $2 }')
|
||
|
if [ "$btpower" = "yes" ]; then
|
||
|
btconn=$(bluetoothctl devices | cut -f2 -d' ' | while read uuid; do bluetoothctl info $uuid; done | grep "Connected: yes")
|
||
|
if [ -z "$btconn" ]; then
|
||
|
bticon="${fggreen}$fgend"
|
||
|
else
|
||
|
bticon="${fgblue}$fgend"
|
||
|
fi
|
||
|
else
|
||
|
bticon="${fgred}$fgend"
|
||
|
fi
|
||
|
fi
|
||
|
|
||
|
if hash docker 2>/dev/null; then
|
||
|
nasavpn=$(docker ps --format "{{.Names}}" | grep nasavpn)
|
||
|
if [ -n "$nasavpn" ]; then
|
||
|
nasaicon="%{O3}${fggreen}異$fgend"
|
||
|
else
|
||
|
nasaicon="%{O3}${fgred}異$fgend"
|
||
|
fi
|
||
|
fi
|
||
|
|
||
|
segment_text="$bticon$nasaicon$neticon"
|
||
|
}
|
||
|
|
||
|
segment_memory() {
|
||
|
local mempct
|
||
|
local memclass
|
||
|
|
||
|
mempct=$(free | grep Mem | awk '{ print int($3/$2 * 100.0 + 0.5) }')
|
||
|
if [ "$mempct" -gt 75 ]; then
|
||
|
memclass=$fgred
|
||
|
elif [ "$mempct" -gt 50 ]; then
|
||
|
memclass=$fgblue
|
||
|
else
|
||
|
memclass=$fggreen
|
||
|
fi
|
||
|
segment_text=$memclass
|
||
|
append_percent_icon "$mempct"
|
||
|
segment_text="${segment_text}$fgend"
|
||
|
}
|
||
|
|
||
|
segment_disk() {
|
||
|
local dpath=$1
|
||
|
local diskpct
|
||
|
local diskclass
|
||
|
local diskicon
|
||
|
|
||
|
if [ "$dpath" = "/" ]; then
|
||
|
diskicon=""
|
||
|
else
|
||
|
diskicon=""
|
||
|
fi
|
||
|
|
||
|
diskpct=$(df --output=pcent "$dpath" | sed 1d | sed 's/^[ \t]*//' | sed 's/%.*//')
|
||
|
if [ "$diskpct" -gt 90 ]; then
|
||
|
diskclass=$fgred
|
||
|
elif [ "$diskpct" -gt 75 ]; then
|
||
|
diskclass=$fgblue
|
||
|
else
|
||
|
diskclass=$fggreen
|
||
|
fi
|
||
|
segment_text=$diskclass
|
||
|
append_percent_icon "$diskpct"
|
||
|
segment_text="${segment_text}$diskicon$fgend"
|
||
|
}
|
||
|
|
||
|
segment_cpu() {
|
||
|
local cpupct
|
||
|
local cpuclass
|
||
|
|
||
|
cpupct=$(awk '{u=$2+$4; t=$2+$4+$5; if (NR==1){u1=u; t1=t;} else print ($2+$4-u1) * 100 / (t-t1); }' <(grep 'cpu ' /proc/stat) <(sleep 1;grep 'cpu ' /proc/stat) | awk '{print int($1+0.5)}')
|
||
|
if [ "$cpupct" -gt 90 ]; then
|
||
|
cpuclass=$fgred
|
||
|
elif [ "$cpupct" -gt 25 ]; then
|
||
|
cpuclass=$fgblue
|
||
|
else
|
||
|
cpuclass=$fggreen
|
||
|
fi
|
||
|
segment_text=$cpuclass
|
||
|
append_percent_icon "$cpupct"
|
||
|
segment_text="${segment_text}$fgend"
|
||
|
}
|
||
|
|
||
|
segment_audio() {
|
||
|
local audiohdmi
|
||
|
local audiobt
|
||
|
local audicon
|
||
|
local volpct
|
||
|
|
||
|
if hash pactl 2>/dev/null; then
|
||
|
# audio output device (hdmi/analog)
|
||
|
audiohdmi=$(pactl get-default-sink | grep hdmi)
|
||
|
audiobt=$(pactl get-default-sink | grep bluez)
|
||
|
fi
|
||
|
|
||
|
if [ -n "$audiobt" ]; then
|
||
|
audclass=$fgblue
|
||
|
audicon=''
|
||
|
else
|
||
|
audclass=$fggreen
|
||
|
if [ "$hostname" != "ellison" ]; then
|
||
|
if [ -z "$audiohdmi" ]; then
|
||
|
audicon=''
|
||
|
else
|
||
|
audicon='蓼'
|
||
|
fi
|
||
|
else
|
||
|
audicon='蓼'
|
||
|
fi
|
||
|
fi
|
||
|
if hash pamixer 2>/dev/null; then
|
||
|
volpct=$(pamixer --get-volume-human | sed 's/%//')
|
||
|
if [ "$volpct" = "muted" ]; then
|
||
|
audclass=$fgred
|
||
|
volpct="0"
|
||
|
fi
|
||
|
fi
|
||
|
segment_text=$audclass
|
||
|
append_percent_icon "$volpct"
|
||
|
segment_text="$segment_text$audicon$fgend"
|
||
|
}
|
||
|
|
||
|
segment_battery() {
|
||
|
local battpct
|
||
|
local batstat
|
||
|
local baticon
|
||
|
local batclass
|
||
|
|
||
|
if hash upower 2>/dev/null; then
|
||
|
# battery charge percent
|
||
|
battpct="$(upower --show-info $(upower --enumerate | grep -i 'BAT') | grep -E "percentage" | awk '{print $2}')"
|
||
|
battpct="${battpct%\%}"
|
||
|
|
||
|
# battery status (charging/charged/etc)
|
||
|
batstat="$(upower --show-info $(upower --enumerate | grep -i 'BAT') | grep -E "state" | awk '{print $2}')"
|
||
|
|
||
|
baticon='B'
|
||
|
|
||
|
if (( battpct > 80 )); then
|
||
|
batclass=$fggreen
|
||
|
elif (( battpct < 20 )); then
|
||
|
batclass=$fgred
|
||
|
else
|
||
|
batclass=$fgblue
|
||
|
fi
|
||
|
|
||
|
if [ "$batstat" = "fully-charged" ]; then
|
||
|
baticon="${baticon}%{O3}⇈"
|
||
|
elif [ "$batstat" = "discharging" ]; then
|
||
|
baticon="${baticon}%{O3}↓";
|
||
|
else
|
||
|
baticon="${baticon}%{O3}↑";
|
||
|
fi
|
||
|
|
||
|
segment_text="$batclass"
|
||
|
append_percent_icon "$battpct"
|
||
|
segment_text="$segment_text$baticon$fgend"
|
||
|
else
|
||
|
segment_text="$fggreenﮣ$fgend"
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
segment_date() {
|
||
|
segment_text="$(date +$'%a %b %d') $fgblue$(date +$'%H:%M')$fgend"
|
||
|
}
|
||
|
|
||
|
last_text=''
|
||
|
while true; do
|
||
|
{
|
||
|
full_text=''
|
||
|
for monitor in $(herbstclient list_monitors | cut -d: -f1); do
|
||
|
panel_text="%{S$monitor}%{l}"
|
||
|
append_segment 0 segment_tags "$monitor"
|
||
|
panel_text="$panel_text%{l}%{r}"
|
||
|
append_segment 60 segment_timew
|
||
|
append_separator
|
||
|
append_segment 60 segment_keyboard
|
||
|
append_separator
|
||
|
append_segment 10 segment_network
|
||
|
append_separator
|
||
|
panel_text="$panel_text%{A:conky:}"
|
||
|
append_segment 10 segment_memory
|
||
|
append_separator
|
||
|
append_segment 60 segment_disk "/"
|
||
|
append_separator
|
||
|
if [ "$hostname" != "ellison" ]; then
|
||
|
append_segment 60 segment_disk "/home"
|
||
|
append_separator
|
||
|
fi
|
||
|
append_segment 5 segment_cpu
|
||
|
append_separator
|
||
|
append_segment 60 segment_audio
|
||
|
append_separator
|
||
|
append_segment 30 segment_battery
|
||
|
panel_text="$panel_text%{A}"
|
||
|
append_separator
|
||
|
append_segment 60 segment_date
|
||
|
if [ "$monitor" -eq 0 ]; then
|
||
|
tray_width=$(xdotool search --classname panel | xargs -n1 xprop -id | grep 'program specified minimum size' | cut -d ' ' -f 5)
|
||
|
tray_width=$(( tray_width + 5 ))
|
||
|
panel_text="$panel_text%{O$tray_width}"
|
||
|
fi
|
||
|
panel_text="$panel_text%{r}"
|
||
|
full_text="$full_text$panel_text"
|
||
|
done
|
||
|
if [ "$full_text" != "$last_text" ]; then
|
||
|
echo -e "$full_text"
|
||
|
last_text="$full_text"
|
||
|
fi
|
||
|
} >> "$fifo"
|
||
|
unset FORCE_REFRESH
|
||
|
sleep 1
|
||
|
done
|