From 14c427feaf6e5dfaeb9779b99b523b453dcbf779 Mon Sep 17 00:00:00 2001 From: AntaresGG Date: Sat, 8 Aug 2026 21:05:29 +0800 Subject: [PATCH] Add Windows (Git Bash / MSYS2 / Cygwin) system info support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On MSYS-based bash, `uname -s` returns MINGW64_NT-* (or MSYS_NT-* / CYGWIN_NT-*), so neither the Darwin nor the Linux branch matched. The greeting rendered empty CPU, Memory, IP and Gateway fields, and printed `bash: uptime: command not found` on every new shell. - _rkt_hw_info: reuse the Linux /proc parsing — MSYS ships Linux-format /proc/cpuinfo and /proc/meminfo — and read the product name from the registry. ProductName still reads "Windows 10" on Windows 11, so it is corrected via CurrentBuild >= 22000. - _rkt_net_info: parse the default-route row of `route print -4 0.0.0.0`. That row is all numbers, so it survives the localized column headers that make `ipconfig` parsing unreliable on non-English Windows. - show_date_info: fall back to /proc/uptime when uptime(1) is missing. Every lookup degrades to the previous empty-string behaviour if the underlying tool is unavailable. The Darwin and Linux branches are untouched, and nothing here goes near the PRNG or the rendering path, so cross-shell palette parity is unaffected. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01XABWp1UM9qhnQn8PvQnyN3 --- bash/starcommand.sh | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/bash/starcommand.sh b/bash/starcommand.sh index 6a4fc18..fc11099 100644 --- a/bash/starcommand.sh +++ b/bash/starcommand.sh @@ -611,6 +611,29 @@ _rkt_hw_info() { os_str="$pretty $arch" fi fi + elif [[ "$os_type" == MINGW* || "$os_type" == MSYS* || "$os_type" == CYGWIN* ]]; then + # Git Bash / MSYS2 / Cygwin expose Linux-style /proc files + local procs_n=$(grep -c "^processor" /proc/cpuinfo 2>/dev/null) + local cores_n=$(grep "cpu cores" /proc/cpuinfo 2>/dev/null | head -1 | cut -d ":" -f2 | tr -d " ") + local cpu_type=$(grep "model name" /proc/cpuinfo 2>/dev/null | head -1 | cut -d ":" -f2 | sed 's/^[[:space:]]*//') + cpu_str="$procs_n processors, $cores_n cores, $cpu_type" + local mem_kb=$(awk '/^MemTotal:/ {print $2}' /proc/meminfo 2>/dev/null | tr -d ' \n') + if [[ -n $mem_kb ]]; then + mem_str=$(awk -v k="$mem_kb" 'BEGIN{printf "%.0fGB", k/1024/1024}') + fi + # Windows product name lives in the registry; ProductName still says + # "Windows 10" on Windows 11, so correct it via the build number. + local reg_out + reg_out=$(reg query 'HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion' 2>/dev/null | tr -d '\r') + local win_name=$(echo "$reg_out" | awk -F'REG_SZ' '$1 ~ /^[[:space:]]*ProductName[[:space:]]/ {print $2; exit}' | sed 's/^[[:space:]]*//; s/[[:space:]]*$//') + local win_disp=$(echo "$reg_out" | awk -F'REG_SZ' '$1 ~ /^[[:space:]]*DisplayVersion[[:space:]]/ {print $2; exit}' | sed 's/^[[:space:]]*//; s/[[:space:]]*$//') + local win_build=$(echo "$reg_out" | awk -F'REG_SZ' '$1 ~ /^[[:space:]]*CurrentBuild[[:space:]]/ {print $2; exit}' | sed 's/^[[:space:]]*//; s/[[:space:]]*$//') + if [[ -n $win_name ]]; then + if [[ "$win_build" =~ ^[0-9]+$ ]] && (( win_build >= 22000 )); then + win_name="${win_name/Windows 10/Windows 11}" + fi + os_str="$win_name${win_disp:+ $win_disp} $(uname -m)" + fi fi printf '_rkt_os="%s"\n' "$os_str" > "$cache" printf '_rkt_cpu="%s"\n' "$cpu_str" >> "$cache" @@ -641,6 +664,17 @@ _rkt_net_info() { elif [[ "$os_type" == "Linux" ]]; then ip=$(ip -o addr show 2>/dev/null | awk '$3 == "inet" && $2 !~ /^(lo|docker|br-|veth|vmnet|vboxnet|utun|tun|tap|awdl|llw|anpi)/ && $4 !~ /^127\./ { split($4, a, "/"); print a[1]; exit }') gw=$(ip route 2>/dev/null | awk '/^default/ {print $3; exit}') + elif [[ "$os_type" == MINGW* || "$os_type" == MSYS* || "$os_type" == CYGWIN* ]]; then + # The default-route row is pure numbers, so it survives any UI language. + # Columns: destination netmask gateway interface metric + local route_line + route_line=$(route print -4 0.0.0.0 2>/dev/null | tr -d '\r' \ + | awk '$1 == "0.0.0.0" && $2 == "0.0.0.0" && $3 ~ /^[0-9]+\./ { + if (best == "" || $5 + 0 < best) { best = $5 + 0; g = $3; a = $4 } + } END { if (g != "") print g, a }') + gw=${route_line%% *} + ip=${route_line##* } + [[ "$gw" == "$ip" ]] && ip="" fi printf '_rkt_ip="%s"\n' "$ip" > "$cache" printf '_rkt_gw="%s"\n' "$gw" >> "$cache" @@ -1248,7 +1282,15 @@ show_date_info() { cols=$(_rkt_cols) prefix_len=19 available=$((cols - prefix_len - 2)) - up_time=$(uptime | awk -F '(up |,)' '{print $2}' | sed 's/^ *//g') + if command -v uptime >/dev/null 2>&1; then + up_time=$(uptime | awk -F '(up |,)' '{print $2}' | sed 's/^ *//g') + elif [[ -r /proc/uptime ]]; then + # Git Bash has no uptime(1), but MSYS provides /proc/uptime + up_time=$(awk '{ s = int($1); d = int(s / 86400); h = int((s % 86400) / 3600); m = int((s % 3600) / 60) + if (d > 0) printf "%d day%s, %d hour%s", d, (d == 1 ? "" : "s"), h, (h == 1 ? "" : "s") + else if (h > 0) printf "%d hour%s, %d min%s", h, (h == 1 ? "" : "s"), m, (m == 1 ? "" : "s") + else printf "%d min%s", m, (m == 1 ? "" : "s") }' /proc/uptime) + fi value="Today is $(date +%Y.%m.%d), we are up and running for $up_time." if [[ ${#value} -gt $available ]]; then echo -n "${value:0:$((available - 1))}…"