~q3cpma/dotfiles

bb6c63f4b99f1b35b1c330749d8c32ac9028aac8 — q3cpma 5 months ago 4ec701d
Update lemonbar
27 files changed, 55 insertions(+), 818 deletions(-)

M .config/lemonbar/README
M .config/lemonbar/bar.sh
M .config/lemonbar/bar_fifo.sh
M .config/lemonbar/config
M .config/lemonbar/cpu_usage.awk
R .config/lemonbar/{diskfree.awk => disk_usage.awk}
M .config/lemonbar/hwmon_temp.awk
D .config/lemonbar/lemonbar-tcl/README
D .config/lemonbar/lemonbar-tcl/bar.sh
D .config/lemonbar/lemonbar-tcl/bar.tcl
D .config/lemonbar/lemonbar-tcl/bar_fifo.sh
D .config/lemonbar/lemonbar-tcl/battery.sh
D .config/lemonbar/lemonbar-tcl/clock.sh
D .config/lemonbar/lemonbar-tcl/config
D .config/lemonbar/lemonbar-tcl/config.tcl
D .config/lemonbar/lemonbar-tcl/cpu_usage.awk
D .config/lemonbar/lemonbar-tcl/diskfree.awk
D .config/lemonbar/lemonbar-tcl/hwmon_temp.awk
D .config/lemonbar/lemonbar-tcl/memfree.awk
D .config/lemonbar/lemonbar-tcl/modules.tcl
D .config/lemonbar/lemonbar-tcl/mus_status.sh
D .config/lemonbar/lemonbar-tcl/netrate.awk
D .config/lemonbar/lemonbar-tcl/util.awk
D .config/lemonbar/lemonbar-tcl/util.tcl
A .config/lemonbar/mem_usage.awk
D .config/lemonbar/memfree.awk
M .config/lemonbar/netrate.awk
M .config/lemonbar/README => .config/lemonbar/README +9 -10
@@ 27,18 27,17 @@ Each script may also have its own dependencies.
    Date wrapper
* cpu_usage.awk
    Cpu usage in % (needs procfs)
* diskfree.awk
    Disk usage (in available / total size)
* memfree.awk
    Same for memory (needs procfs)
* disk_usage.awk
    Disk usage (in used / total size)
* mem_usage.awk
    Memory usage (needs procfs) using the same algo as free
* netrate.awk
    Network up and down rates, with cool graphs (needs sysfs)
* sensors_coretemp.awk
    Intel CPU temperature (needs lm_sensors)
* sensors_k10temp.awk
    AMD CPU temperature (needs lm_sensors)
* hwmon_temp.awk
    Device temperature using hwmon (needs an entry in /sys/class/hwmon/)
* mus_status.sh
    Status command for mus (https://repo.or.cz/mus.git) (needs mbcut)
    Status command for mus (https://git.sr.ht/~q3cpma/mus) (needs mbcut from
	https://git.sr.ht/~q3cpma/misc-tools)

mbcut can be found at https://repo.or.cz/misc-tools.git



@@ 50,5 49,5 @@ The only files you'll have to touch (unless a bug appears, of course) are
"config" and "bar.sh". If you add some new plugins, corresponding entries in
the case statement of "bar_fifo.sh" will have to be added.

Then it's just a matter of adding "~/.config/lemonbar/bar.sh &" to your bspwmrc
Then it's just a matter of adding "path/to/lemonbar/bar.sh &" to your bspwmrc
or .xinitrc.
\ No newline at end of file

M .config/lemonbar/bar.sh => .config/lemonbar/bar.sh +4 -4
@@ 27,12 27,12 @@ awk -vdelay="$hwmon_temp_delay" -vred="$red" -vprefix="$hwmon_temp_prefix" \
	-f util.awk -f hwmon_temp.awk >"$fifo" &

# Avail / total mem
awk -vdelay="$memfree_delay" -vred="$red" -vlow="$memfree_low" \
	-f util.awk -f memfree.awk >"$fifo" &
awk -vdelay="$mem_usage_delay" -vred="$red" -vhigh="$mem_usage_high" \
	-f util.awk -f mem_usage.awk >"$fifo" &

# Avail / total disk
awk -vdelay="$diskfree_delay" -vred="$red" -vmountpoint="$diskfree_mountpoint" \
	-vlow="$diskfree_low" -f util.awk -f diskfree.awk >"$fifo" &
awk -vdelay="$disk_usage_delay" -vred="$red" -vmountpoint="$disk_usage_mountpoint" \
	-vhigh="$disk_usage_high" -f util.awk -f disk_usage.awk >"$fifo" &

# Cpu usage (percentage)
awk -vdelay="$cpu_usage_delay" -vred="$red" -vhigh_pct="$cpu_usage_high" \

M .config/lemonbar/bar_fifo.sh => .config/lemonbar/bar_fifo.sh +1 -1
@@ 36,7 36,7 @@ do
			temp="${line#?}"
			;;
		M*)
			mus="mus: ${line#?}"
			mus="${line#?}"
			;;
		n*)
			net="net: ${line#?}"

