diff options
| author | Pinapelz <yukais@pinapelz.com> | 2026-07-10 11:21:24 -0700 |
|---|---|---|
| committer | Pinapelz <yukais@pinapelz.com> | 2026-07-10 11:21:24 -0700 |
| commit | 24de2a31a52d17b6f7214197bdbfeab7428742dd (patch) | |
| tree | f7736c4712d5a394525a3da2f2b4294e81ba9540 /config/hypr/scripts/PersistWorkspaceLayout.sh | |
| parent | 861bf5be200bfcf2440fec4cda911d29ec18493f (diff) | |
| parent | bca86bbec4757cec1f6f5bdea2ed210542f10fae (diff) | |
Merge remote-tracking branch 'upstream'
Diffstat (limited to 'config/hypr/scripts/PersistWorkspaceLayout.sh')
| -rwxr-xr-x | config/hypr/scripts/PersistWorkspaceLayout.sh | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/config/hypr/scripts/PersistWorkspaceLayout.sh b/config/hypr/scripts/PersistWorkspaceLayout.sh new file mode 100755 index 00000000..b5745880 --- /dev/null +++ b/config/hypr/scripts/PersistWorkspaceLayout.sh @@ -0,0 +1,223 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# Persist active monitor/workspace layout back into ~/.config/hypr/workspaces.conf. + +set -u + +quiet_mode=0 +layout_override="" +workspace_override="" +monitor_override="" +workspaces_file="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/workspaces.conf" + +usage() { + cat <<'EOF' +Usage: PersistWorkspaceLayout.sh [--quiet] [--layout <layout>] [--workspace <selector>] [--monitor <monitor>] [--file <path>] + --quiet Suppress console notifications. + --layout <layout> Override layout (master|dwindle|scrolling|monocle). + --workspace <sel> Override workspace selector (e.g. 5, name:code, special:scratchpad). + --monitor <name> Override monitor name. + --file <path> Target workspace rules file (default: ~/.config/hypr/workspaces.conf). +EOF +} + +normalize_layout() { + case "$1" in + master | dwindle | scrolling | monocle) + printf '%s\n' "$1" + ;; + *) + printf '\n' + ;; + esac +} + +require_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "Missing dependency: $1" >&2 + exit 1 + } +} + +get_active_workspace_json() { + hyprctl -j activeworkspace 2>/dev/null || printf '{}' +} + +get_workspace_selector() { + local ws_json="$1" + local ws_id ws_name + + ws_id="$(jq -r '.id // empty' <<<"$ws_json" 2>/dev/null || true)" + ws_name="$(jq -r '.name // empty' <<<"$ws_json" 2>/dev/null || true)" + + if [[ "$ws_id" =~ ^[0-9]+$ ]] && ((ws_id > 0)); then + printf '%s\n' "$ws_id" + return 0 + fi + + if [[ -n "$ws_name" && "$ws_name" != "null" ]]; then + if [[ "$ws_name" == name:* || "$ws_name" == special:* ]]; then + printf '%s\n' "$ws_name" + else + printf 'name:%s\n' "$ws_name" + fi + return 0 + fi + + return 1 +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --quiet | --no-notify) + quiet_mode=1 + shift + ;; + --layout) + layout_override="${2:-}" + shift 2 + ;; + --workspace) + workspace_override="${2:-}" + shift 2 + ;; + --monitor) + monitor_override="${2:-}" + shift 2 + ;; + --file) + workspaces_file="${2:-}" + shift 2 + ;; + -h | --help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 1 + ;; + esac +done + +require_cmd hyprctl +require_cmd jq +require_cmd awk +require_cmd mktemp + +ws_json="$(get_active_workspace_json)" +workspace_selector="${workspace_override:-$(get_workspace_selector "$ws_json" || true)}" +monitor_name="${monitor_override:-$(jq -r '.monitor // empty' <<<"$ws_json" 2>/dev/null || true)}" + +if [[ -n "$layout_override" ]]; then + layout_name="$(normalize_layout "$layout_override")" +else + layout_name="$(jq -r '.tiledLayout // .tiled_layout // empty' <<<"$ws_json" 2>/dev/null || true)" + layout_name="$(normalize_layout "$layout_name")" + if [[ -z "$layout_name" ]]; then + layout_name="$(hyprctl -j getoption general:layout 2>/dev/null | jq -r '.str // empty' 2>/dev/null || true)" + layout_name="$(normalize_layout "$layout_name")" + fi +fi + +if [[ -z "$workspace_selector" || -z "$monitor_name" || -z "$layout_name" ]]; then + echo "Unable to resolve workspace, monitor, or layout for persistence" >&2 + exit 1 +fi + +mkdir -p "$(dirname "$workspaces_file")" +touch "$workspaces_file" + +tmp_file="$(mktemp "${workspaces_file}.XXXXXX")" +cleanup() { + rm -f "$tmp_file" +} +trap cleanup EXIT + +awk \ + -v target_ws="$workspace_selector" \ + -v target_mon="$monitor_name" \ + -v target_layout="$layout_name" ' +function trim(v) { + gsub(/^[[:space:]]+|[[:space:]]+$/, "", v) + return v +} +BEGIN { + updated = 0 +} +{ + line = $0 + content = line + comment = "" + hash_pos = index(line, "#") + if (hash_pos > 0) { + content = substr(line, 1, hash_pos - 1) + comment = substr(line, hash_pos) + } + stripped = trim(content) + indent_len = match(line, /[^[:space:]]/) - 1 + if (indent_len < 0) { + indent_len = length(line) + } + indent = substr(line, 1, indent_len) + + if (stripped ~ /^workspace[[:space:]]*=/) { + sub(/^workspace[[:space:]]*=[[:space:]]*/, "", stripped) + token_count = split(stripped, tokens, /,/) + ws = trim(tokens[1]) + mon = "" + extras_count = 0 + delete extras + + for (i = 2; i <= token_count; i++) { + token = trim(tokens[i]) + if (token == "") { + continue + } + if (token ~ /^monitor:/) { + mon = trim(substr(token, 9)) + continue + } + if (token ~ /^layout:/) { + continue + } + extras[++extras_count] = token + } + + if (ws == target_ws && mon == target_mon) { + if (!updated) { + rebuilt = indent "workspace = " ws ", monitor:" target_mon ", layout:" target_layout + for (i = 1; i <= extras_count; i++) { + rebuilt = rebuilt ", " extras[i] + } + if (comment != "") { + rebuilt = rebuilt " " comment + } + print rebuilt + updated = 1 + } + next + } + } + + print line +} +END { + if (!updated) { + print "workspace = " target_ws ", monitor:" target_mon ", layout:" target_layout + } +} +' "$workspaces_file" >"$tmp_file" + +mv "$tmp_file" "$workspaces_file" +trap - EXIT + +if [[ "$quiet_mode" -eq 0 ]]; then + printf 'Saved workspace layout: %s @ %s -> %s\n' "$workspace_selector" "$monitor_name" "$layout_name" +fi |
