#!/usr/bin/env bash # Every schema entry with a `hypr` block declares `readAs`: which JSON field # `hyprctl getoption` answers with for that option. Verification compares # against that field, so a wrong declaration does not fail loudly -- it makes # every write to that setting look rejected, and the user sees "Hyprland did not # apply ..." for a change that actually worked. # # cursor:inactive_timeout shipped as "int" and is answered as "float", which is # exactly that failure. This contract asks the compositor for the real shape of # every mapped option so the next one cannot reach a release. set -euo pipefail repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" schema="$repo_dir/config/dot/quickshell/config/PreferenceSchema.qml" fail() { printf 'schema hypr shape contract: %s\n' "$1" >&2 exit 1 } [[ -r "$schema" ]] || fail "cannot read $schema" mismatches=0 checked=0 while IFS='|' read -r option declared; do [[ -n "$option" ]] || continue checked=$((checked + 1)) answer="$(hyprctl -j getoption "$option" 2>/dev/null)" \ || fail "hyprctl could not read $option" # An option Hyprland does not know answers without any value field at all. actual="" for field in int bool float str css; do if jq -e --arg f "$field" 'has($f)' <<<"$answer" >/dev/null 2>&1; then actual="$field" break fi done [[ -n "$actual" ]] || fail "$option is not a known Hyprland option (answered: $answer)" if [[ "$actual" != "$declared" ]]; then printf 'schema hypr shape contract: %s declares readAs "%s" but answers with "%s"\n' \ "$option" "$declared" "$actual" >&2 mismatches=$((mismatches + 1)) fi done < <(grep -oE 'option: "[^"]+", readAs: "[a-z]+"' "$schema" \ | sed -E 's/option: "([^"]+)", readAs: "([a-z]+)"/\1|\2/') [[ "$checked" -gt 0 ]] || fail 'no hypr-mapped schema entries were found to check' [[ "$mismatches" -eq 0 ]] || fail "$mismatches option(s) declare the wrong answer shape" printf 'schema hypr shape contract: PASS (%d mapped options)\n' "$checked"