M .config/lemonbar/config => .config/lemonbar/config +9 -9
@@ 13,20 13,20 @@ cmus_fmt='%A - %{?y?(%y) ?}%l - %{?n?%02n.?} %t%{?va? (%a)?}'
cpu_usage_delay=2
cpu_usage_high=90

hwmon_temp_prefix="/sys/class/hwmon/hwmon1/temp2"
hwmon_temp_prefix="/sys/class/hwmon/hwmon2/temp1"
hwmon_temp_delay=4

diskfree_delay=30
diskfree_low=.1
diskfree_mountpoint=~/Data
disk_usage_delay=30
disk_usage_high=.9
disk_usage_mountpoint=~/Data

memfree_delay=3
memfree_low=.25
mem_usage_delay=3
mem_usage_high=.75

netrate_bar_width=8
netrate_delay=2
netrate_high=.9
netrate_netif=enp7s0
netrate_netif=enp6s0
# These are in Kib/s
netrate_rxmax=1700
netrate_txmax=125
netrate_rxmax=81250
netrate_txmax=81250

M .config/lemonbar/cpu_usage.awk => .config/lemonbar/cpu_usage.awk +1 -1
@@ 11,7 11,7 @@ function stat_read()
BEGIN\
{
	stat_read()
	while(1)
	while (1)
	{
		sleep(delay)
		split($0, old)

R .config/lemonbar/diskfree.awk => .config/lemonbar/disk_usage.awk +2 -2
@@ 2,13 2,13 @@ BEGIN\
{
	auto_unit_init()
	cmd = "df -k -- " mountpoint
	while(1)
	while (1)
	{
		cmd | getline
		cmd | getline
		close(cmd)
		print "d" (($4 / $2 < low) ? red : "") \
			auto_unit_ratio($4 * 2^10, $2 * 2^10, "%.1f / %.1f %s")
			auto_unit_ratio($3 * 2^10, $2 * 2^10, "%.1f / %.1f %s")
		sleep(delay)
	}
}

M .config/lemonbar/hwmon_temp.awk => .config/lemonbar/hwmon_temp.awk +2 -3
@@ 7,17 7,16 @@ BEGIN\
	if (tmax)
	{
		tmax /= 1000
		while(1)
		while (1)
		{
			tcur = gets(prefix "_input") / 1000
			printf "t%s: %s%d°C\n", label, (tcur > tmax ? red : ""), tcur
			sleep(delay)
		}

	}
	else
	{
		while(1)
		while (1)
		{
			printf "t%s: %d°C\n", label, gets(prefix "_input") / 1000
			sleep(delay)

D .config/lemonbar/lemonbar-tcl/README => .config/lemonbar/lemonbar-tcl/README +0 -54
@@ 1,54 0,0 @@
        My simple script collection for lemonbar
        ========================================

Inspired mostly by the bspwm example (especially the FIFO loop concept) but
with some massive improvements. This is what I use, so it has some stuff
hardcoded like bspwm usage, font choice and config values and assumes a Linux
kernel (mostly because of procfs and sysfs).

Remember: NO RICE, NO LIFE!


    Dependencies
    ------------

Out of the box, it needs a POSIX environment (sh and awk, especially),
bspwm/bspc (easily removable), lemonbar (duh) and xdo.

Each script may also have its own dependencies.


    Script list
    -----------

* battery.sh
    Battery capacity (in %) and state (needs sysfs)
* clock.sh
    Date wrapper
* cpu_usage.awk
    Cpu usage in % (needs procfs)
* diskfree.awk
    Disk usage (in available / total size)
* memfree.awk
    Same for memory (needs procfs)
* netrate.awk
    Network up and down rates, with cool graphs (needs sysfs)
* sensors_coretemp.awk
    Intel CPU temperature (needs lm_sensors)
* sensors_k10temp.awk
    AMD CPU temperature (needs lm_sensors)
* mus_status.sh
    Status command for mus (https://repo.or.cz/mus.git) (needs mbcut)

mbcut can be found at https://repo.or.cz/misc-tools.git


    Usage
    -----

The only files you'll have to touch (unless a bug appears, of course) are
"config" and "bar.sh". If you add some new plugins, corresponding entries in
the case statement of "bar_fifo.sh" will have to be added.

Then it's just a matter of adding "~/.config/lemonbar/bar.sh &" to your bspwmrc
or .xinitrc.
\ No newline at end of file

D .config/lemonbar/lemonbar-tcl/bar.sh => .config/lemonbar/lemonbar-tcl/bar.sh +0 -56
@@ 1,56 0,0 @@
#!/bin/sh
# Dependencies: lemonbar, xdo
# Portability:	POSIX
set -eu


cd "$(dirname -- "$0")"
. ./config

mkfifo -- "$fifo"

trap 'exit' INT TERM HUP QUIT
trap 'rm -- "$fifo"; kill 0' EXIT


# bspwm workspaces status
bspc subscribe report >"$fifo" &

# Clock
sh clock.sh 1 >"$fifo" &

# Battery capacity (percentage)
# sh battery.sh "$battery_delay" >"$fifo" &

# Cpu temperature
awk -vdelay="$hwmon_temp_delay" -vred="$red" -vprefix="$hwmon_temp_prefix" \
	-f util.awk -f hwmon_temp.awk >"$fifo" &

# Avail / total mem
awk -vdelay="$memfree_delay" -vred="$red" -vlow="$memfree_low" \
	-f util.awk -f memfree.awk >"$fifo" &

# Avail / total disk
awk -vdelay="$diskfree_delay" -vred="$red" -vmountpoint="$diskfree_mountpoint" \
	-vlow="$diskfree_low" -f util.awk -f diskfree.awk >"$fifo" &

# Cpu usage (percentage)
awk -vdelay="$cpu_usage_delay" -vred="$red" -vhigh="$cpu_usage_high" \
	-f util.awk -f cpu_usage.awk >"$fifo" &

# RX and TX netrate (with graph)
awk -vdelay="$netrate_delay" -vred="$red" -vrxmax="$netrate_rxmax" \
	-vtxmax="$netrate_txmax" -vbarwidth="$netrate_bar_width" \
	-vnetif="$netrate_netif" -vhigh="$netrate_high" \
	-f util.awk -f netrate.awk >"$fifo" &


./bar_fifo.sh <"$fifo" | lemonbar -a 17 -u2 -F'#aaaaaa' -n"bspwm_bar" \
	-f'-xos4-terminus-medium-*-*-*-16-*-*-*-*-*-*-*' \
	-f'-mona-gothic-medium-r-*-*-14-*-*-*-*-*-jisx0208.1990-*' \
	-f'-misc-fixed-medium-r-normal-ja-13-*-*-*-*-*-*-*'| sh &

xdo below -t "$(xdo id -N Bspwm -n root | sort | head -n1)" \
	"$(xdo id -m -a "bspwm_bar")"

wait

D .config/lemonbar/lemonbar-tcl/bar.tcl => .config/lemonbar/lemonbar-tcl/bar.tcl +0 -21
@@ 1,21 0,0 @@
#!/usr/bin/env tclsh
set where [file dirname [info script]]
source [file join $where modules.tcl]


bar_init {{%{l}$bspwm%{r}} {$mus} {$netrate} {$cpu_usage} {$hwmon_temp}
	{$battery} {$memfree} {$diskfree} {$date}}

bspwm
mus /tmp/bar_mus.fifo
netrate enp7s0 750 100
cpu_usage
hwmon_temp /sys/devices/pci0000:00/0000:00:18.3/hwmon/hwmon1/temp1
if [file exists /sys/class/power_supply/BAT0/uevent] {
	battery /sys/class/power_supply/BAT0/uevent
}
memfree
diskfree ~/Data
date

vwait forever

D .config/lemonbar/lemonbar-tcl/bar_fifo.sh => .config/lemonbar/lemonbar-tcl/bar_fifo.sh +0 -89
@@ 1,89 0,0 @@
#!/bin/sh
# Dependencies: bspc (bspwm)
# Portability:	POSIX
set -eu

. "$(dirname -- "$0")"/config


tosuperscript()
{
	sed -e 's#0#⁰#g; s#1#¹#g; s#2#²#g; s#3#³#g; s#4#⁴#g; s#5#⁵#g; s#6#⁶#g' \
		-e 's#7#⁷#g; s#8#⁸#g; s#9#⁹#g'
}

leafnum()
{
	printf '(%s+1)/2\n' "$(bspc query -d "$1" -N | wc -l)" | bc | tosuperscript
}

while read -r line
do
	case "$line" in
		c*)
			clock="${line#?}"
			;;
		b*)
			bat="${line#?}"
			;;
		m*)
			mem="mem: ${line#?}"
			;;
		d*)
			disk="disk: ${line#?}"
			;;
		p*)
			cpu="cpu: ${line#?}"
			;;
		t*)
			temp="temp: ${line#?}"
			;;
		M*)
			mus="mus: ${line#?}"
			;;
		n*)
			net="net: ${line#?}"
			;;
		W*)
			wslist=
			OLDIFS=$IFS
			IFS=:
			for i in ${line#*:}
			do
				ws=${i#?}
				case "$i" in
					F*)
						wslist="$wslist%{R}$ws%{R} "
						;;
					O*)
						wslist="$wslist%{R}$ws$(leafnum "$ws")%{R} "
						;;
					o*)
						wslist="$wslist%{A:bspc desktop -f $ws:}$ws$(leafnum "$ws")%{A} "
						;;
					U*)
						wslist="$wslist%{F#aa0000}%{R}$ws$(leafnum "$ws")%{R}%{F-} "
						;;
					u*)
						wslist="$wslist%{A:bspc desktop -f $ws:}%{F#aa0000}$ws$(leafnum "$ws")%{F-}%{A} "
						;;
				esac
			done
			IFS=$OLDIFS
			;;
		*)
			printf 'Invalid line: %s\n' "$line" >&2
			exit 1
			;;
	esac
	out="%{l}${wslist:-}%{r}"
	out="$out${mus+$mus $bar_separator }"
	out="$out${net+$net $bar_separator }"
	out="$out${cpu+$cpu $bar_separator }"
	out="$out${temp+$temp $bar_separator }"
	out="$out${mem+$mem $bar_separator }"
	out="$out${disk+$disk $bar_separator }"
	out="$out${bat+$bat $bar_separator }"
	out="$out${clock:-}"
	printf '%s\n' "$out"
