dwm-bar (11084B)
1 #!/bin/sh 2 # TODO: Add OpenBSD support for Volume, Battery Modules 3 4 # ------------------ # 5 # ----- Config ----- # 6 # ------------------ # 7 # Cache directory 8 CACHE_DIR=${XDG_CACHE_HOME:-$HOME/.cache}/dwm-bar 9 [ -d "$CACHE_DIR" ] || mkdir -p "$CACHE_DIR" 10 11 # The location for weather module, the necessary information is parsed from: 12 # v2d.wttr.in/${WEATHER_LOC} 13 WEATHER_LOC="Babol" 14 15 # List of modules 16 full_mods="Weather PublicIP PrivateIP Keyboard Battery Brightness Volume CPUtemp Memory Uptime DTime" 17 opts_mods=" 18 Volume Memory DTime 19 Volume CPUtemp Uptime DTime 20 Keyboard Battery Brightness DTime 21 Weather Battery Brightness DTime 22 Weather Keyboard Battery Brightness DTime 23 Weather PublicIP PrivateIP Uptime DTime 24 " 25 26 # Store Kernel's Name (Linux/FreeBSD/OpenBSD) 27 KERNEL=$(uname -s) 28 29 case "$KERNEL" in 30 Linux*) 31 TEMPERATURE_FILES=" 32 /sys/class/thermal/thermal_zone0/temp 33 /sys/class/thermal/thermal_zone1/temp 34 /sys/class/thermal/thermal_zone2/temp 35 /sys/class/hwmon/hwmon0/temp1_input 36 /sys/class/hwmon/hwmon1/temp1_input 37 /sys/class/hwmon/hwmon2/temp1_input 38 /sys/class/hwmon/hwmon0/device/temp1_input 39 /sys/class/hwmon/hwmon1/device/temp1_input 40 /sys/class/hwmon/hwmon2/device/temp1_input 41 null 42 " 43 44 for file in $TEMPERATURE_FILES; do 45 TEMP_FILE=$file 46 [ -f "$TEMP_FILE" ] && break 47 done 48 49 [ "$TEMP_FILE" = "null" ] && unset TEMP_FILE 50 ;; 51 esac 52 53 54 # ------------------ # 55 # ---- Modules ----- # 56 # ------------------ # 57 Weather(){ 58 weather_file="$CACHE_DIR/.weather" 59 weather_file_last=$(stat -c%Y "$weather_file") 60 if [ "$(date +%s)" -ge $((weather_file_last+3600)) ]; then 61 for interface in $(find /sys/class/net -depth | \ 62 sed '/\/lo$/d;/\/net$/d'); do 63 if [ "$(cat "$interface" 2>/dev/null)" -eq 1 ]; then 64 rm "$weather_file" 65 break 66 fi 67 done 68 fi 69 weather=$(cat "$weather_file" 2>/dev/null) 70 71 if [ ! "$weather" ]; then 72 weather=$(curl -s "v2d.wttr.in/$WEATHER_LOC" | \ 73 sed "/Weather:/!d;s/Weather://;s/,//g; 74 s/+//g;s/°C.*//;s/.*m//;s/ //;s/ //;s/ //") 75 weather="${weather}°C" 76 echo "$weather" > "$weather_file" 77 fi 78 79 [ "$weather" ] && printf "%s" "$weather" 80 } 81 82 PublicIP(){ 83 publicip_file="$CACHE_DIR/.publicip" 84 publicip_last=$(stat -c%Y "$publicip_file") 85 if [ "$(date +%s)" -ge $((publicip_last+300)) ]; then 86 for interface in $(find /sys/class/net -depth | \ 87 sed '/\/lo$/d;/\/net$/d'); do 88 if [ "$(cat "$interface" 2>/dev/null)" -eq 1 ]; then 89 rm "$publicip_file" 90 break 91 fi 92 done 93 fi 94 PUBLIC_IP=$(cat "$publicip_file" 2>/dev/null) 95 96 if [ ! "$PUBLIC_IP" ]; then 97 RESOLVERS='resolver1.opendns.com resolver2.opendns.com resolver3.opendns.com resolver4.opendns.com' 98 for resolver in $RESOLVERS ; do 99 PUBLIC_IP=$(host myip.opendns.com "$resolver" | \ 100 grep "myip.opendns.com has" | awk '{print $4}') 101 [ -n "$PUBLIC_IP" ] && break 102 done 103 echo "$PUBLIC_IP" > "$publicip_file" 104 fi 105 106 [ "$PUBLIC_IP" ] && printf " %s" "$PUBLIC_IP" 107 } 108 109 PrivateIP(){ 110 case "$KERNEL" in 111 Darwin*|FreeBSD*|OpenBSD*) 112 PRIVATE_IP=$(ifconfig | grep "inet " | \ 113 grep -Fv 127.0.0.1 | awk '{print $2}') 114 ;; 115 Linux*) 116 PRIVATE_IP=$(ip a | sed '/inet.*scope global/!d' | \ 117 grep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' | sed -n '1p') 118 ;; 119 esac 120 121 [ "$PRIVATE_IP" ] && printf " %s" "$PRIVATE_IP" 122 } 123 124 Keyboard(){ 125 KBD_LAYOUTS=$(setxkbmap -query | awk '/layout/{print $2}' | \ 126 tr ',' '\n' | awk '{print NR-1":"$1}') 127 KBD=$(xset -q | grep LED | awk '{print substr($10,5,1)}') 128 KBD=$(echo "$KBD_LAYOUTS" | sed "/^$KBD:/!d;s/.*://") 129 [ "$KBD" ] && printf " %s" "$KBD" 130 } 131 132 Battery() { 133 CHARGING_ICON='' 134 WARNING_ICON='' 135 BATTERY_FULL_ICON='' 136 BATTERY_2_ICON='' 137 BATTERY_3_ICON='' 138 BATTERY_4_ICON='' 139 140 FULL_AT=98 141 WARNING_AT=15 142 143 BAT_ICON="" 144 ICON="" 145 146 case "$KERNEL" in 147 Linux*) 148 BAT=$(find /sys/class/power_supply/ -name "BAT*") 149 if [ -d "$BAT" ]; then 150 CAPACITY=$(cat "$BAT/capacity") 151 CHARGING=$(cat "$BAT/status") 152 fi 153 [ "$CHARGING" = "Charging" ] && ICON=$CHARGING_ICON 154 ;; 155 FreeBSD*) 156 CAPACITY=$(sysctl -n hw.acpi.battery.life) 157 CHARGING=$(sysctl -n hw.acpi.battery.state) 158 [ "$CHARGING" -eq 2 ] && ICON=$CHARGING_ICON 159 ;; 160 esac 161 162 [ -z "$ICON" ] && [ "$CAPACITY" -le "$WARNING_AT" ] && ICON=$WARNING_ICON 163 164 if [ "$CAPACITY" -ge "$FULL_AT" ]; then 165 BAT_ICON=$BATTERY_FULL_ICON 166 CAPACITY=100 167 elif [ "$CAPACITY" -le 25 ]; then 168 BAT_ICON=$BATTERY_4_ICON 169 elif [ "$CAPACITY" -le 60 ]; then 170 BAT_ICON=$BATTERY_3_ICON 171 elif [ "$CAPACITY" -le "$FULL_AT" ]; then 172 BAT_ICON=$BATTERY_2_ICON 173 fi 174 175 [ "$ICON" ] && printf "%s " "$ICON" 176 [ "$BAT_ICON" ] && printf "%s " "$BAT_ICON" 177 [ "$CAPACITY" ] && printf "%s%%" "$CAPACITY" 178 179 CHARG_BAT="$CACHE_DIR/.battery-charge" 180 if [ "$CHARGING" = "Charging" ] || [ "$CHARGING" -eq 2 ]; then 181 [ -e "$CHARG_BAT" ] && return; 182 touch "$CHARG_BAT" 183 notify "Charging - ${ICON} ${BAT_ICON} ${CAPACITY}%" 184 rm "$LOW_BAT" 185 else 186 [ -e "$CHARG_BAT" ] || return; 187 notify "Discharging - ${BAT_ICON} ${CAPACITY}%" 188 rm "$CHARG_BAT" 189 fi 190 191 LOW_BAT="$CACHE_DIR/.battery-low" 192 if [ "$CAPACITY" -le "$WARNING_AT" ] && \ 193 [ ! -e "$LOW_BAT" ] && [ ! -e "$CHARG_BAT" ]; then 194 touch "$LOW_BAT" 195 notify "${WARNING_ICON} Low Battery 196 ${BAT_ICON} ${CAPACITY}% Remains" 197 fi 198 } 199 200 Brightness() { 201 case "$KERNEL" in 202 *Linux*) 203 BRIGHTNESS_CARD=$(find /sys/class/backlight -depth | head -n 1) 204 BRIGHTNESS_MAX=$(cat "$BRIGHTNESS_CARD/max_brightness") 205 BRIGHTNESS=$(cat "$BRIGHTNESS_CARD/brightness") 206 BRIGHTNESS=$((BRIGHTNESS*100/BRIGHTNESS_MAX)) 207 BRIGHTNESS=${BRIGHTNESS%.*} 208 ;; 209 FreeBSD*) 210 BRIGHTNESS=$(backlight | cut -d ' ' -f 2) 211 ;; 212 OpenBSD*) 213 BRIGHTNESS=$(apm -l) 214 ;; 215 esac 216 if [ "$BRIGHTNESS" -le 25 ]; then 217 ICON="" 218 elif [ "$BRIGHTNESS" -le 60 ]; then 219 ICON="" 220 else 221 ICON="" 222 fi 223 [ "$BRIGHTNESS" ] && printf "%s %s%%" "$ICON" "$BRIGHTNESS" 224 } 225 226 Volume() { 227 case "$KERNEL" in 228 Linux*) 229 if pactl stat >/dev/null 2>&1; then 230 DEFAULT_SINK=$(pactl get-default-sink) 231 VOLUME=$(pactl get-sink-volume "$DEFAULT_SINK" | \ 232 awk '/%/{sub(/%/, "", $5);print $5}') 233 else 234 VOLUME=$(amixer sget Master on | \ 235 grep -o '[0-9]*%' | sed 's/%//') 236 fi 237 ;; 238 FreeBSD*) 239 VOLUME=$(mixer -s vol | cut -d ':' -f 2) 240 ;; 241 esac 242 if [ "$VOLUME" -le 25 ]; then 243 ICON="" 244 elif [ "$VOLUME" -le 60 ]; then 245 ICON="" 246 else 247 ICON="" 248 fi 249 [ "$VOLUME" ] && printf "%s %s%%" "$ICON" "$VOLUME" 250 } 251 252 CPUtemp() { 253 case "$KERNEL" in 254 Linux*) 255 [ -z "$TEMP_FILE" ] || \ 256 TEMP=$(sed 's/...$//' "$TEMP_FILE" 2>/dev/null) 257 ;; 258 FreeBSD*) 259 TEMP=$(sysctl -n dev.cpu.0.temperature | sed 's/\..*//') 260 ;; 261 OpenBSD*) 262 TEMP=$(sysctl hw.sensors | \ 263 awk -F '=| degC' '/lm0.temp|cpu0.temp/ {print $2; exit}' | \ 264 sed 's/00/0/') 265 ;; 266 esac 267 [ "$TEMP" ] && printf " %s°C" "$TEMP" 268 } 269 270 Memory() { 271 case "$KERNEL" in 272 Linux*) 273 free=$(awk '/^MemFree/{free=$2} 274 /^Buffers/{buff=$2} 275 /^Cached/{cached=$2} 276 /^SReclaimable/{rec=$2} 277 /^MemTotal/{total=$2} 278 END{print (free+buff+cached+rec)}' /proc/meminfo) 279 total=$(awk '/^MemTotal/ {print $2}' /proc/meminfo) 280 ;; 281 FreeBSD*) 282 total=$(sysctl -n hw.physmem) 283 pagesize=$(sysctl -n hw.pagesize) 284 inactive=$(($(sysctl -n vm.stats.vm.v_inactive_count) * pagesize)) 285 unused=$(($(sysctl -n vm.stats.vm.v_free_count) * pagesize)) 286 cache=$(($(sysctl -n vm.stats.vm.v_cache_count) * pagesize)) 287 free=$((inactive+unused+cache)) 288 ;; 289 OpenBSD*) 290 total=$(sysctl -n hw.physmem) 291 free=$(vmstat | awk 'END {printf $5}') 292 ;; 293 esac 294 USAGE=$(((total-free)*100/total)) 295 [ "$USAGE" ] && printf " %s%%" "${USAGE%.*}" 296 } 297 298 Uptime() { 299 case "$KERNEL" in 300 Linux*) 301 SECS=$(sed 's/\..*//g' /proc/uptime) 302 ;; 303 *BSD*) 304 SECS=$(($(date +%s)-$(sysctl -n kern.boottime | \ 305 cut -d ',' -f 1 | cut -d '=' -f 2))) 306 ;; 307 esac 308 if [ "$SECS" -ge 86400 ]; then 309 D=$((SECS / 60 / 60 / 24)) 310 H=$((SECS / 60/ 60 % 24)) 311 M=$((SECS / 60 % 60)) 312 UPTIME="${D}d ${H:-0}h ${M:-0}m" 313 elif [ "$SECS" -ge 3600 ]; then 314 H=$((SECS / 60/ 60 % 24)) 315 M=$((SECS / 60 % 60)) 316 UPTIME="${H}h ${M:-0}m" 317 elif [ "$SECS" -ge 60 ]; then 318 M=$((SECS / 60 % 60)) 319 UPTIME="${M}m" 320 else 321 UPTIME="${SECS}s" 322 fi 323 [ "$UPTIME" ] && printf " %s" "$UPTIME" 324 } 325 326 DTime() { 327 DAY=$(date +%d | sed -e 's/^0//g') 328 day_suffix() { 329 case "$DAY" in 330 1|01|21|31) echo "st";; 331 2|02|22) echo "nd";; 332 3|03|23) echo "rd";; 333 *) echo "th";; 334 esac 335 } 336 DATE=$(date "+$DAY$(day_suffix) %b %I:%M %p") 337 [ "$DATE" ] && printf " %s" "$DATE" 338 } 339 340 # ------------------ # 341 # --- Functions ---- # 342 # ------------------ # 343 usage() { 344 printf "%s [-m modules] [-M] [-h]\n" "$0" 345 exit 2 346 } 347 stopbar() { 348 for pid in $(ps ax | grep "/bin/sh.*dwm-bar" | awk '{print $1}'); do 349 [ "$pid" = "$$" ] && continue 350 kill -9 "$pid" 2>/dev/null 351 wait 352 done 353 } 354 startbar() { 355 c=1 356 while ! pgrep -x dwm 2>/dev/null; do 357 sleep 1; 358 c=$((c+1)) 359 [ "$c" = 10 ] && exit 2 360 done 361 mods_list=$(cat "$CACHE_DIR/Modules" 2>/dev/null) 362 mods_list=${mods_list:-$full_mods} 363 mods=${mods:-$mods_list} 364 c=1 365 for mod in $mods; do 366 mod_prefix="" 367 mod_suffix="" 368 mod_sep=" | " 369 #mod_prefix=" [ " 370 #mod_suffix=" ] " 371 #mod_sep="" 372 if [ "$c" = 1 ]; then 373 output="$mod_prefix%$mod%$mod_suffix" 374 else 375 output="$output$mod_sep$mod_prefix%$mod%$mod_suffix" 376 fi 377 c=$((c+1)) 378 done 379 # Add padding 380 output=" $output " 381 while true; do 382 out=$output 383 for mod in $mods; do 384 unset mod_output 385 #mod_output=$($mod) 386 mod_output=$(cat "$CACHE_DIR/mod-$mod") 387 if [ -z "$mod_output" ]; then 388 out=$(printf "%s" "$out" | \ 389 sed "s|$mod_sep$mod_prefix%$mod%$mod_suffix||") 390 continue 391 fi 392 out=$(echo "$out" | sed "s|%$mod%|$mod_output|") 393 done 394 dwm -s "$out" 395 sleep 1 396 done 397 } 398 399 updatebar() { 400 mods_list=$(cat "$CACHE_DIR/Modules") 401 mods_list=${mods_list:-$full_mods} 402 while true; do 403 for mod in ${mods:-$mods_list}; do 404 printf '%s' "$($mod)" > "$CACHE_DIR/mod-$mod" 405 done 406 done 407 } 408 409 main() { 410 while getopts "m:M" flag; do 411 case "$flag" in 412 M) 413 full_text="[All Modules]" 414 rest="[Restart Modules]" 415 cust="[Custom Modules]" 416 opts=$(echo "$opts_mods" | \ 417 sed 's/^[ \t]*//g;/^ *$/d' | column -t) 418 choice=$(printf "%s\n" \ 419 "$full_text" "$rest" "$cust" "$opts" | dmenu -i -l 20) 420 [ -z "$choice" ] && choice=$(cat "$CACHE_DIR/Modules") 421 case "$choice" in 422 "$cust") 423 HEIGHT=$(($(echo "$full_mods" | wc -w)+2)) 424 WIDTH=$(($(echo "$full_mods" | tr ' ' '\n' | wc -L)*2)) 425 [ "$WIDTH" -lt 30 ] && WIDTH="30" 426 "$TERMINAL" -c "st-float" -g "${WIDTH}x${HEIGHT}+400+150" \ 427 -e sh -c "echo \"$full_mods\" | tr ' ' '\n' | \ 428 smenu -m \"Select Modules:\" -l -P -n 100 -q | \ 429 tr '\n' ' ' > \"$CACHE_DIR/Modules.tmp\"" 430 mods=$(cat "$CACHE_DIR/Modules.tmp") 431 [ -z "$mods" ] && mods=$(cat "$CACHE_DIR/Modules") 432 rm "$CACHE_DIR/Modules.tmp" 433 ;; 434 "$rest") 435 mods=$(cat "$CACHE_DIR/Modules") 436 ;; 437 "$full_text") 438 mods=$full_mods 439 ;; 440 *) 441 mods=$choice 442 ;; 443 esac 444 echo "$mods" > "$CACHE_DIR/Modules" 445 ;; 446 m) 447 mods=$OPTARG 448 echo "$mods" > "$CACHE_DIR/Modules" 449 ;; 450 *) usage ;; 451 esac 452 done 453 454 stopbar 455 updatebar & 456 startbar & 457 } 458 459 main "$@"