From 4cd23d95840ffbe2cfa7803ba9e7ab12dad59f29 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 21 May 2026 11:58:43 +0200 Subject: [PATCH] Extract stats and clipboard helpers --- bin/omarchy | 1 + bin/omarchy-clipboard-paste-file | 20 ++++++ bin/omarchy-clipboard-paste-text | 25 ++++++++ bin/omarchy-system-stats | 35 +++++++++++ shell/plugins/bar/widgets/SystemStats.qml | 77 ++++++++--------------- shell/plugins/clipboard/Clipboard.qml | 4 +- shell/plugins/emojis/Emojis.qml | 3 +- 7 files changed, 109 insertions(+), 56 deletions(-) create mode 100755 bin/omarchy-clipboard-paste-file create mode 100755 bin/omarchy-clipboard-paste-text diff --git a/bin/omarchy b/bin/omarchy index 1f253ed3..13eeab1e 100755 --- a/bin/omarchy +++ b/bin/omarchy @@ -35,6 +35,7 @@ GROUP_DESCRIPTIONS[branding]="About and screensaver branding" GROUP_DESCRIPTIONS[brightness]="Display and keyboard brightness" GROUP_DESCRIPTIONS[capture]="Screenshots and screen recording" GROUP_DESCRIPTIONS[channel]="Omarchy release channel management" +GROUP_DESCRIPTIONS[clipboard]="Clipboard helpers" GROUP_DESCRIPTIONS[cmd]="Command and shortcut helpers" GROUP_DESCRIPTIONS[config]="System configuration helpers" GROUP_DESCRIPTIONS[debug]="Diagnostics and support logs" diff --git a/bin/omarchy-clipboard-paste-file b/bin/omarchy-clipboard-paste-file new file mode 100755 index 00000000..7064e601 --- /dev/null +++ b/bin/omarchy-clipboard-paste-file @@ -0,0 +1,20 @@ +#!/bin/bash + +# omarchy:summary=Copy a file to the clipboard and paste it +# omarchy:group=clipboard +# omarchy:args= +# omarchy:examples=omarchy clipboard paste file image/png /tmp/screenshot.png + +mime=${1:-} +path=${2:-} + +if [[ -z $mime || -z $path ]]; then + echo "Usage: omarchy-clipboard-paste-file " >&2 + exit 1 +fi + +[[ -r $path ]] || exit 1 + +wl-copy --type "$mime" < "$path" +sleep 0.15 +wtype -M shift -k Insert -m shift 2>/dev/null || true diff --git a/bin/omarchy-clipboard-paste-text b/bin/omarchy-clipboard-paste-text new file mode 100755 index 00000000..3f3eee65 --- /dev/null +++ b/bin/omarchy-clipboard-paste-text @@ -0,0 +1,25 @@ +#!/bin/bash + +# omarchy:summary=Copy text to the clipboard and type or paste it +# omarchy:group=clipboard +# omarchy:args=[--shift-insert] +# omarchy:examples=omarchy clipboard paste text "hello" | omarchy clipboard paste text --shift-insert "hello" + +use_shift_insert=false + +if [[ ${1:-} == "--shift-insert" ]]; then + use_shift_insert=true + shift +fi + +text=${1:-} +[[ -n $text ]] || exit + +printf '%s' "$text" | wl-copy +sleep 0.15 + +if [[ $use_shift_insert == "true" ]]; then + wtype -M shift -k Insert -m shift 2>/dev/null || true +else + wtype "$text" 2>/dev/null || true +fi diff --git a/bin/omarchy-system-stats b/bin/omarchy-system-stats index 59239c60..12ee3015 100755 --- a/bin/omarchy-system-stats +++ b/bin/omarchy-system-stats @@ -2,6 +2,41 @@ # omarchy:summary=Print CPU and memory stats for the shell # omarchy:group=system +# omarchy:args=[--bar-widget] + +bar_widget_stats() { + awk ' + NR == 1 { + idle = $5 + total = 0 + for (i = 2; i <= NF; i++) total += $i + printf "cpu\t%s\t%s\n", idle, total + } + ' /proc/stat + + awk ' + /^MemTotal:/ { total = $2 } + /^MemAvailable:/ { avail = $2 } + END { + if (total > 0) printf "memory\t%.2f\n", ((total - avail) / total) * 100 + } + ' /proc/meminfo + + awk '{ print "load\t" $1 }' /proc/loadavg +} + +case "${1:-}" in + "") + ;; + --bar-widget) + bar_widget_stats + exit + ;; + *) + echo "Usage: omarchy-system-stats [--bar-widget]" >&2 + exit 1 + ;; +esac cpu=$(top -bn1 | awk '/^%?Cpu/ { gsub(/,/, "") diff --git a/shell/plugins/bar/widgets/SystemStats.qml b/shell/plugins/bar/widgets/SystemStats.qml index 971539d0..a41c214c 100644 --- a/shell/plugins/bar/widgets/SystemStats.qml +++ b/shell/plugins/bar/widgets/SystemStats.qml @@ -24,9 +24,7 @@ BarWidget { readonly property int historyLimit: 30 function refresh() { - if (!cpuProc.running) cpuProc.running = true - if (!memProc.running) memProc.running = true - if (!loadProc.running) loadProc.running = true + if (!statsProc.running) statsProc.running = true } function pushHistory(arr, value) { @@ -36,20 +34,9 @@ BarWidget { return next } - function updateCpu(raw) { - var fields = String(raw || "").trim().split(/\s+/) - if (fields.length < 8) return - var user = parseInt(fields[1], 10) || 0 - var nice = parseInt(fields[2], 10) || 0 - var sys = parseInt(fields[3], 10) || 0 - var idle = parseInt(fields[4], 10) || 0 - var iowait = parseInt(fields[5], 10) || 0 - var irq = parseInt(fields[6], 10) || 0 - var softirq = parseInt(fields[7], 10) || 0 - - var total = user + nice + sys + idle + iowait + irq + softirq - var totalDiff = total - prevCpu.total + function updateCpuTotals(idle, total) { var idleDiff = idle - prevCpu.idle + var totalDiff = total - prevCpu.total if (prevCpu.total > 0 && totalDiff > 0) { var usage = (1 - idleDiff / totalDiff) * 100 @@ -60,52 +47,38 @@ BarWidget { prevCpu = { idle: idle, total: total } } - function updateMem(raw) { - var lines = String(raw || "").split("\n") - var total = 0 - var available = 0 - for (var i = 0; i < lines.length; i++) { - var line = lines[i] - if (line.indexOf("MemTotal:") === 0) total = parseInt(line.replace(/[^0-9]/g, ""), 10) || 0 - else if (line.indexOf("MemAvailable:") === 0) available = parseInt(line.replace(/[^0-9]/g, ""), 10) || 0 - } - if (total > 0) { - memPercent = ((total - available) / total) * 100 - memHistory = pushHistory(memHistory, memPercent) - } - } - function updateLoad(raw) { var n = parseFloat(String(raw || "").trim().split(/\s+/)[0]) if (!isNaN(n)) loadAvg = n } + function updateStats(raw) { + var lines = String(raw || "").split("\n") + for (var i = 0; i < lines.length; i++) { + var parts = lines[i].trim().split("\t") + if (parts.length < 2) continue + if (parts[0] === "cpu") updateCpuTotals(parseInt(parts[1], 10) || 0, parseInt(parts[2], 10) || 0) + else if (parts[0] === "memory") updateMemPercent(parts[1]) + else if (parts[0] === "load") updateLoad(parts[1]) + } + } + + function updateMemPercent(raw) { + var n = parseFloat(String(raw || "").trim()) + if (!isNaN(n)) { + memPercent = Math.max(0, Math.min(100, n)) + memHistory = pushHistory(memHistory, memPercent) + } + } + Component.onCompleted: refresh() Process { - id: cpuProc - command: ["bash", "-lc", "head -n1 /proc/stat"] + id: statsProc + command: [root.bar ? root.bar.omarchyPath + "/bin/omarchy-system-stats" : "omarchy-system-stats", "--bar-widget"] stdout: StdioCollector { waitForEnd: true - onStreamFinished: root.updateCpu(text) - } - } - - Process { - id: memProc - command: ["bash", "-lc", "head -n3 /proc/meminfo"] - stdout: StdioCollector { - waitForEnd: true - onStreamFinished: root.updateMem(text) - } - } - - Process { - id: loadProc - command: ["bash", "-lc", "cat /proc/loadavg"] - stdout: StdioCollector { - waitForEnd: true - onStreamFinished: root.updateLoad(text) + onStreamFinished: root.updateStats(text) } } diff --git a/shell/plugins/clipboard/Clipboard.qml b/shell/plugins/clipboard/Clipboard.qml index 0ad52d66..7918f167 100644 --- a/shell/plugins/clipboard/Clipboard.qml +++ b/shell/plugins/clipboard/Clipboard.qml @@ -189,9 +189,9 @@ Item { if (!row) return root.opened = false if (row.entryType === "image") { - Quickshell.execDetached(["bash", "-lc", "wl-copy --type " + Util.shellQuote(row.mime) + " < " + Util.shellQuote(row.path) + "; sleep 0.15; wtype -M shift -k Insert -m shift 2>/dev/null || true"]) + Quickshell.execDetached([root.omarchyPath + "/bin/omarchy-clipboard-paste-file", row.mime, row.path]) } else if (row.fullText) { - Quickshell.execDetached(["bash", "-lc", "printf %s " + Util.shellQuote(row.fullText) + " | wl-copy; sleep 0.15; wtype -M shift -k Insert -m shift 2>/dev/null || true"]) + Quickshell.execDetached([root.omarchyPath + "/bin/omarchy-clipboard-paste-text", "--shift-insert", row.fullText]) } } diff --git a/shell/plugins/emojis/Emojis.qml b/shell/plugins/emojis/Emojis.qml index 24269fba..5cced23e 100644 --- a/shell/plugins/emojis/Emojis.qml +++ b/shell/plugins/emojis/Emojis.qml @@ -159,8 +159,7 @@ Item { function applySelected(emoji) { if (!emoji) return root.dismiss() - var escEmoji = emoji.replace(/'/g, "'\\''") - Quickshell.execDetached(["bash", "-lc", "wl-copy '" + escEmoji + "'; sleep 0.15; wtype '" + escEmoji + "' 2>/dev/null || true"]) + Quickshell.execDetached([root.omarchyPath + "/bin/omarchy-clipboard-paste-text", emoji]) } ListModel { id: displayModel }