summaryrefslogtreecommitdiff
path: root/ar/.local/bin/statusbar/sb-system
blob: 48addca17f6aee3aa4ac172bb3c6c15a3043f4a5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/bin/sh

# Combined system status bar module
# Toggle each section on/off (1=on, 0=off)
SHOW_CPU=1
SHOW_CPUBARS=0
SHOW_MEMORY=1
SHOW_DISK=1

# Refresh interval per module (seconds)
# The script itself should be called at the shortest interval (e.g. 5s)
INTERVAL_CPU=5
INTERVAL_CPUBARS=15
INTERVAL_MEMORY=60
INTERVAL_DISK=10800

# Disk mountpoint (only used if SHOW_DISK=1)
DISK_LOCATION=${1:-/}

# Cache directory
CACHE_DIR=/tmp/sb-system
mkdir -p "$CACHE_DIR"

# Clear stale caches on first run (e.g. dwmblocks restart)
LOCK="$CACHE_DIR/.started"
if [ ! -f "$LOCK" ]; then
  rm -f "$CACHE_DIR"/cpu "$CACHE_DIR"/cpubars "$CACHE_DIR"/cpubars_prev "$CACHE_DIR"/memory "$CACHE_DIR"/disk*
  touch "$LOCK"
fi

# ── Helper: check if cache is stale ────────────────────────
# usage: is_stale <cache_file> <interval_seconds>
is_stale() {
  [ ! -f "$1" ] && return 0
  last=$(stat -c %Y "$1" 2>/dev/null || echo 0)
  now=$(date +%s)
  [ $((now - last)) -ge "$2" ]
}

# ── Click handlers ──────────────────────────────────────────
case $BLOCK_BUTTON in
1)
  [ "$SHOW_CPU" = 1 ] && notify-send "🖥 CPU hogs" "$(ps axch -o cmd,%cpu | awk '{cmd[$1]+=$2} END {for (i in cmd) print i, cmd[i]}' | sort -nrk2 | head)\\n(100% per core)"
  [ "$SHOW_MEMORY" = 1 ] && notify-send "🐏 Memory hogs" "$(ps axch -o cmd,%mem | awk '{cmd[$1]+=$2} END {for (i in cmd) print i, cmd[i]}' | sort -nrk2 | head)"
  [ "$SHOW_DISK" = 1 ] && notify-send "💽 Disk space" "$(df -h --output=target,used,size)"
  ;;
2) setsid -f "$TERMINAL" -e htop ;;
3) notify-send "🖥 System module" "CPU temp, CPU bars, Memory, Disk usage
Left click: show hogs & disk info
Middle click: open htop
Right click: this help" ;;
6) setsid -f "$TERMINAL" -e "$EDITOR" "$0" ;;
esac

# ── Module: CPU temperature ─────────────────────────────────
if [ "$SHOW_CPU" = 1 ]; then
  cf="$CACHE_DIR/cpu"
  if is_stale "$cf" "$INTERVAL_CPU"; then
    sensors | awk '/Tctl:/ {gsub(/[+°C]/,"",$2); printf "🧁%s°", $2}' >"$cf"
  fi
fi

# ── Module: CPU bars ────────────────────────────────────────
if [ "$SHOW_CPUBARS" = 1 ]; then
  cf="$CACHE_DIR/cpubars"
  if is_stale "$cf" "$INTERVAL_CPUBARS"; then
    prev_cache="$CACHE_DIR/cpubars_prev"
    stats=$(awk '/cpu[0-9]+/ {printf "%d %d %d\n", substr($1,4), ($2 + $3 + $4 + $5), $5 }' /proc/stat)
    [ ! -f "$prev_cache" ] && echo "$stats" >"$prev_cache"
    old=$(cat "$prev_cache")
    echo "$stats" | while read -r row; do
      id=${row%% *}
      rest=${row#* }
      total=${rest%% *}
      idle=${rest##* }
      case "$(echo "$old" | awk '{if ($1 == id)
				printf "%d\n", (1 - (idle - $3) / (total - $2))*100 /12.5}' \
        id="$id" total="$total" idle="$idle")" in
      "0") printf "▁" ;; "1") printf "▂" ;; "2") printf "▃" ;; "3") printf "▄" ;;
      "4") printf "▅" ;; "5") printf "▆" ;; "6") printf "▇" ;; "7" | "8") printf "█" ;;
      esac
    done >"$cf"
    echo "$stats" >"$prev_cache"
  fi
fi

# ── Module: Memory + NVMe temp ──────────────────────────────
if [ "$SHOW_MEMORY" = 1 ]; then
  cf="$CACHE_DIR/memory"
  if is_stale "$cf" "$INTERVAL_MEMORY"; then
    width=$(xrandr | grep "\*" | awk '{print $1}' | sed 's/x[0-9]*//g' | head -n1)
    nvme_temp=$(sensors 2>/dev/null |
      awk '/Composite:/ {gsub(/[+°C]/,"",$2); print $2; exit}')
    if [ -n "$width" ] && [ "$width" -eq "$width" ] 2>/dev/null; then
      if [ "$width" -lt 1920 ]; then
        free --mebi | sed -n '2{p;q}' |
          awk -v t="$nvme_temp" '{printf "🌡%s° 🐏%d%%", t, ($3/$2)*100+0.5}' >"$cf"
      else
        free --mebi | sed -n '2{p;q}' |
          awk -v t="$nvme_temp" '{printf "🌡%s° 🐏%dGB/%dGB", t, $3/1000+0.5, $2/1000+0.5}' >"$cf"
      fi
    fi
  fi
fi

# ── Module: Disk usage ──────────────────────────────────────
if [ "$SHOW_DISK" = 1 ] && [ -d "$DISK_LOCATION" ]; then
  disk_key=$(printf "%s" "$DISK_LOCATION" | tr '/' '_')
  cf="$CACHE_DIR/disk${disk_key}"
  if is_stale "$cf" "$INTERVAL_DISK"; then
    case "$DISK_LOCATION" in
    "/home"*) icon="💾" ;; "/mnt"*) icon="🫜" ;; *) icon="💻" ;;
    esac
    printf "%s%s" "$icon" "$(df -hP "$DISK_LOCATION" | awk '/[0-9]/ {print $5}')" >"$cf"
  fi
fi

# ── Clean up disabled module caches ───────────────────────────
[ "$SHOW_CPU" = 0 ] && rm -f "$CACHE_DIR/cpu"
[ "$SHOW_CPUBARS" = 0 ] && rm -f "$CACHE_DIR/cpubars" "$CACHE_DIR/cpubars_prev"
[ "$SHOW_MEMORY" = 0 ] && rm -f "$CACHE_DIR/memory"
disk_key=$(printf "%s" "$DISK_LOCATION" | tr '/' '_')
[ "$SHOW_DISK" = 0 ] && rm -f "$CACHE_DIR/disk${disk_key}"

# ── Assemble output ─────────────────────────────────────────
out=""
for mod in cpu cpubars memory "disk${disk_key}"; do
  f="$CACHE_DIR/$mod"
  [ -f "$f" ] && val=$(cat "$f") && [ -n "$val" ] && {
    [ -n "$out" ] && out="$out "
    out="$out$val"
  }
done
printf "%s\n" "$out"