prompts.sh 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. # Prompt helpers for interactive setup.
  2. CLEAR_INPUT_SENTINEL="__LIGHTRAG_CLEAR__"
  3. _truncate_for_display() {
  4. local value="$1"
  5. local max=50
  6. if [[ ${#value} -gt $max ]]; then
  7. printf '%s' "${value:0:$max}..."
  8. else
  9. printf '%s' "$value"
  10. fi
  11. }
  12. mask_sensitive_input() {
  13. local prompt="$1"
  14. local value
  15. read -r -p "$prompt" value
  16. printf '%s' "$value"
  17. }
  18. prompt_secret_with_default() {
  19. local prompt="$1"
  20. local default="${2:-}"
  21. local value
  22. if [[ -n "$default" ]]; then
  23. local display_default
  24. display_default="$(_truncate_for_display "$default")"
  25. read -r -p "$prompt [${display_default}]: " value
  26. else
  27. read -r -p "$prompt" value
  28. fi
  29. if [[ -z "$value" ]]; then
  30. value="$default"
  31. fi
  32. printf '%s' "$value"
  33. }
  34. prompt_clearable_with_default() {
  35. local prompt="$1"
  36. local default="${2:-}"
  37. local value
  38. local prompt_text="$prompt"
  39. if [[ -n "$default" ]]; then
  40. prompt_text="$prompt (Enter to keep, type 'clear' to remove)"
  41. else
  42. prompt_text="$prompt (type 'clear' to remove)"
  43. fi
  44. value="$(prompt_with_default "$prompt_text" "$default")"
  45. if [[ "${value,,}" == "clear" ]]; then
  46. printf '%s' "$CLEAR_INPUT_SENTINEL"
  47. return 0
  48. fi
  49. printf '%s' "$value"
  50. }
  51. prompt_clearable_secret_with_default() {
  52. local prompt="$1"
  53. local default="${2:-}"
  54. local value
  55. local prompt_text="$prompt"
  56. if [[ -n "$default" ]]; then
  57. prompt_text="$prompt (Enter to keep, type 'clear' to remove)"
  58. else
  59. prompt_text="$prompt (type 'clear' to remove)"
  60. fi
  61. value="$(prompt_secret_with_default "$prompt_text" "$default")"
  62. if [[ "${value,,}" == "clear" ]]; then
  63. printf '%s' "$CLEAR_INPUT_SENTINEL"
  64. return 0
  65. fi
  66. printf '%s' "$value"
  67. }
  68. prompt_with_default() {
  69. local prompt="$1"
  70. local default="$2"
  71. local value
  72. if [[ -n "$default" ]]; then
  73. read -r -p "$prompt [$default]: " value
  74. else
  75. read -r -p "$prompt: " value
  76. fi
  77. if [[ -z "$value" ]]; then
  78. value="$default"
  79. fi
  80. printf '%s' "$value"
  81. }
  82. style_prompt_text() {
  83. local prompt="$1"
  84. if [[ -n "${COLOR_YELLOW:-}" && "$prompt" == *Docker* ]]; then
  85. prompt="${prompt//Docker/${COLOR_YELLOW}Docker${COLOR_RESET}}"
  86. fi
  87. printf '%s' "$prompt"
  88. }
  89. confirm_default_no() {
  90. local prompt="$1"
  91. local response
  92. local styled_prompt
  93. styled_prompt="$(style_prompt_text "$prompt")"
  94. while true; do
  95. read -r -n 1 -p "$styled_prompt [y/N]: " response
  96. echo
  97. case "$response" in
  98. y|Y) return 0 ;;
  99. n|N|"") return 1 ;;
  100. esac
  101. done
  102. }
  103. confirm_default_yes() {
  104. local prompt="$1"
  105. local response
  106. local styled_prompt
  107. styled_prompt="$(style_prompt_text "$prompt")"
  108. while true; do
  109. read -r -n 1 -p "$styled_prompt [Y/n]: " response
  110. echo
  111. case "$response" in
  112. y|Y|"") return 0 ;;
  113. n|N) return 1 ;;
  114. esac
  115. done
  116. }
  117. confirm_required_yes_no() {
  118. local prompt="$1"
  119. local response
  120. local styled_prompt
  121. styled_prompt="$(style_prompt_text "$prompt")"
  122. while true; do
  123. printf '%b' "$styled_prompt [yes/no]: " >&2
  124. read -r response
  125. case "${response,,}" in
  126. yes) return 0 ;;
  127. no) return 1 ;;
  128. *)
  129. echo "Please type 'yes' or 'no'." >&2
  130. ;;
  131. esac
  132. done
  133. }
  134. prompt_until_valid() {
  135. local prompt="$1"
  136. local default="$2"
  137. local validator="$3"
  138. shift 3
  139. local value
  140. while true; do
  141. value="$(prompt_with_default "$prompt" "$default")"
  142. if "$validator" "$value" "$@"; then
  143. printf '%s' "$value"
  144. return 0
  145. fi
  146. echo "Invalid value. Please try again."
  147. done
  148. }
  149. prompt_secret_until_valid() {
  150. local prompt="$1"
  151. local validator="$2"
  152. shift 2
  153. local value
  154. while true; do
  155. value="$(mask_sensitive_input "$prompt")"
  156. if "$validator" "$value" "$@"; then
  157. printf '%s' "$value"
  158. return 0
  159. fi
  160. echo "Invalid value. Please try again."
  161. done
  162. }
  163. prompt_secret_until_valid_with_default() {
  164. local prompt="$1"
  165. local default="$2"
  166. local validator="$3"
  167. shift 3
  168. local value
  169. while true; do
  170. value="$(prompt_secret_with_default "$prompt" "$default")"
  171. if "$validator" "$value" "$@"; then
  172. printf '%s' "$value"
  173. return 0
  174. fi
  175. echo "Invalid value. Please try again."
  176. done
  177. }
  178. prompt_required_secret() {
  179. local prompt="$1"
  180. local value
  181. while true; do
  182. value="$(mask_sensitive_input "$prompt")"
  183. if [[ -n "$value" ]]; then
  184. printf '%s' "$value"
  185. return 0
  186. fi
  187. echo "Value cannot be empty. Please try again."
  188. done
  189. }
  190. prompt_choice() {
  191. local prompt="$1"
  192. local default="$2"
  193. shift 2
  194. local options=("$@")
  195. local choice
  196. local index=1
  197. local default_index=""
  198. local count="${#options[@]}"
  199. for option in "${options[@]}"; do
  200. if [[ "$option" == "$default" ]]; then
  201. default_index="$index"
  202. fi
  203. index=$((index + 1))
  204. done
  205. while true; do
  206. printf '%s\n' "${COLOR_BLUE}${prompt}${COLOR_RESET} options:" >&2
  207. index=1
  208. for option in "${options[@]}"; do
  209. if [[ "$index" == "$default_index" ]]; then
  210. printf ' %s) %s%s%s\n' \
  211. "${COLOR_GREEN}${index}${COLOR_RESET}" \
  212. "${COLOR_YELLOW}" \
  213. "$option" \
  214. "${COLOR_RESET}" >&2
  215. else
  216. printf ' %s) %s\n' "${COLOR_GREEN}${index}${COLOR_RESET}" "$option" >&2
  217. fi
  218. index=$((index + 1))
  219. done
  220. if [[ -n "$default_index" ]]; then
  221. printf 'Enter number (default: %s): ' "$default_index" >&2
  222. else
  223. printf 'Enter number: ' >&2
  224. fi
  225. if ((count <= 9)); then
  226. read -r -n 1 choice
  227. printf '\n' >&2
  228. else
  229. read -r choice
  230. fi
  231. if [[ -z "$choice" ]]; then
  232. if [[ -n "$default_index" ]]; then
  233. printf '%s' "${options[default_index-1]}"
  234. return 0
  235. fi
  236. elif [[ "$choice" =~ ^[0-9]+$ ]] && ((choice >= 1 && choice <= count)); then
  237. printf '%s' "${options[choice-1]}"
  238. return 0
  239. fi
  240. printf '%s\n' "${COLOR_YELLOW}Invalid selection.${COLOR_RESET} Please enter a number between 1 and ${count}." >&2
  241. done
  242. }