Assume gum is always available and drop fallbacks

This commit is contained in:
David Heinemeier Hansson
2026-06-29 14:49:39 -05:00
parent 38553effa3
commit d4731eca25
7 changed files with 23 additions and 103 deletions
+2 -16
View File
@@ -263,14 +263,7 @@ choose_widget() {
' <<<"$widgets" | awk -F '\t' '{ printf "%-28s %-22s [%s] %s\n", $1, $2, $3, $4 }') ' <<<"$widgets" | awk -F '\t' '{ printf "%-28s %-22s [%s] %s\n", $1, $2, $3, $4 }')
if [[ -t 0 || -t 2 ]]; then if [[ -t 0 || -t 2 ]]; then
if omarchy-cmd-present gum; then selected=$(printf '%s\n' "${options[@]}" | gum filter --header "Add bar widget" --placeholder "Search addable widgets..." --limit 1 --height 14) || return 1
selected=$(printf '%s\n' "${options[@]}" | gum filter --header "Add bar widget" --placeholder "Search addable widgets..." --limit 1 --height 14) || return 1
elif omarchy-cmd-present fzf; then
selected=$(printf '%s\n' "${options[@]}" | fzf --prompt "Add bar widget > " --height 40% --layout reverse --border) || return 1
else
print_available_widgets >&2
fail "gum or fzf is required for interactive widget selection"
fi
else else
print_available_widgets >&2 print_available_widgets >&2
fail "widget id is required; use list to see addable widgets" fail "widget id is required; use list to see addable widgets"
@@ -311,14 +304,7 @@ choose_removal() {
' <<<"$entries" | awk -F '\t' '{ printf "%-10s %-28s %-22s %s\n", $1, $2, $3, $4 }') ' <<<"$entries" | awk -F '\t' '{ printf "%-10s %-28s %-22s %s\n", $1, $2, $3, $4 }')
if [[ -t 0 || -t 2 ]]; then if [[ -t 0 || -t 2 ]]; then
if omarchy-cmd-present gum; then selected=$(printf '%s\n' "${options[@]}" | gum filter --header "Remove bar widget" --placeholder "Search current widgets..." --limit 1 --height 14) || return 1
selected=$(printf '%s\n' "${options[@]}" | gum filter --header "Remove bar widget" --placeholder "Search current widgets..." --limit 1 --height 14) || return 1
elif omarchy-cmd-present fzf; then
selected=$(printf '%s\n' "${options[@]}" | fzf --prompt "Remove bar widget > " --height 40% --layout reverse --border) || return 1
else
jq -r '.[] | "\(.section)[\(.index)]\t\(.id)"' <<<"$entries" >&2
fail "gum or fzf is required for interactive widget selection"
fi
else else
jq -r '.[] | "\(.section)[\(.index)]\t\(.id)"' <<<"$entries" >&2 jq -r '.[] | "\(.section)[\(.index)]\t\(.id)"' <<<"$entries" >&2
fail "widget id is required; use show to see current widgets" fail "widget id is required; use show to see current widgets"
+6 -29
View File
@@ -751,35 +751,19 @@ clone_source_options() {
choose_value() { choose_value() {
local prompt="$1" local prompt="$1"
shift shift
if command -v gum >/dev/null 2>&1; then gum choose --header "$prompt" "$@"
gum choose --header "$prompt" "$@"
else
printf '%s\n' "$@" | fzf --prompt "$prompt > "
fi
} }
input_value() { input_value() {
local prompt="$1" local prompt="$1"
local value="${2:-}" local value="${2:-}"
if command -v gum >/dev/null 2>&1; then gum input --prompt "$prompt " --value "$value"
gum input --prompt "$prompt " --value "$value"
else
read -r -p "$prompt " value
printf '%s' "$value"
fi
} }
choose_clone_source() { choose_clone_source() {
local selected local selected
if command -v gum >/dev/null 2>&1; then selected=$(clone_source_options | awk -F '\t' '{ printf "%-32s %-15s %s\n", $3, $2, $1 }' | gum filter --header "Clone plugin" --placeholder "Search built-in and user plugins..." --limit 1) || return 1
selected=$(clone_source_options | awk -F '\t' '{ printf "%-32s %-15s %s\n", $3, $2, $1 }' | gum filter --header "Clone plugin" --placeholder "Search built-in and user plugins..." --limit 1) || return 1 awk '{ print $NF }' <<<"$selected"
awk '{ print $NF }' <<<"$selected"
elif command -v fzf >/dev/null 2>&1; then
selected=$(clone_source_options | fzf --delimiter=$'\t' --with-nth=1,2,3 --prompt "Clone plugin > ") || return 1
cut -f1 <<<"$selected"
else
fail "gum or fzf is required for interactive clone selection"
fi
} }
edit_source_options() { edit_source_options() {
@@ -795,15 +779,8 @@ edit_source_options() {
choose_edit_source() { choose_edit_source() {
local selected local selected
if command -v gum >/dev/null 2>&1; then selected=$(edit_source_options | awk -F '\t' '{ printf "%-32s %s\n", $2, $1 }' | gum filter --header "Edit plugin" --placeholder "Search user plugins..." --limit 1) || return 1
selected=$(edit_source_options | awk -F '\t' '{ printf "%-32s %s\n", $2, $1 }' | gum filter --header "Edit plugin" --placeholder "Search user plugins..." --limit 1) || return 1 awk '{ print $NF }' <<<"$selected"
awk '{ print $NF }' <<<"$selected"
elif command -v fzf >/dev/null 2>&1; then
selected=$(edit_source_options | fzf --delimiter=$'\t' --with-nth=2,1 --prompt "Edit plugin > ") || return 1
cut -f1 <<<"$selected"
else
fail "gum or fzf is required for interactive plugin selection"
fi
} }
validate_user_plugin_dir() { validate_user_plugin_dir() {
+3 -12
View File
@@ -86,11 +86,8 @@ require_command jq
confirm() { confirm() {
local prompt="$1" local prompt="$1"
((ASSUME_YES)) && return 0 ((ASSUME_YES)) && return 0
if command -v gum >/dev/null 2>&1 && interactive; then
gum confirm "$prompt"; return
fi
if interactive; then if interactive; then
local reply; read -r -p "$prompt [y/N] " reply; [[ $reply == [yY]* ]]; return gum confirm "$prompt"; return
fi fi
fail "refusing to add without confirmation; pass --yes" fail "refusing to add without confirmation; pass --yes"
} }
@@ -110,13 +107,7 @@ if [[ -z $PLUGIN_ID ]]; then
interactive || fail "a plugin-id is required (try: omarchy plugin available)" interactive || fail "a plugin-id is required (try: omarchy plugin available)"
choices=$(jq -r '.[] | "\(.manifest.id)\t\(.manifest.name // .manifest.id)\t\(.manifest.version // "?")\t\(.sourceId)"' <<<"$CATALOG") choices=$(jq -r '.[] | "\(.manifest.id)\t\(.manifest.name // .manifest.id)\t\(.manifest.version // "?")\t\(.sourceId)"' <<<"$CATALOG")
rows=$(awk -F '\t' '{ printf "%-26s %-26s v%-8s [%s]\n", $1, $2, $3, $4 }' <<<"$choices") rows=$(awk -F '\t' '{ printf "%-26s %-26s v%-8s [%s]\n", $1, $2, $3, $4 }' <<<"$choices")
if command -v gum >/dev/null 2>&1; then pick=$(gum choose --header="Add which plugin?" <<<"$rows") || fail "cancelled"
pick=$(gum choose --header="Add which plugin?" <<<"$rows") || fail "cancelled"
elif command -v fzf >/dev/null 2>&1; then
pick=$(fzf --prompt "Add which plugin > " <<<"$rows") || fail "cancelled"
else
fail "a plugin-id is required (gum or fzf needed for an interactive picker)"
fi
[[ -n $pick ]] || fail "nothing selected" [[ -n $pick ]] || fail "nothing selected"
PLUGIN_ID=$(awk '{print $1}' <<<"$pick") PLUGIN_ID=$(awk '{print $1}' <<<"$pick")
fi fi
@@ -227,7 +218,7 @@ if ((!ASSUME_YES)); then
if ((DO_REVIEW)); then if ((DO_REVIEW)); then
review_files review_files
confirm "Add $m_id $m_version now?" || fail "aborted" confirm "Add $m_id $m_version now?" || fail "aborted"
elif interactive && command -v gum >/dev/null 2>&1; then elif interactive; then
action=$(gum choose --header="Add $m_id $m_version?" "Add" "Review files first" "Cancel") || fail "aborted" action=$(gum choose --header="Add $m_id $m_version?" "Add" "Review files first" "Cancel") || fail "aborted"
case "$action" in case "$action" in
"Review files first") "Review files first")
+2 -9
View File
@@ -46,8 +46,7 @@ done
confirm() { confirm() {
local prompt="$1" local prompt="$1"
((ASSUME_YES)) && return 0 ((ASSUME_YES)) && return 0
if command -v gum >/dev/null 2>&1 && interactive; then gum confirm "$prompt"; return; fi if interactive; then gum confirm "$prompt"; return; fi
if interactive; then local reply; read -r -p "$prompt [y/N] " reply; [[ $reply == [yY]* ]]; return; fi
fail "refusing to remove without confirmation; pass --yes" fail "refusing to remove without confirmation; pass --yes"
} }
@@ -57,13 +56,7 @@ if [[ -z $PLUGIN_ID ]]; then
mapfile -t ids < <(find "$PLUGINS_DIR" -mindepth 1 -maxdepth 1 \( -type d -o -type l \) ! -name '.*' -printf '%f\n' 2>/dev/null | sort) mapfile -t ids < <(find "$PLUGINS_DIR" -mindepth 1 -maxdepth 1 \( -type d -o -type l \) ! -name '.*' -printf '%f\n' 2>/dev/null | sort)
((${#ids[@]})) || fail "no plugins installed" ((${#ids[@]})) || fail "no plugins installed"
interactive || fail "a plugin-id is required" interactive || fail "a plugin-id is required"
if command -v gum >/dev/null 2>&1; then PLUGIN_ID=$(printf '%s\n' "${ids[@]}" | gum choose --header="Remove which plugin?") || fail "cancelled"
PLUGIN_ID=$(printf '%s\n' "${ids[@]}" | gum choose --header="Remove which plugin?") || fail "cancelled"
elif command -v fzf >/dev/null 2>&1; then
PLUGIN_ID=$(printf '%s\n' "${ids[@]}" | fzf --prompt "Remove which plugin > ") || fail "cancelled"
else
fail "a plugin-id is required (gum or fzf needed for an interactive picker)"
fi
[[ -n $PLUGIN_ID ]] || fail "nothing selected" [[ -n $PLUGIN_ID ]] || fail "nothing selected"
fi fi
+6 -24
View File
@@ -35,20 +35,14 @@ interactive() {
[[ -t 0 && -t 1 ]] [[ -t 0 && -t 1 ]]
} }
# Yes/no prompt. Honours a caller-set ASSUME_YES, falls back to a plain read # Yes/no prompt. Honours a caller-set ASSUME_YES, and refuses in a
# when gum is missing, and refuses in a non-interactive context so an agent # non-interactive context so an agent must pass --yes deliberately rather than
# must pass --yes deliberately rather than hang on a prompt. # hang on a prompt.
confirm() { confirm() {
local prompt="$1" local prompt="$1"
[[ ${ASSUME_YES:-0} == 1 ]] && return 0 [[ ${ASSUME_YES:-0} == 1 ]] && return 0
if command -v gum >/dev/null 2>&1 && interactive; then
gum confirm "$prompt"
return
fi
if interactive; then if interactive; then
local reply gum confirm "$prompt"
read -r -p "$prompt [y/N] " reply
[[ $reply == [yY]* ]]
return return
fi fi
fail "refusing to continue without confirmation; pass --yes" fail "refusing to continue without confirmation; pass --yes"
@@ -56,13 +50,7 @@ confirm() {
ask_input() { ask_input() {
local prompt="$1" local prompt="$1"
local value="" gum input --prompt "$prompt " || return 1
if command -v gum >/dev/null 2>&1; then
gum input --prompt "$prompt " || return 1
else
read -r -p "$prompt " value || return 1
printf '%s' "$value"
fi
} }
ensure_sources_file() { ensure_sources_file() {
@@ -257,13 +245,7 @@ source_remove() {
if [[ -z $id ]]; then if [[ -z $id ]]; then
interactive || fail "a source id is required" interactive || fail "a source id is required"
if command -v gum >/dev/null 2>&1; then id=$(jq -r '.sources[].id' "$SOURCES_FILE" | gum choose --header="Remove which plugin source?") || fail "cancelled"
id=$(jq -r '.sources[].id' "$SOURCES_FILE" | gum choose --header="Remove which plugin source?") || fail "cancelled"
elif command -v fzf >/dev/null 2>&1; then
id=$(jq -r '.sources[].id' "$SOURCES_FILE" | fzf --prompt "Remove which plugin source > ") || fail "cancelled"
else
fail "a source id is required (install gum or fzf for an interactive picker)"
fi
[[ -n $id ]] || fail "nothing selected" [[ -n $id ]] || fail "nothing selected"
fi fi
+2 -9
View File
@@ -69,8 +69,7 @@ require_command jq
confirm() { confirm() {
local prompt="$1" local prompt="$1"
((ASSUME_YES)) && return 0 ((ASSUME_YES)) && return 0
if command -v gum >/dev/null 2>&1 && interactive; then gum confirm "$prompt"; return; fi if interactive; then gum confirm "$prompt"; return; fi
if interactive; then local reply; read -r -p "$prompt [y/N] " reply; [[ $reply == [yY]* ]]; return; fi
fail "refusing to update without confirmation; pass --yes" fail "refusing to update without confirmation; pass --yes"
} }
@@ -148,13 +147,7 @@ else
done done
[[ -n $outdated ]] || { echo "No updates available."; exit 0; } [[ -n $outdated ]] || { echo "No updates available."; exit 0; }
rows=$(awk -F '\t' 'NF{printf "%-28s %s\n", $1, $2}' <<<"$outdated") rows=$(awk -F '\t' 'NF{printf "%-28s %s\n", $1, $2}' <<<"$outdated")
if command -v gum >/dev/null 2>&1; then pick=$(gum choose --no-limit --header="Update which plugins? (space toggles, enter confirms)" <<<"$rows") || fail "cancelled"
pick=$(gum choose --no-limit --header="Update which plugins? (space toggles, enter confirms)" <<<"$rows") || fail "cancelled"
elif command -v fzf >/dev/null 2>&1; then
pick=$(fzf --multi --prompt "Update which plugins (tab to mark) > " <<<"$rows") || fail "cancelled"
else
fail "a plugin-id is required (install gum or fzf for an interactive picker, or pass --all)"
fi
[[ -n $pick ]] || { echo "Nothing selected."; exit 0; } [[ -n $pick ]] || { echo "Nothing selected."; exit 0; }
mapfile -t targets < <(awk '{print $1}' <<<"$pick") mapfile -t targets < <(awk '{print $1}' <<<"$pick")
fi fi
+2 -4
View File
@@ -20,8 +20,7 @@ echo "Battle.net and its Proton prefix at $PREFIX have been removed."
if omarchy-pkg-present umu-launcher; then if omarchy-pkg-present umu-launcher; then
echo echo
read -rp "Also remove umu-launcher? It's only used by this command. [y/N] " reply if gum confirm "Also remove umu-launcher? It's only used by this command."; then
if [[ $reply =~ ^[Yy]$ ]]; then
omarchy-pkg-drop umu-launcher omarchy-pkg-drop umu-launcher
fi fi
fi fi
@@ -29,8 +28,7 @@ fi
PROTON_DIR="$HOME/.local/share/Steam/compatibilitytools.d" PROTON_DIR="$HOME/.local/share/Steam/compatibilitytools.d"
if compgen -G "$PROTON_DIR/GE-Proton*" >/dev/null; then if compgen -G "$PROTON_DIR/GE-Proton*" >/dev/null; then
echo echo
read -rp "Also remove GE-Proton runtimes downloaded by umu? [y/N] " reply if gum confirm "Also remove GE-Proton runtimes downloaded by umu?"; then
if [[ $reply =~ ^[Yy]$ ]]; then
rm -rf "$PROTON_DIR"/GE-Proton* rm -rf "$PROTON_DIR"/GE-Proton*
rm -rf "$HOME/.local/share/umu" rm -rf "$HOME/.local/share/umu"
fi fi