done

D .config/lemonbar/lemonbar-tcl/battery.sh => .config/lemonbar/lemonbar-tcl/battery.sh +0 -11
@@ 1,11 0,0 @@
set -eu

while true
do
	awk -F= \
		'/CAPACITY=/ {cap = $2}
		 /STATUS=/ {status = $2}
		 END {printf "bbat: %02u%% (%s)\n", cap, status}' \
		 /sys/class/power_supply/BAT0/uevent
	sleep "$1"
done

D .config/lemonbar/lemonbar-tcl/clock.sh => .config/lemonbar/lemonbar-tcl/clock.sh +0 -7
@@ 1,7 0,0 @@
set -eu

while true
do
	printf 'c%s\n' "$(date '+%a %b %d %T')"
	sleep "$1"
done

D .config/lemonbar/lemonbar-tcl/config => .config/lemonbar/lemonbar-tcl/config +0 -33
@@ 1,33 0,0 @@
fifo=/tmp/bar.fifo
bar_default_color='#aaaaaa'
bar_separator='%{F#555555}|%{F-}'

red='%{F#aa0000}'
yellow='%{F#aaaa00}'

battery_delay=3
battery_path=/sys/class/power_supply/BAT0/uevent

music_maxlen=100
cmus_fmt='%A - %{?y?(%y) ?}%l - %{?n?%02n.?} %t%{?va? (%a)?}'

