mirror of
https://github.com/Matir/skel.git
synced 2026-05-25 21:19:09 -07:00
108 lines
2.7 KiB
Bash
108 lines
2.7 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# verify array support
|
|
if eval '_t=(1)' 2>/dev/null; then
|
|
unset _t
|
|
else
|
|
echo "Error: This script requires a shell with array and local variable support (like Bash or Zsh)." >&2
|
|
(return 0 2>/dev/null) && return 1 || exit 1
|
|
fi
|
|
|
|
select_entry() {
|
|
# interactive selection from a list
|
|
# usage: select_entry "$prompt" "$default"
|
|
local prompt="${1:-Select an entry}"
|
|
local default_choice="${2:-}"
|
|
local input_data
|
|
|
|
if [[ -t 0 ]] ; then
|
|
echo "select_entry should be used with piped input" >&2
|
|
return 1
|
|
fi
|
|
|
|
input_data=$(cat)
|
|
|
|
if [[ -z "$input_data" ]]; then
|
|
return 1
|
|
fi
|
|
|
|
local display_prompt="$prompt"
|
|
if [[ -n "$default_choice" ]]; then
|
|
display_prompt="$prompt [$default_choice]"
|
|
fi
|
|
|
|
if [[ -z "${NO_FZF:-}" ]] && command -v fzf >/dev/null 2>&1; then
|
|
local fzf_input="$input_data"
|
|
|
|
# If a default is provided, move that line to the very top
|
|
# so fzf's cursor starts on it.
|
|
if [[ -n "$default_choice" ]]; then
|
|
local default_line
|
|
default_line=$(echo "$input_data" | grep "^$default_choice\([[:space:]]\|$\)")
|
|
if [[ -n "$default_line" ]]; then
|
|
# Remove the original line and prepend it to the top
|
|
fzf_input=$(printf "%s\n%s" "$default_line" "$(echo "$input_data" | grep -v "^$default_choice\([[:space:]]\|$\)")")
|
|
fi
|
|
fi
|
|
|
|
local choice
|
|
choice=$(echo "$fzf_input" | \
|
|
fzf --prompt="$prompt: " --accept-nth 1 --height '~100%' --reverse)
|
|
if [[ -z "$choice" ]]; then
|
|
[[ -n "$default_choice" ]] && echo "$default_choice" && return 0
|
|
return 1
|
|
fi
|
|
echo "${choice}"
|
|
return 0
|
|
else
|
|
local i=1
|
|
local lines=()
|
|
|
|
printf "\n--- %s ---\n" "$prompt" >&2
|
|
|
|
# Load lines into an array
|
|
while IFS= read -r line; do
|
|
[[ -z "$line" ]] && continue
|
|
printf "%2d) %s\n" "$i" "$line"
|
|
lines[i]="$line"
|
|
((i++))
|
|
done <<< "$input_data"
|
|
|
|
local count=$((i - 1))
|
|
|
|
printf "%s (1-%d or word): " "$display_prompt" "$count" >&2
|
|
read -r choice
|
|
|
|
if [[ -z "$choice" ]]; then
|
|
if [[ -n "$default_choice" ]]; then
|
|
echo "$default_choice"
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
# Match logic
|
|
if [[ "$choice" =~ ^[0-9]+$ ]] && (( choice >= 1 && choice <= count )); then
|
|
echo "${lines[$choice]}" | awk '{print $1}'
|
|
else
|
|
# Iterate to find word match
|
|
local found=0
|
|
for (( j=1; j<=count; j++ )); do
|
|
local current_line="${lines[$j]}"
|
|
local first_word="${current_line%%[[:space:]]*}"
|
|
if [[ "$choice" == "$first_word" ]]; then
|
|
echo "$first_word"
|
|
found=1
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [[ $found -eq 0 ]]; then
|
|
echo "Invalid selection: $choice" >&2
|
|
return 1
|
|
fi
|
|
fi
|
|
fi
|
|
}
|