#!/usr/bin/env bash set -euo pipefail # Colors cyan=$'\e[1;36m'; green=$'\e[1;32m'; red=$'\e[1;31m' magenta=$'\e[1;35m'; blue=$'\e[1;34m' reset=$'\e[0m' # Box drawing chars (UTF-8 fallback safe) tl="╭"; tr="╮"; bl="╰"; br="╯"; h="─"; v="│" if ! locale charmap 2>/dev/null | grep -qi 'utf'; then tl="+"; tr="+"; bl="+"; br="+"; h="-"; v="|" fi # Strip ANSI escapes strip_colors() { printf '%s' "$1" | sed -r 's/\x1B\[[0-9;]*[mK]//g'; } # --- Collect stats --- # CPU (cores/threads) if command -v lscpu >/dev/null; then sockets=$(lscpu | awk -F: '/Socket\(s\)/{gsub(/ /,"");print $2;exit}') cores_per=$(lscpu | awk -F: '/Core\(s\) per socket/{gsub(/ /,"");print $2;exit}') physical_cores=$((sockets * cores_per)) else physical_cores=$(grep -E 'cpu cores' /proc/cpuinfo | head -1 | awk '{print $4}') fi logical_threads=$(nproc --all) # CPU usage (quick sample) cpu_usage() { read -r _ u n s i _ < <(grep '^cpu ' /proc/stat) prev=$((u+n+s+i)); prev_idle=$i sleep 0.1 read -r _ u n s i _ < <(grep '^cpu ' /proc/stat) cur=$((u+n+s+i)); idle=$i dt=$((cur - prev)); di=$((idle - prev_idle)) ((dt>0)) && printf "%.1f%%" "$(bc -l <<< "100*($dt-$di)/$dt")" || echo "0.0%" } # Time since last system update since_update() { days_since_update=0 if [[ -f ~/.last_world_update ]]; then last_epoch=$(stat -c %Y ~/.last_world_update) days_since_update=$(( ( $(date +%s) - last_epoch ) / 86400 )) fi echo $days_since_update } cpu_use=$(cpu_usage) # Memory mem_usage=$(free -h | awk '/Mem:/ {print $3 "/" $2}') # System age sys_age=$(( ( $(date +%s) - $(stat -c %W / 2>/dev/null || echo 0) ) / 86400 )) # Packages pkg_count=$(find /var/db/pkg -mindepth 2 -maxdepth 2 -type d 2>/dev/null | wc -l) # Days since last update days_update=$(since_update) # --- Define lines (easy to add new ones) --- lines=( "${cyan}CPU${reset}: ${physical_cores}c/${logical_threads}t/${cpu_use}" "${green}Memory${reset}: ${mem_usage}" "${magenta}Age${reset}: ${sys_age} days" "${blue}Pkgs${reset}: ${pkg_count}" "${red}Update${reset}: ${days_update}" ) # --- Compute max width --- maxlen=0 for l in "${lines[@]}"; do stripped=$(strip_colors "$l") slen=${#stripped} ((slen > maxlen)) && maxlen=$slen done # --- Borders --- hline=$(printf "%${maxlen}s" "" | sed "s/ /$h/g") printf '%s%s%s\n' "$tl" "$hline" "$tr" # # --- Content --- # for l in "${lines[@]}"; do # stripped=$(strip_colors "$l") # pad=$((maxlen - ${#stripped})) # printf '%s%s%*s%s\n' "$v" "$l" "$pad" "" "$v" # done # --- Content with right-aligned values --- for l in "${lines[@]}"; do # split into label and value at first colon label="${l%%:*}:" # label including colon value="${l#*: }" # everything after colon + space # strip colors for length calculation stripped_label=$(strip_colors "$label") stripped_value=$(strip_colors "$value") # compute padding: value is right-aligned label_len=${#stripped_label} value_len=${#stripped_value} pad=$((maxlen - label_len - value_len)) # print line: label left, pad spaces, value right printf '%s%s%*s%s%s\n' "$v" "$label" "$pad" "" "$value" "$v" done # --- Bottom --- printf '%s%s%s\n' "$bl" "$hline" "$br"