Commit 46bf9e05 authored by epsi sayidina's avatar epsi sayidina

herbstluftwm putting it all together

parent 84a0c809
......@@ -3,7 +3,7 @@
DIR=$(dirname "$0")
. ${DIR}/assets/gmc.sh
. ${DIR}/gmc.sh
. ${DIR}/config.sh
. ${DIR}/helper.sh
. ${DIR}/startup.sh
......
#!/usr/bin/env bash
event_generator_top() {
### Event generator ###
# based on different input data (mpc, date, hlwm hooks, ...) this generates events, formed like this:
# <eventname>\t<data> [...]
# e.g.
# date ^fg(#efefef)18:33^fg(#909090), 2013-10-^fg(#efefef)29
# endless loop can be written as
# while true ; do
# or
# while :; do
# date
while :; do
# "date" output is checked once a second, but an event is only
# generated if the output changed compared to the previous run.
evDate
sleep 1 || break
done > >(uniq_linebuffered) &
local date_pid=$!
# hlwm events
hc --idle
# exiting; kill stray event-emitting processes
kill $date_pid
}
event_generator_bottom() {
# player (mpd)
mpc idleloop player &
local mpc_pid=$!
# host
while true ; do
evHost
sleep 1h || break
done > >(uniq_linebuffered) &
local host_pid=$!
# cpu
while true ; do
evCPU
sleep 3 || break
done > >(uniq_linebuffered) &
local cpu_pid=$!
# net
while true ; do
evNet
sleep 7 || break
done > >(uniq_linebuffered) &
local net_pid=$!
# batch
while true ; do
# evVolume
# evMemory
# evDisk
evCPU
evSSID
evNet
# evUptime
sleep 1m || break
done &
local batch_pid=$!
# updates in
# while true ; do
# evUpdates
# sleep 1m || break
# done &
# updates_pid=$!
# hlwm events
hc --idle
# exiting; kill stray event-emitting processes
kill $mpc_pid $host_id $cpu_id $net_id $batch_pid
# kill $updates_pid
}
generated_output_top() {
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.
# draw tags
for i in "${tags[@]}" ; do
output_by_tagmark_pre $i
output_by_tagnumber $i
output_by_tagmark_post $i
done
output_leftside_top
output_rightside_top
handle_cmd_event
done
### dzen2 ###
# After the data is gathered and processed, the output of the previous block
# gets piped to dzen2.
}
generated_output_bottom() {
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.
output_leftside_bottom
output_rightside_bottom
handle_cmd_event
done
### dzen2 ###
# After the data is gathered and processed, the output of the previous block
# gets piped to dzen2.
}
handle_cmd_event() {
### 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 next event
IFS=$'\t' read -ra cmd || break
# find out event origin
case "${cmd[0]}" in
reload)
pkill dzen2
exit
;;
quit_panel)
exit
;;
tag*)
# http://www.tldp.org/LDP/abs/html/x17837.html#HERESTRINGSREF
# echo "resetting tags" >&2
setTagValue
;;
focus_changed|window_title_changed)
setWindowtitle "${cmd[@]:2}"
;;
date)
# echo "resetting date" >&2
setDate
;;
mpd_player|player)
setMPD
;;
volume)
setVolume "${cmd[@]:1}"
;;
memory)
setMemory "${cmd[@]:1}"
;;
disk)
setDisk "${cmd[@]:1}"
;;
cpu)
setCPU "${cmd[@]:1}"
;;
ssid)
setSSID "${cmd[@]:1}"
;;
net)
setNet
;;
uptime)
setUptime "${cmd[@]:1}"
;;
host)
setHost "${cmd[@]:1}"
;;
updates)
setUpdates "${cmd[@]:1}"
;;
esac
}
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# Initial Value
init_segments() {
setDate
setWindowtitle ""
setTagValue
setMPD
#setMemory
#setDisk
helperCPU
helperNet
}
#!/usr/bin/env bash
####
# Try to find textwidth binary.
# In e.g. Ubuntu, this is named dzen2-textwidth.
if which textwidth &> /dev/null ; then
textwidth="textwidth";
elif which dzen2-textwidth &> /dev/null ; then
textwidth="dzen2-textwidth";
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
# https://www.gnu.org/software/gawk/manual/html_node/I_002fO-Functions.html
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
#!/usr/bin/env bash
init_theme() {
theme_config_default=~/.config/herbstluftwm/bash/dzen2/themes/dark-colorful.sh
theme_config=~/.config/herbstluftwm/bash/dzen2/themes/${theme}.sh
[ -x "$theme_config" ] || theme_config=$theme_config_default
. $theme_config
}
output_by_tagmark_pre() {
$i=$1
local tagmark=${i:0:1}
theme_tagmark_pre $tagmark
}
output_by_tagmark_post() {
$i=$1
local tagmark=${i:0:1}
theme_tagmark_post $tagmark
}
output_by_tagnumber() {
i=$1
local index=${i:1}-1
local key=${tag_shows[$index]}
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}\") ${key} ^ca() "
else
# non-clickable tags if using older dzen
echo -n " ${key} "
fi
}
rightside_space() {
# small adjustments
local adjustment=$1
#using global $right
local right_text_only=$(echo -n "$right" | sed 's.\^[^(]*([^)]*)..g')
# get width of right aligned text.. and add some space..
local width=$($textwidth "$font" "$right_text_only ")
echo -n "^pa($(($panel_width - $width -$adjustment)))"
}
output_leftside_top() {
local left=" ^r(5x0) $separator ^r(5x0) "
left+="$segmentWindowtitle"
echo -n $left
}
output_rightside_top() {
theme_rightside_top
}
output_leftside_bottom() {
theme_leftside_bottom
}
output_rightside_bottom() {
theme_rightside_bottom
}
#!/usr/bin/env bash
hc() { "${herbstclient_command[@]:-herbstclient}" "$@" ;}
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# theme
# Four themes: [ 'dark-colorful', 'bright-colorful', 'dark-arrow', 'bright-arrow' ]
theme='bright-arrow'
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# geometry calculation
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]}
panel_height=24
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# google material colors
. ~/.config/herbstluftwm/bash/assets/gmc.sh
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# libraries
. ~/.config/herbstluftwm/bash/dzen2/vars.sh
. ~/.config/herbstluftwm/bash/dzen2/helper.sh
. ~/.config/herbstluftwm/bash/dzen2/segments.sh
. ~/.config/herbstluftwm/bash/dzen2/output.sh
. ~/.config/herbstluftwm/bash/dzen2/generate.sh
init_theme
init_segments
# do `man herbsluftclient`, and type \pad to search what it means
# hc pad $monitor $panel_height 0 $panel_height 0
hc pad $monitor $panel_height 0 $panel_height 0
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# dzen Parameters
dzen2_top_parameters=" -x $x -y $y -w $panel_width -h 24"
dzen2_top_parameters+=" -fn $font"
dzen2_top_parameters+=" -ta l -bg $bgcolor -fg $fgcolor"
dzen2_top_parameters+=" -title-name dzentop"
dzen2_bottom_parameters=" -x $x -y -24 -w $panel_width -h 24"
dzen2_bottom_parameters+=" -fn $font_bottom"
dzen2_bottom_parameters+=" -ta l -bg $bgcolor -fg $fgcolor"
dzen2_bottom_parameters+=" -title-name dzenbottom"
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# By redirecting stderr to /dev/null, you effectively suppress these messages.
# 2> /dev/null
event_generator_top 2> /dev/null | generated_output_top 2> /dev/null | dzen2 $dzen2_top_parameters \
-e 'button3=;button4=exec:herbstclient use_index -1;button5=exec:herbstclient use_index +1' &
# event_generator_bottom 2> /dev/null | generated_output_bottom 2> /dev/null | dzen2 $dzen2_bottom_parameters &
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# optional transparency
# https://github.com/wildefyr/transset-df
# sleep 1 && exec `(transset-df .8 -n dzenbottom >/dev/null 2>&1 &)` &
# sleep 2 && exec `(transset-df .8 -n dzentop >/dev/null 2>&1 &)` &
# you may use xorg-transset instead of transset-df
# sleep 1 && exec `(transset .8 -n dzenbottom >/dev/null 2>&1 &)` &
sleep 2 && exec `(transset .8 -n dzentop >/dev/null 2>&1 &)` &
#!/usr/bin/env bash
# note:
# * Debian/ubuntu based use /sbin/iw instead of /iw
setTagValue() {
# http://wiki.bash-hackers.org/commands/builtin/read
# http://wiki.bash-hackers.org/syntax/shellvars#ifs
# http://www.tldp.org/LDP/abs/html/x17837.html#HERESTRINGSREF
IFS=$'\t' read -ra tags <<< "$(hc tag_status $monitor)"
}
evDate() {
date +$'date\t%H:%M'
}
setDate() {
local iconDate="$preIcon$postIcon"
local date=$(date +"%Y-%m")
local day=$(date +"%d")
local iconTime="$preIcon$postIcon"
local time=$(date +"%H:%M")
case $theme in
'bright-arrow')
segmentDate=" $iconTime ^fg(${color['grey200']})$time, "
segmentDate+="$iconDate ^fg(${color['grey500']})$date-^fg(${color['grey200']})$day"
;;
'dark-arrow')
segmentDate=" $iconTime ^fg(${color['grey200']})$time, "
segmentDate+="$iconDate ^fg(${color['grey500']})$date-^fg(${color['grey200']})$day"
;;
'bright-colorful')
segmentDate=" $iconTime ^fg(${color['grey900']})$time, "
segmentDate+="$iconDate ^fg(${color['grey600']})$date-^fg(${color['grey900']})$day"
;;
*) # 'dark-colorful'
segmentDate=" $iconTime ^fg(${color['grey200']})$time, "
segmentDate+="$iconDate ^fg(${color['grey500']})$date-^fg(${color['grey200']})$day"
;;
esac
}
evVolume() {
local value=$(amixer get Master | tail -1 | sed 's/.*\[\([0-9]*%\)\].*/\1/')
echo -e "volume\t$value"
}
setVolume() {
local icon="$preIcon$postIcon"
segmentVolume="$icon $labelColor Vol $valueColor$1"
}
setWindowtitle() {
local icon="$preIcon$postIcon"
# "${segmentWindowtitle//^/^^}"
case $theme in
'bright-arrow')
segmentWindowtitle=" $icon ^bg()^fg(${color['grey700']}) $1"
;;
'dark-arrow')
segmentWindowtitle=" $icon ^bg()^fg(${color['grey500']}) $1"
;;
'bright-colorful')
segmentWindowtitle=" $icon ^bg()^fg(${color['grey700']}) $1"
;;
*) # 'dark-colorful'
segmentWindowtitle=" $icon ^bg()^fg(${color['grey500']}) $1"
;;
esac
}
setMPD() {
case $theme in
'bright-arrow')
local format="^fg(#${color['grey900']})[%artist% ^fg()- ]^fg(#${color['grey300']})[%title%]"
;;
'dark-arrow')
local format="^fg(#${color['grey100']})[%artist% ^fg()- ]^fg(#${color['yellow500']})[%title%]"
;;
'bright-colorful')
local format="^fg(#${color['blue500']})[%artist% ^fg()- ]^fg(#${color['pink700']})[%title%]"
;;
*) # 'dark-colorful'
local format="^fg(#${color['blue300']})[%artist% ^fg()- ]^fg(#${color['yellow500']})[%title%]"
;;
esac
local iconPlay="$preIcon$postIcon"
local iconPause="$preIcon$postIcon"
segmentMPD="$iconPlay "$(mpc current -f "$format")
}
evSSID() {
local wifi=$(iw dev | grep Interface | awk '{print $2}')
local value=""
if [ \"$wifi\" ]; then
value=$(iw dev $wifi link | grep SSID: | awk '{print $2 $3}')
fi
echo -e "ssid\t$value"
}
setSSID() {
local icon="$preIcon$postIcon"
segmentSSID="$icon $valueColor$1"
}
evMemory() {
local mem_total=$(free | awk 'FNR == 2 {print $2}')
local mem_used=$(free | awk 'FNR == 2 {print $3}')
local value=$[$mem_used * 100 / $mem_total]
echo -e "memory\t$value"
}
setMemory() {
local icon="$preIcon$postIcon"
segmentMemory="$icon $labelColor Mem $valueColor$1%"
}
evDisk() {
local value=$(df /home -h | awk 'FNR == 2 {print $5}' | sed s/%//)
echo -e "disk\t$value"
}
setDisk() {
local icon="$preIcon$postIcon"
segmentDisk="$icon $labelColor Disk $valueColor$1%"
}
evCPU() {
helperCPU
local value=$cpu_util
echo -e "cpu\t$value"
}
setCPU() {
local icon="$preIcon$postIcon"
segmentCPU="$icon $labelColor CPU $valueColor$1%"
}
evNet() {
local value="$RX_text $TX_text"
echo -e "net\t$value"
}
setNet() {
helperNet
local iconUp="$preIcon$postIcon"
local iconDown="$preIcon$postIcon"
segmentNet="$labelColor Net $iconUp $valueColor$TX_text $iconDown $valueColor$RX_text"
}
evUptime() {
local value=$(uptime -p)
echo -e "uptime\t$value"
}
setUptime() {
#  Uptime
local icon="$preIcon$postIcon"
segmentUptime="$icon $labelColor Uptime $valueColor$1"
}
evHost() {
# I prefer $(uname -r)
local value=$(uname -n)
echo -e "host\t$value"
}
setHost() {
#  Machine
#  Home
local icon="$preIcon$postIcon"
segmentHost="$icon $labelColor Host $valueColor$1"
}
evUpdates() {
local value=$(pacman -Qu | wc -l)
echo -e "updates\t$value"
}
setUpdates() {
local icon="$preIcon$postIcon"
segmentUpdates="$icon $labelColor Updates $valueColor$1"
}
helperNet() {
local interface=$(iw dev | grep Interface | awk '{print $2}')
if [ "$interface" ]; then
# Read first datapoint
read TX_prev < /sys/class/net/$interface/statistics/tx_bytes
read RX_prev < /sys/class/net/$interface/statistics/rx_bytes
sleep 1
# Read second datapoint
read TX_curr < /sys/class/net/$interface/statistics/tx_bytes
read RX_curr < /sys/class/net/$interface/statistics/rx_bytes
# compute
local TX_diff=$((TX_curr-TX_prev))
local RX_diff=$((RX_curr-RX_prev))
# printout var
TX_text=$(echo "scale=1; $TX_diff/1024" | bc | awk '{printf "%.1f", $0}')
RX_text=$(echo "scale=1; $RX_diff/1024" | bc | awk '{printf "%.1f", $0}')
fi;
}
helperCPU() {
# Read /proc/stat file (for first datapoint)
read cpu user nice system idle iowait irq softirq steal guest< /proc/stat
# compute active and total utilizations
local cpu_active_prev=$((user+system+nice+softirq+steal))
local cpu_total_prev=$((user+system+nice+softirq+steal+idle+iowait))
# echo 'cpu_active_prev = '.cpu_active_prev
sleep 1
# Read /proc/stat file (for second datapoint)
read cpu user nice system idle iowait irq softirq steal guest< /proc/stat
# compute active and total utilizations
local cpu_active_cur=$((user+system+nice+softirq+steal))
local cpu_total_cur=$((user+system+nice+softirq+steal+idle+iowait))
# compute CPU utilization (%)
cpu_util=$((100*( cpu_active_cur-cpu_active_prev ) / (cpu_total_cur-cpu_total_prev) ))
}
#!/usr/bin/env bash
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# dzen panel color
bgcolor=${color['white']}
fgcolor=${color['black']}
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# theme
#plain
separator="^bg()^fg(${color['black']})|^bg()^fg()"
preIcon="^fg(${color['yellow500']})$FontAwesome"
postIcon="^fn()^fg()"
labelColor="^fg(${color['grey300']})"
valueColor="^fg(${color['grey900']})"
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# dzen2 panel parts
theme_tagmark_pre() {
local deco=""
local tagmark=$1
case $tagmark in
'#')
deco+="^bg(${color['blue500']})^fg(${color['white']})$right_hard_arrow"
deco+="^bg(${color['blue500']})^fg(${color['black']})"
;;
'+') deco+="^bg(${color['yellow500']})^fg(${color['grey400']})" ;;
':') deco+="^bg()^fg(${color['black']})" ;;
'!') deco+="^bg(${color['red500']})^fg(${color['black']})" ;;
*) deco+="^bg()^fg(${color['grey600']})" ;;
esac
echo -n $deco
}
theme_tagmark_post() {
local deco=""
local tagmark=$1
case $tagmark in
'#')
deco+="^bg(${color['white']})^fg(${color['blue500']})$right_hard_arrow"
;;
*) ;; # do nothing
esac
echo -n $deco
}