diff --git a/bin/omarchy b/bin/omarchy index c5640dfc..8f739bad 100755 --- a/bin/omarchy +++ b/bin/omarchy @@ -51,6 +51,7 @@ GROUP_DESCRIPTIONS[install]="Optional software installers" GROUP_DESCRIPTIONS[launch]="Application launchers" GROUP_DESCRIPTIONS[menu]="Omarchy menu commands" GROUP_DESCRIPTIONS[migrate]="Migration runner" +GROUP_DESCRIPTIONS[monitor]="Monitor status helpers" GROUP_DESCRIPTIONS[network]="Network status helpers" GROUP_DESCRIPTIONS[notification]="Notification helpers" GROUP_DESCRIPTIONS[npm]="NPM package wrappers" @@ -69,7 +70,7 @@ GROUP_DESCRIPTIONS[screensaver]="Screensaver branding and animation" GROUP_DESCRIPTIONS[snapshot]="System snapshots" GROUP_DESCRIPTIONS[style]="Global UI style controls" GROUP_DESCRIPTIONS[sudo]="Sudo configuration helpers" -GROUP_DESCRIPTIONS[system]="Reboot, shutdown, logout, and lock" +GROUP_DESCRIPTIONS[system]="System status, reboot, shutdown, logout, and lock" GROUP_DESCRIPTIONS[theme]="Theme management" GROUP_DESCRIPTIONS[toggle]="Toggle Omarchy features" GROUP_DESCRIPTIONS[transcode]="Image and video transcoding" diff --git a/bin/omarchy-audio-sink-availability b/bin/omarchy-audio-sink-availability new file mode 100755 index 00000000..0f333e26 --- /dev/null +++ b/bin/omarchy-audio-sink-availability @@ -0,0 +1,45 @@ +#!/bin/bash + +# omarchy:summary=Print PulseAudio sink availability for the shell +# omarchy:group=audio + +pactl list sinks 2>/dev/null | awk ' + function emit_sink() { + if (name == "") return + print name "\t" ((port_count == 0 || available) ? 1 : 0) + } + + /^Sink #/ { + emit_sink() + name = "" + in_ports = 0 + port_count = 0 + available = 0 + next + } + + /^[[:space:]]*Name:/ { + name = $2 + next + } + + /^[[:space:]]*Ports:$/ { + in_ports = 1 + next + } + + in_ports && /^\tActive Port:/ { + in_ports = 0 + next + } + + in_ports && /^\t\t/ { + port_count++ + if ($0 !~ /not available/) available = 1 + next + } + + END { + emit_sink() + } +' diff --git a/bin/omarchy-battery-status b/bin/omarchy-battery-status index 88c336b2..f43c75ed 100755 --- a/bin/omarchy-battery-status +++ b/bin/omarchy-battery-status @@ -1,27 +1,61 @@ #!/bin/bash # omarchy:summary=Returns a formatted battery status string with percentage and power draw/charge. +# omarchy:args=[--shell] -battery_info=$(upower -i $(upower -e | grep BAT)) +shell_output=false -percentage=$(echo "$battery_info" | awk '/percentage/ { - print int($2) - exit -}') +case "${1:-}" in + "") + ;; + --shell) + shell_output=true + ;; + *) + echo "Usage: omarchy-battery-status [--shell]" >&2 + exit 2 + ;; +esac -power_rate=$(echo "$battery_info" | awk '/energy-rate/ { - rounded = sprintf("%.1f", $2) - sub(/\.0$/, "", rounded) - print rounded - exit -}') +battery=$(upower -e 2>/dev/null | grep BAT | head -n 1) +[[ -z $battery ]] && exit 0 -state=$(echo "$battery_info" | awk '/state/ { print $2; exit }') -time_remaining=$(omarchy-battery-remaining-time) -capacity=$(omarchy-battery-capacity) +battery_info=$(upower -i "$battery") + +percentage=$(awk '/percentage/ { print int($2); exit }' <<<"$battery_info") +power_rate=$(awk '/energy-rate/ { + rounded = sprintf("%.1f", $2) + sub(/\.0$/, "", rounded) + print rounded + exit +}' <<<"$battery_info") +state=$(awk '/state/ { print $2; exit }' <<<"$battery_info") +time_remaining=$(omarchy-battery-remaining-time 2>/dev/null) +capacity=$(omarchy-battery-capacity 2>/dev/null) + +if [[ $shell_output == "true" ]]; then + printf 'percentage\t%s\n' "${percentage}%" + printf 'state\t%s\n' "$state" + printf 'rate\t%s\n' "${power_rate}W" + printf 'size\t%s\n' "${capacity}Wh" + printf 'time\t%s\n' "$time_remaining" + + end=$(cat /sys/class/power_supply/BAT*/charge_control_end_threshold 2>/dev/null | head -1) + start=$(cat /sys/class/power_supply/BAT*/charge_control_start_threshold 2>/dev/null | head -1) + + if [[ -n $end ]]; then + if [[ -n $start && $start != "$end" ]]; then + printf 'threshold\t%s-%s%%\n' "$start" "$end" + else + printf 'threshold\t%s%%\n' "$end" + fi + fi + + exit 0 +fi if [[ $state == "charging" ]]; then - echo "Battery ${percentage}% · ${time_remaining} to full ·  ${power_rate}W / ${capacity}Wh" + echo "Battery ${percentage}% · ${time_remaining} to full ·  ${power_rate}W / ${capacity}Wh" else - echo "Battery ${percentage}% · ${time_remaining} left ·  ${power_rate}W / ${capacity}Wh" + echo "Battery ${percentage}% · ${time_remaining} left ·  ${power_rate}W / ${capacity}Wh" fi diff --git a/bin/omarchy-monitor-state b/bin/omarchy-monitor-state new file mode 100755 index 00000000..26663aa2 --- /dev/null +++ b/bin/omarchy-monitor-state @@ -0,0 +1,21 @@ +#!/bin/bash + +# omarchy:summary=Print monitor panel state for the shell +# omarchy:group=monitor + +{ omarchy-brightness-display 2>/dev/null; echo; } | head -n 1 + +monitors_json=$(hyprctl monitors all -j) + +printf '%s\n' "$monitors_json" | jq -r ' + def internal: test("^(eDP|LVDS|DSI)-"); + ([.[] | select(.name | internal)][0].name // ""), + ([.[] | select((.name | internal) | not)][0].name // ""), + ([.[] | select((.name | internal) and .disabled != true)][0].name // ""), + ([.[] | select((.name | internal) and .mirrorOf != "none")][0].mirrorOf // "") +' + +omarchy-hyprland-monitor-focused 2>/dev/null || echo +omarchy-hyprland-monitor-scaling 2>/dev/null || echo + +printf '%s\n' "$monitors_json" | jq -c '[.[] | {name, enabled:(.disabled != true), focused:(.focused == true)}]' diff --git a/bin/omarchy-system-stats b/bin/omarchy-system-stats new file mode 100755 index 00000000..59239c60 --- /dev/null +++ b/bin/omarchy-system-stats @@ -0,0 +1,24 @@ +#!/bin/bash + +# omarchy:summary=Print CPU and memory stats for the shell +# omarchy:group=system + +cpu=$(top -bn1 | awk '/^%?Cpu/ { + gsub(/,/, "") + for (i = 1; i <= NF; i++) { + if ($(i + 1) == "id") { + printf "%.0f%%", 100 - $i + exit + } + } +}') + +awk -v cpu="$cpu" ' + /^MemTotal:/ { total = $2 } + /^MemAvailable:/ { avail = $2 } + END { + used = total - avail + printf "cpu\t%s\n", cpu + printf "memory\t%.1fGB / %.0fGB\n", used / 1024 / 1024, total / 1024 / 1024 + } +' /proc/meminfo diff --git a/shell/plugins/panels/Audio.qml b/shell/plugins/panels/Audio.qml index 12fa8e9a..234e19e3 100644 --- a/shell/plugins/panels/Audio.qml +++ b/shell/plugins/panels/Audio.qml @@ -509,31 +509,7 @@ Panel { Process { id: sinkAvailabilityProc - command: ["bash", "-lc", ` -pactl list sinks 2>/dev/null | python3 -c ' -import re -import sys - -for block in re.split(r"(?m)^Sink #", sys.stdin.read())[1:]: - name = re.search(r"(?m)^\\s*Name:\\s*(\\S+)", block) - if not name: - continue - - ports = [] - in_ports = False - for line in block.splitlines(): - if line.strip() == "Ports:": - in_ports = True - continue - if in_ports and line.startswith("\\tActive Port:"): - in_ports = False - if in_ports and line.startswith("\\t\\t"): - ports.append(line) - - available = not ports or any("not available" not in port for port in ports) - print("%s\\t%d" % (name.group(1), 1 if available else 0)) -' -`] + command: [root.bar ? root.bar.omarchyPath + "/bin/omarchy-audio-sink-availability" : "omarchy-audio-sink-availability"] stdout: StdioCollector { waitForEnd: true onStreamFinished: root.updateSinkAvailability(text) diff --git a/shell/plugins/panels/Monitor.qml b/shell/plugins/panels/Monitor.qml index 7241db45..4bf48d4f 100644 --- a/shell/plugins/panels/Monitor.qml +++ b/shell/plugins/panels/Monitor.qml @@ -286,7 +286,7 @@ Panel { Process { id: stateProc - command: ["bash", "-lc", "{ omarchy-brightness-display 2>/dev/null; echo; } | head -n 1; monitors_json=$(hyprctl monitors all -j); printf '%s\\n' \"$monitors_json\" | jq -r 'def internal: test(\"^(eDP|LVDS|DSI)-\"); ([.[] | select(.name | internal)][0].name // \"\"), ([.[] | select((.name | internal) | not)][0].name // \"\"), ([.[] | select((.name | internal) and .disabled != true)][0].name // \"\"), ([.[] | select((.name | internal) and .mirrorOf != \"none\")][0].mirrorOf // \"\")'; omarchy-hyprland-monitor-focused 2>/dev/null || echo; omarchy-hyprland-monitor-scaling 2>/dev/null || echo; printf '%s\\n' \"$monitors_json\" | jq -c '[.[] | {name, enabled:(.disabled != true), focused:(.focused == true)}]'"] + command: [root.bar ? root.bar.omarchyPath + "/bin/omarchy-monitor-state" : "omarchy-monitor-state"] stdout: StdioCollector { waitForEnd: true onStreamFinished: { diff --git a/shell/plugins/panels/Power.qml b/shell/plugins/panels/Power.qml index 8f1f8014..2e7b2e16 100644 --- a/shell/plugins/panels/Power.qml +++ b/shell/plugins/panels/Power.qml @@ -116,25 +116,7 @@ Panel { Process { id: batteryProc - command: ["bash", "-lc", ` -bat=$(upower -e 2>/dev/null | grep BAT | head -n1) -[[ -z $bat ]] && exit 0 -info=$(upower -i "$bat") -printf 'percentage\t%s\n' "$(awk '/percentage/ { print int($2) "%"; exit }' <<<"$info")" -printf 'state\t%s\n' "$(awk '/state/ { print $2; exit }' <<<"$info")" -printf 'rate\t%s\n' "$(awk '/energy-rate/ { v=sprintf("%.1f", $2); sub(/\.0$/, "", v); print v "W"; exit }' <<<"$info")" -printf 'size\t%s\n' "$(awk '/energy-full:/ { printf "%dWh", $2; exit }' <<<"$info")" -printf 'time\t%s\n' "$($OMARCHY_PATH/bin/omarchy-battery-remaining-time 2>/dev/null)" -end=$(cat /sys/class/power_supply/BAT*/charge_control_end_threshold 2>/dev/null | head -1) -start=$(cat /sys/class/power_supply/BAT*/charge_control_start_threshold 2>/dev/null | head -1) -if [[ -n $end ]]; then - if [[ -n $start && $start != "$end" ]]; then - printf 'threshold\t%s-%s%%\n' "$start" "$end" - else - printf 'threshold\t%s%%\n' "$end" - fi -fi -`] + command: [root.bar ? root.bar.omarchyPath + "/bin/omarchy-battery-status" : "omarchy-battery-status", "--shell"] stdout: StdioCollector { waitForEnd: true; onStreamFinished: root.updateKeyValue(text, "battery") } } @@ -146,7 +128,7 @@ fi Process { id: systemProc - command: ["bash", "-lc", "cpu=$(top -bn1 | awk '/^%?Cpu/ { gsub(/,/, \"\"); for (i=1; i<=NF; i++) if ($(i+1) == \"id\") { printf \"%.0f%%\", 100 - $i; exit } }'); awk -v cpu=\"$cpu\" '/^MemTotal:/ { total=$2 } /^MemAvailable:/ { avail=$2 } END { used=total-avail; printf \"cpu\\t%s\\n\", cpu; printf \"memory\\t%.1fGB / %.0fGB\\n\", used/1024/1024, total/1024/1024 }' /proc/meminfo"] + command: [root.bar ? root.bar.omarchyPath + "/bin/omarchy-system-stats" : "omarchy-system-stats"] stdout: StdioCollector { waitForEnd: true; onStreamFinished: root.updateKeyValue(text, "system") } }