cpu_usage_delay=2
cpu_usage_high=.9

hwmon_temp_prefix=/sys/devices/pci0000:00/0000:00:18.3/hwmon/hwmon1/temp1
hwmon_temp_delay=4

diskfree_delay=30
diskfree_low=.15
diskfree_mountpoint=~/Data

memfree_delay=3
memfree_low=.25

netrate_bar_width=8
netrate_delay=2
netrate_high=.9
netrate_netif=enp7s0
# These are in Kib/s
netrate_rxmax=750
netrate_txmax=100

D .config/lemonbar/lemonbar-tcl/config.tcl => .config/lemonbar/lemonbar-tcl/config.tcl +0 -4
@@ 1,4 0,0 @@
set colour(red)    {%{F#aa0000}}
set colour(yellow) {%{F#aaaa00}}

set memfree_low 0.25

D .config/lemonbar/lemonbar-tcl/cpu_usage.awk => .config/lemonbar/lemonbar-tcl/cpu_usage.awk +0 -19
@@ 1,19 0,0 @@
function stat_read()
{
	getline <"/proc/stat"
	close("/proc/stat")
}

BEGIN\
{
	stat_read()
	while(1)
	{
		sleep(delay)
		split($0, old)
		stat_read()
		usersys = $2 - old[2] + ($4 - old[4])
		usage = usersys / (usersys + $5 - old[5])
		printf "p%s%02u%%\n", (usage > high) ? red : "", usage * 100
	}
}

D .config/lemonbar/lemonbar-tcl/diskfree.awk => .config/lemonbar/lemonbar-tcl/diskfree.awk +0 -14
@@ 1,14 0,0 @@
BEGIN\
{
	auto_unit_init()
	cmd = "df -k -- " mountpoint
	while(1)
	{
		cmd | getline
		cmd | getline
		close(cmd)
		print "d" (($4 / $2 < low) ? red : "") \
			auto_unit_ratio($4 * 2^10, $2 * 2^10, "%.1f / %.1f %s")
		sleep(delay)
	}
}

D .config/lemonbar/lemonbar-tcl/hwmon_temp.awk => .config/lemonbar/lemonbar-tcl/hwmon_temp.awk +0 -10
@@ 1,10 0,0 @@
BEGIN\
{
	tmax = gets(prefix "_max") / 1000
	while(1)
	{
		tcur = gets(prefix "_input") / 1000
		printf "t%s%d°C\n", (tcur > tmax ? red : ""), tcur
		sleep(delay)
	}
}

D .config/lemonbar/lemonbar-tcl/memfree.awk => .config/lemonbar/lemonbar-tcl/memfree.awk +0 -16
@@ 1,16 0,0 @@
BEGIN\
{
	auto_unit_init()
	while(1)
	{
		getline <"/proc/meminfo"
		total = $2 * 2 ^ 10
		getline <"/proc/meminfo"
		getline <"/proc/meminfo"
		avail = $2 * 2 ^ 10
		close("/proc/meminfo")
		print "m" ((avail / total < low) ? red : "") \
			auto_unit_ratio(avail, total, "%.1f / %.1f %s")
		sleep(delay)
	}
}

D .config/lemonbar/lemonbar-tcl/modules.tcl => .config/lemonbar/lemonbar-tcl/modules.tcl +0 -139
@@ 1,139 0,0 @@
set where [file dirname [info script]]
source [file join $where util.tcl]

set colour(red)    {%{F#aa0000}}
set colour(yellow) {%{F#aaaa00}}
set bar_val        [dict create]
set bar_fmt        {}
set bar_separator  {%{F#555555}|%{F-}}


proc bar_init fmt {
	global bar_fmt
	set bar_fmt $fmt
}

proc _bspwm_handler chan {
	global bar_val
	dict set bar_val bspwm [gets $chan]
}

proc bspwm {} {
	set chan [open {| bspc subscribe report}]
}

proc date {{format "%a %b %d %T"} {delay 1}} {
	global bar
	dict set date [clock format [clock seconds] -format $format]
	after [expr {$delay * 1000}] [info level 0]
}

proc battery {{sysfs_path /sys/class/power_supply/BAT0/uevent} {low_pct 25}
			  {delay 3}} {
	global colour bar_val
    lassign [awkparse $sysfs_path = CAPACITY 1 STATUS 1] capa_pct status
	dict set bar_val [format {%s%02d%% (%s)} \
		[ter {$capa_pct < $low_pct} $colour(red)] $capa_pct $status]
	after [expr {$delay * 1000}] [info level 0]
}

proc _hwmon_temp {sysfs_prefix tmax delay} {
	global colour bar_val
	set tcur [expr {[readfile ${sysfs_prefix}_input] / 1000}]
    dict set bar_val hwmon_temp \
		[format {%s%02d°C} [ter {$tcur > $tmax} $colour(red)] $tcur]
	after [expr {$delay * 1000}] [info level 0]
}

proc hwmon_temp {sysfs_prefix {delay 4}} {
	set tmax [expr {[readfile ${sysfs_prefix}_max] / 1000}]
    _hwmon_temp $sysfs_prefix $tmax $delay
}

proc memfree {{low_ratio 0.25} {delay 3}} {
	global colour bar_val
	lassign [awkparse /proc/meminfo { } MemTotal: 1 MemAvailable: 1] \
		total avail
    dict set bar_val memfree \
		"[ter {($avail / $total) > $low_ratio} $colour(red)]$avail / $total"
	after [expr {$delay * 1000}] [info level 0]
}

proc diskfree {{path /} {low_pct 15} {delay 30}} {
	global colour bar_val
	lassign [awksplit [lexec df -P -- [file nativename $path] | sed 1d]] \
		_ total _ avail used_pct
	set avail_pct [expr {100 - [string range $used_pct 0 end-1]}]
	dict set bar_val diskfree \
		"[ter {$avail_pct < $low_pct} $colour(red)]$avail / $total"
}

proc read_stat {} {
	set time [lrange [awksplit [readfile /proc/stat]] 1 end]
	set total [lsum $time]
	set work [expr {$total - [lindex $time 3] - [lindex $time 4]}]
	return [list $work $total]
}

proc _cpu_usage {high_pct delay prev} {
	global colour bar_val
	lassign [set cur [read_stat]] work total
	lassign $prev pwork ptotal
	set usage_pct [expr {($work - $pwork) * 100 / ($total - $ptotal)}]
	dict set bar_val cpu_usage [format {%s%02d%%} \
		[ter {$usage_pct > $high_pct} $colour(red)] $usage_pct]
	after [expr {$delay * 1000}] [lreplace [info level 0] end end $cur]
}

proc cpu_usage {{high_pct 90} {delay 2}} {
    set first [read_stat]
	after [expr {$delay * 1000}]
    _cpu_usage $high_pct $delay $first
}

proc _getbarchar {rate max} {
	lindex {▁ ▂ ▃ ▄ ▅ ▆ ▇ █} [expr {min(7, int($rate * 8 / $max))}]
}

proc _netrate {rxpath txpath rxmax txmax bar_width delay high_ratio state} {
	global colour bar_val
	lassign $state rxprev txprev rxbar txbar
	set rx [readfile $rxpath]
	set tx [readfile $txpath]
	set rxrate [expr {($rx - $rxprev) / $delay}]
	set txrate [expr {($tx - $txprev) / $delay}]
	set rxbar [string range $rxbar 1 end][_getbarchar $rxrate $rxmax]
	set txbar [string range $txbar 1 end][_getbarchar $txrate $txmax]
    dict set bar_val [format {rx: %s%8s/s %s%%{F-}, tx: %s%8s/s %s}  \
		[ter {$rxrate > $rxmax * $high_ratio} $colour(red)] $rxrate $rxbar \
		[ter {$txrate > $txmax * $high_ratio} $colour(red)] $txrate $txbar]
	after [expr {$delay * 1000}] \
		[lreplace [info level 0] end end [list $rx $tx $rxbar $txbar]]
}

proc netrate {netif rxmax txmax {bar_width 8} {delay 2} {high_ratio 0.9}} {
	set sysfspath "/sys/class/net/$netif"
	if {![file exist $sysfspath]} {
		return -code error "$sysfspath: directory not found"
	}
	set rxpath "$sysfspath/statistics/rx_bytes"
	set txpath "$sysfspath/statistics/tx_bytes"
	set rx [readfile $rxpath]
	set tx [readfile $txpath]
	set empty_bar [string repeat " " $bar_width]
	after [expr {$delay * 1000}]
	_netrate $rxpath $txpath \
		[expr {$rxmax * 2 ** 10}] [expr {$txmax * 2 ** 10}] \
		$bar_width $delay $high_ratio [list $rx $tx $empty_bar $empty_bar]
}

proc _mus_handler chan {
	global bar_val
	dict set bar_val mus [gets $chan]
}

proc mus {fifopath} {
	lexec mkfifo -- $fifopath
	set fifo [open $fifopath {RDWR NONBLOCK}]
	fileevent $fifo readable [list _mus_handler $fifo]
}

D .config/lemonbar/lemonbar-tcl/mus_status.sh => .config/lemonbar/lemonbar-tcl/mus_status.sh +0 -96
@@ 1,96 0,0 @@
#!/bin/sh
# Dependencies: mus, mbcut
# Portability:	POSIX
set -eu

. "$(dirname -- "$0")"/config


format_status()
{
	awk '
		function value(line)
		{
			sub("tag [^ ]+ ", "", line)
			return line
		}

		/^tag / {tag[$2] = value($0)}

		END\
		{
			# Remove /TOTAL from NUMBER tags
			sub("/.*$", "", tag["TRACKNUMBER"])
			# DISCNUMBER / DISCTOTAL
			if("DISCNUMBER" in tag)
			{
				sub("/.*$", "", tag["DISCNUMBER"])
				if("DISCTOTAL" in tag)
				{
					disc = sprintf(" (Disc %0" length(tag["DISCTOTAL"]) "d/%d)", \
						tag["DISCNUMBER"], tag["DISCTOTAL"])
				}
				else
					disc = " (Disc " tag["DISCNUMBER"] ")"
			}
			# TRACKNUMBER / TRACKTOTAL
			if("TRACKTOTAL" in tag)
			{
				track = sprintf("%0" length(tag["TRACKTOTAL"]) "d/%d", \
					tag["TRACKNUMBER"], tag["TRACKTOTAL"])
			}
			else
				track = tag["TRACKNUMBER"]
			# Various artists
			if("ARTIST" in tag && tag["ARTIST"] != tag["ALBUMARTIST"])
				various = " (" tag["ARTIST"] ")"

			printf "%s - %s%s%s - %s. %s%s\n",
				("ALBUMARTIST" in tag ? tag["ALBUMARTIST"] : tag["ARTIST"]),
				("DATE" in tag ? "(" tag["DATE"] ") " : ""),
				tag["ALBUM"],
				disc,
				track,
				tag["TITLE"],
				various
		}'
}

read -r status
status=${status#status }
case "$status" in
	paused)
		color=$yellow
		mid_button="play"
		;;
	playing)
		color=
		mid_button="pause"
		;;
	no_playlist)
		msg="No playlist found"
		;;
	empty_playlist)
		msg="Playlist is empty"
	    ;;
esac

case "$status" in
	paused|playing)
		buttons="%{A:mus_client.sh track_first:}%{R}first%{R}%{A}"
		buttons="$buttons %{A:mus_client.sh track_prev:}%{R}prev%{R}%{A}"
		buttons="$buttons %{A:mus_client.sh track_rewind:}%{R}rewind%{R}%{A}"
		buttons="$buttons %{A:mus_client.sh pause_play:}%{R}$mid_button%{R}%{A}"
		buttons="$buttons %{A:mus_client.sh track_next:}%{R}next%{R}%{A}"
		buttons="$buttons %{A:mus_client.sh album_next:}%{R}nextalbm%{R}%{A}"
		buttons="$buttons %{A:mus_client.sh pl_edit:}"
		msg=$(mbcut -e "$(format_status)" $music_maxlen | sed 's#%#%%#g')
		;;
	no_playlist|empty_playlist)
		color=$red
		buttons="%{A:mus_client.sh pl_edit:}"
		;;
esac
msg="$msg%{A}"

printf "M%s%s%s\n" "$color" "$buttons" "$msg" >"$fifo"

D .config/lemonbar/lemonbar-tcl/netrate.awk => .config/lemonbar/lemonbar-tcl/netrate.awk +0 -70
@@ 1,70 0,0 @@
function update_rate()
{
	rxprev = rx
	txprev = tx
	rx = gets(rxpath)
	tx = gets(txpath)
	rxrate = (rx - rxprev) / delay
	txrate = (tx - txprev) / delay
}

function init_bar()
{
	barsym[0] = "▁"
	barsym[1] = "▂"
	barsym[2] = "▃"
	barsym[3] = "▄"
	barsym[4] = "▅"
	barsym[5] = "▆"
	barsym[6] = "▇"
	barsym[7] = "█"
	rxbar = txbar = str_repeat(" ", barwidth)
	rxbarden = rxmax / 8
	txbarden = txmax / 8
}

function update_bar()
{
	if(tics == barwidth)
	{
		# The blocks are 3 bytes unicode chars
		rxbar = substr(rxbar, 4)
		txbar = substr(txbar, 4)
	}
	else # Remove initial spaces
	{
		rxbar = substr(rxbar, 2)
		txbar = substr(txbar, 2)
		++tics
	}
	rxbar = rxbar barsym[min(7, int(rxrate / rxbarden))]
	txbar = txbar barsym[min(7, int(txrate / txbarden))]
}

BEGIN\
{
	if(rxmax == "" || txmax == "")
		die("rxmax and txmax variables must be set!")

	sysfspath = "/sys/class/net/" netif
	if(system("test -e " sysfspath))
		die(sysfspath ": path doesn't exist")
	rxpath = sysfspath "/statistics/rx_bytes"
	txpath = sysfspath "/statistics/tx_bytes"
	# Values given in KiB
	rxmax *= 2^10
	txmax *= 2^10

	auto_unit_init()
	init_bar()
	update_rate()
	while(1)
	{
		sleep(delay);
		update_rate()
		update_bar()
		printf "nrx: %s%8s/s %s%%{F-}, tx: %s%8s/s %s\n", \
			(rxrate > rxmax * high ? red : ""), auto_unit(rxrate, "%.0f %s"), rxbar, \
			(txrate > txmax * high ? red : ""), auto_unit(txrate, "%.0f %s"), txbar
	}
}

D .config/lemonbar/lemonbar-tcl/util.awk => .config/lemonbar/lemonbar-tcl/util.awk +0 -70
@@ 1,70 0,0 @@
function die(msg)
{
	print msg >"/dev/stderr"
	exit(exit_status = 1)
}

function max(a, b)
{
	return a > b ? a : b
}

function min(a, b)
{
	return a < b ? a : b
}

function log2(val)
{
	return log(val) / log(2)
}

function sleep(val)
{
	system("sleep " val)
}

function gets(path)
{
	getline _s <path
	close(path)
	return _s
}

function auto_unit_init()
{
	unit_name[0]  = "B"
	unit_name[1]  = "KiB"
	unit_name[2]  = "MiB"
	unit_name[3] = "GiB"
	unit_name[4] = "TiB"

	unit_den[0]	 = 1
	unit_den[1]	 = 2^10
	unit_den[2]	 = 2^20
	unit_den[3] = 2^30
	unit_den[4] = 2^40
}

function str_repeat(str, n)
{
	_ret = ""
	for(i = 0; i < n; ++i)
		_ret = _ret str
	return _ret
}

function auto_unit(val, fmt)
{
	_ind = val ? int(log2(val) / 10) : 0
	return sprintf(fmt, val / unit_den[_ind], unit_name[_ind])
}

function auto_unit_ratio(val1, val2, fmt)
{
	_ind1 = val1 ? int(log2(val1) / 10) : 0
	_ind2 = val2 ? int(log2(val2) / 10) : 0
	_ind = min(_ind1, _ind2)
	return sprintf(fmt, val1 / unit_den[_ind], val2 / unit_den[_ind],
		unit_name[_ind])
}

D .config/lemonbar/lemonbar-tcl/util.tcl => .config/lemonbar/lemonbar-tcl/util.tcl +0 -62
@@ 1,62 0,0 @@
proc lexec args {
	set chan [open [concat | $args]]
	set ret [read -nonewline $chan]
	close $chan
	return $ret
}

proc lsum list {::tcl::mathop::+ {*}$list}
proc sum args {::tcl::mathop::+ {*}$args}

proc printf {fmt args} {
	puts [format $fmt {*}$args]
}

proc readfile path {
	set chan [open $path]
    gets $chan ret
	close $chan
	return $ret
}

proc ter {expr if_val {else_val {}}} {
    if {[uplevel expr \{$expr\}]} {
		return $if_val
	} else {
		return $else_val
	}
}

proc every {seconds body} {
	eval $body
	after [expr {$seconds * 1000}] [info level 0]
}

proc awksplit {string {fs {[:blank:]}}} {
    regexp -inline -all \[^$fs\]+ $string
}

proc awkparse {path fs args} {
	set switch_body {}
	set keys {}
	foreach {key field} $args {
		lappend switch_body ${key}${fs}* \
			"dict set match $key \[lindex \[awksplit \$line $fs\] $field\]"
		lappend keys $key
	}

	set chan [open $path]
    while {[gets $chan line] >= 0} {
	    if {[switch -glob -- $line $switch_body] ne ""} {
			if {[dict size $match] == [llength $keys]} {
				close $chan
				return [lmap key $keys {dict get $match $key}]
			}
		}
	}
	close $chan
	return -code error "Some patterns weren't matched"
}

# lassign [awkparse test = key4 1 key2 1 key9 2] key4 key2
# puts "$key4 $key2"

A .config/lemonbar/mem_usage.awk => .config/lemonbar/mem_usage.awk +26 -0
@@ 0,0 1,26 @@
function get_meminfo()
{
	while ((getline <"/proc/meminfo") == 1)
	{
		meminfo[substr($1, 1, length($1) - 1)] = $2
	}
	close("/proc/meminfo")
}

BEGIN\
{
	auto_unit_init()
	while (1)
	{
		get_meminfo()
		total   = meminfo["MemTotal"]
		free    = meminfo["MemFree"]
		buffers = meminfo["Buffers"]
		cache   = meminfo["Cached"] + meminfo["SReclaimable"]
		used    = total - free - buffers - cache
		printf "m%s%.1f / %.1f GiB\n",
			(used / total > high ? red : ""),
			used / 2^20, total / 2^20
		sleep(delay)
	}
}

D .config/lemonbar/memfree.awk => .config/lemonbar/memfree.awk +0 -16
@@ 1,16 0,0 @@
BEGIN\
{
	auto_unit_init()
	while(1)
	{
		getline <"/proc/meminfo"
		total = $2 * 2 ^ 10
		getline <"/proc/meminfo"
		getline <"/proc/meminfo"
		avail = $2 * 2 ^ 10
		close("/proc/meminfo")
		print "m" ((avail / total < low) ? red : "") \
			auto_unit_ratio(avail, total, "%.1f / %.1f %s")
		sleep(delay)
	}
}

M .config/lemonbar/netrate.awk => .config/lemonbar/netrate.awk +1 -1
@@ 63,7 63,7 @@ BEGIN\
		sleep(delay);
		update_rate()
		update_bar()
		printf "nrx: %s%8s/s %s%%{F-}, tx: %s%8s/s %s\n", \
		printf "n %s↓ %8s/s %s%%{F-} %s↑ %8s/s %s\n", \
			(rxrate > rxmax * high ? red : ""), auto_unit(rxrate, "%.0f %s"), rxbar, \
			(txrate > txmax * high ? red : ""), auto_unit(txrate, "%.0f %s"), txbar
	}