From b32cbaa7800b1e192612ee8cc56b737bf4738813 Mon Sep 17 00:00:00 2001 From: Rick Peters Date: Sat, 3 Oct 2026 11:52:22 +0200 Subject: [PATCH] refactor: is_wanted / is_current predicates Co-Authored-By: Claude Sonnet 5.5 --- CHANGELOG.md | 1 + lib/backend.sh | 6 +++--- lib/menu.sh | 34 ++++++++++++++++++---------------- steamify.sh | 10 +++++----- 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dee485..e23a957 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ one per merged pull request. - **refactor: Valve's package mirror in one module (`lib/valve-mirror.sh`: newest repo, package database fields, checksummed download); the SteamOS extras, CEC driver, BIOS lookup and os-release version used four copies** - **refactor: the rules between menu items are three tables (`REQUIRES`, `FOLLOWS`, `EXCLUDES` in `lib/menu.sh`) used by the menu's toggles and, as `normalize_wanted`, by the app's selection (it had its own copy of the rules). The app now also ticks the Steamify shortcut for "Add as non-Steam game" and unticks the game entry with it, like the menu** - **refactor: the entry point picks its mode once (`MODE`) and `--defaults` and `--boot` are functions with one failure report, instead of four booleans and two copies of the apply-and-report code; `NO_COLOR` gives plain output** +- **refactor: `is_wanted` and `is_current` instead of repeated `[[ "${WANTED[x]}" == 1 ]]` checks in the menu, the app's backend and the entry point** - **test: the menu rules, the plan and the app's and installer's JSON are checked against a golden file (`tests/menu-test.sh` in steamify-cachyos-dev); `make check`, `.editorconfig`, `.shellcheckrc`** - **docs: README lists the sources and projects Steamify builds on, with licences and thanks** diff --git a/lib/backend.sh b/lib/backend.sh index 16a6cb9..b26348a 100644 --- a/lib/backend.sh +++ b/lib/backend.sh @@ -40,7 +40,7 @@ backend_status() { local c first_run=true items="" kind parent now detect_components for c in "${COMPONENTS[@]}"; do - component_available "$c" && ! is_action "$c" && [[ "${CURRENT[$c]}" == 1 ]] && first_run=false + component_available "$c" && ! is_action "$c" && is_current "$c" && first_run=false done for c in "${COMPONENTS[@]}"; do component_available "$c" || continue @@ -52,7 +52,7 @@ backend_status() { items+=",\"kind\":\"$kind\",\"parent\":$(json_str "$parent")" items+=",\"needs\":\"\"" items+=",\"on\":$( [[ "$now" == 1 ]] && echo true || echo false)" - items+=",\"wanted\":$( [[ "${WANTED[$c]:-0}" == 1 ]] && echo true || echo false)" + items+=",\"wanted\":$( is_wanted "$c" && echo true || echo false)" items+=",\"update\":$(feature_outdated "$c" && echo true || echo false)" items+=",\"new\":$({ feature_new "$c" || feature_new_optin "$c"; } && echo true || echo false)" items+=",\"selectable\":$(component_selectable "$c" && echo true || echo false)" @@ -163,7 +163,7 @@ backend_apply() { backend_sudo || return 1 LOGIN_MANAGER=plasmalogin - [[ "${WANTED[single]}" == 1 ]] && LOGIN_MANAGER=sddm + is_wanted single && LOGIN_MANAGER=sddm local -a failed=() for c in "${TO_DISABLE[@]}"; do if backend_run_component "$c" disable; then feature_record "$c" disable; else failed+=("$c"); fi diff --git a/lib/menu.sh b/lib/menu.sh index 9f89309..b3c57b8 100644 --- a/lib/menu.sh +++ b/lib/menu.sh @@ -87,6 +87,8 @@ component_available() { esac } +is_wanted() { [[ "${WANTED[$1]:-0}" == 1 ]]; } +is_current() { [[ "${CURRENT[$1]:-0}" == 1 ]]; } is_action() { [[ " ${ACTIONS[*]} " == *" $1 "* ]]; } boot_mode() { @@ -129,7 +131,7 @@ feature_outdated() { # On, but set up by an older version of that feature (compared as # versions: 2.10.0 is newer than 2.9.0). local have want - [[ "${CURRENT[$1]:-0}" == 1 ]] || return 1 + is_current "$1" || return 1 have="$(state_get features "$1" "$FEATURE_BASELINE")" [[ "$have" == off ]] && have="$FEATURE_BASELINE" want="${FEATURE_VERSION[$1]:-$FEATURE_BASELINE}" @@ -266,14 +268,14 @@ defaults_options() { warn "Leaving out ${LABEL[$c]%%:*}: not available on this PC." fi done - [[ "${WANTED[single]}" == 1 ]] && component_available gaming && WANTED[gaming]=1 + is_wanted single && component_available gaming && WANTED[gaming]=1 for c in "${COMPONENTS[@]}"; do [[ "${WANTED[$c]}" == 1 && -n "${PARENT[$c]:-}" ]] && WANTED[${PARENT[$c]}]=1 done fi case "$boot" in desktop) - [[ "${WANTED[gaming]}" == 1 ]] || { err "--boot desktop needs the SteamOS conversion (gaming)."; return 1; } + is_wanted gaming || { err "--boot desktop needs the SteamOS conversion (gaming)."; return 1; } WANTED[boot]=1 ;; gamescope) WANTED[boot]=0 ;; esac @@ -316,7 +318,7 @@ toggle_component() { local c="$1" p x component_selectable "$c" || return 1 WANTED[$c]=$(( 1 - WANTED[$c] )) - if [[ "${WANTED[$c]}" == 1 ]]; then + if is_wanted "$c"; then p="${REQUIRES[$c]:-}" [[ -n "$p" ]] && component_available "$p" && WANTED[$p]=1 x="${EXCLUDES[$c]:-}" @@ -358,16 +360,16 @@ show_menu() { menu_visible "$c" || continue i=$((i + 1)); MENU_ITEMS[$i]=$c # Pad the plain word, then colour it: colour codes would count as width. - now="off"; [[ "${CURRENT[$c]}" == 1 ]] && now="on" + now="off"; is_current "$c" && now="on" is_action "$c" && now="-" now="$(printf '%-6s' "$now")" - [[ "${CURRENT[$c]}" == 1 ]] && now="${now/on/${c_green}on${c_reset}}" - want="[ ]"; [[ "${WANTED[$c]}" == 1 ]] && want="[x]" + is_current "$c" && now="${now/on/${c_green}on${c_reset}}" + want="[ ]"; is_wanted "$c" && want="[x]" if [[ "$c" == boot ]]; then # A choice rather than a checkbox: Now/Want show the mode. - now="gaming"; [[ "${CURRENT[boot]}" == 1 ]] && now="desk" - [[ "${CURRENT[gaming]}" == 1 ]] || now="-" - want="gaming"; [[ "${WANTED[boot]}" == 1 ]] && want="desk" + now="gaming"; is_current boot && now="desk" + is_current gaming || now="-" + want="gaming"; is_wanted boot && want="desk" printf " %-3s %-6s %-6s └ %s\n" "$i" "$now" "$want" "$(boot_choice "${WANTED[boot]}")" elif ! component_selectable "$c"; then local tree=""; [[ -n "${PARENT[$c]:-}" ]] && tree=" └ " @@ -406,8 +408,8 @@ draw_menu_tui() { for c in "${COMPONENTS[@]}"; do menu_visible "$c" || continue MENU_ITEMS[$i]=$c - box="[ ]"; [[ "${WANTED[$c]}" == 1 ]] && box="[${c_green}x${c_reset}]" - state=" (now: off)"; [[ "${CURRENT[$c]}" == 1 ]] && state=" (now: ${c_green}on${c_reset})" + box="[ ]"; is_wanted "$c" && box="[${c_green}x${c_reset}]" + state=" (now: off)"; is_current "$c" && state=" (now: ${c_green}on${c_reset})" is_action "$c" && state=" (opt-in, runs once)" line="$box ${LABEL[$c]}" if [[ "$c" == boot ]]; then @@ -415,9 +417,9 @@ draw_menu_tui() { # Indented under the conversion, whose sub-option it is. line="$(boot_choice "${WANTED[boot]}")" line=" └ ${line/\[/[${c_green}}"; line="${line/\]/${c_reset}]}" - local mode=gamescope; [[ "${CURRENT[boot]}" == 1 ]] && mode=desktop + local mode=gamescope; is_current boot && mode=desktop state=" (${c_bold}←/→${c_reset} choose)" - [[ "${CURRENT[gaming]}" == 1 ]] && state=" (now: $mode; ${c_bold}←/→${c_reset} choose)" + is_current gaming && state=" (now: $mode; ${c_bold}←/→${c_reset} choose)" elif [[ -n "${PARENT[$c]:-}" ]]; then line=" └ $line" fi @@ -506,7 +508,7 @@ plan_changes() { done for c in "${COMPONENTS[@]}"; do component_available "$c" || continue - [[ "${WANTED[$c]}" == 1 ]] || continue + is_wanted "$c" || continue if is_action "$c"; then TO_ENABLE+=("$c"); continue; fi if [[ "${CURRENT[$c]}" == 0 || "$REAPPLY" == true ]] || feature_outdated "$c" || [[ "$c" == gaming && "${CURRENT[single]}" != "${WANTED[single]}" ]]; then @@ -518,7 +520,7 @@ plan_changes() { apply_changes() { local c failed=() LOGIN_MANAGER=plasmalogin - [[ "${WANTED[single]}" == 1 ]] && LOGIN_MANAGER=sddm + is_wanted single && LOGIN_MANAGER=sddm for c in "${TO_DISABLE[@]}"; do if [[ "$c" == boot ]]; then echo; echo -e "${c_bold}Boot into: gamescope${c_reset}" diff --git a/steamify.sh b/steamify.sh index 1ba7d3a..638917c 100755 --- a/steamify.sh +++ b/steamify.sh @@ -151,7 +151,7 @@ run_boot_only() { *) err "--boot takes gamescope or desktop"; return 1 ;; esac detect_components - [[ "${CURRENT[gaming]}" == 1 ]] || { err "--boot needs the SteamOS conversion; turn it on first."; return 1; } + is_current gaming || { err "--boot needs the SteamOS conversion; turn it on first."; return 1; } # What is on stays on, and nothing else changes: not the updates or # removals a normal run would pick. for c in "${COMPONENTS[@]}"; do WANTED[$c]=${CURRENT[$c]:-0}; done @@ -209,7 +209,7 @@ while true; do if [[ "$c" == boot ]]; then echo " - boot into: desktop (from the next boot)" elif is_action "$c"; then echo " - run: ${LABEL[$c]%%:*} at your own risk (checks, then asks twice more)" elif feature_outdated "$c"; then echo " - update: ${LABEL[$c]} (changed in this version)" - elif [[ "${CURRENT[$c]}" == 1 ]]; then echo " - re-apply: ${LABEL[$c]}" + elif is_current "$c"; then echo " - re-apply: ${LABEL[$c]}" elif feature_new "$c"; then echo " - turn on: ${LABEL[$c]} (new in this version)" else echo " - turn on: ${LABEL[$c]}"; fi done @@ -234,11 +234,11 @@ while true; do for c in "${COMPONENTS[@]}"; do component_available "$c" && ! is_action "$c" || continue if [[ "$c" == boot ]]; then - [[ "${CURRENT[gaming]}" == 1 ]] && echo " └ boots into: $(boot_mode "${CURRENT[boot]}")" + is_current gaming && echo " └ boots into: $(boot_mode "${CURRENT[boot]}")" elif [[ -n "${PARENT[$c]:-}" ]]; then [[ "${CURRENT[${PARENT[$c]}]}" == 1 ]] || continue - if [[ "${CURRENT[$c]}" == 1 ]]; then echo -e " └ ${c_green}on ${c_reset} ${LABEL[$c]}"; else echo " └ off ${LABEL[$c]}"; fi - elif [[ "${CURRENT[$c]}" == 1 ]]; then echo -e " ${c_green}on ${c_reset} ${LABEL[$c]}"; else echo " off ${LABEL[$c]}"; fi + if is_current "$c"; then echo -e " └ ${c_green}on ${c_reset} ${LABEL[$c]}"; else echo " └ off ${LABEL[$c]}"; fi + elif is_current "$c"; then echo -e " ${c_green}on ${c_reset} ${LABEL[$c]}"; else echo " off ${LABEL[$c]}"; fi done if [[ ${#FAILED[@]} -gt 0 ]]; then warn "These had problems (see above): ${FAILED[*]}"