Skip to content

Commit 0e23579

Browse files
committed
prompt: Add read_prompt_response, prompt_for_input
1 parent 1c1d684 commit 0e23579

File tree

3 files changed

+150
-1
lines changed

3 files changed

+150
-1
lines changed

lib/prompt

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,60 @@
33
# User input prompts
44
#
55
# Exports:
6+
# @go.read_prompt_response
7+
# Reads a line, trims leading/trailing space, and sets a default if empty
8+
#
9+
# @go.prompt_for_input
10+
# Prompts the user for a line of input
11+
#
612
# @go.select_option
713
# Prompts the user to select one item from a list of options
814

9-
. "$_GO_USE_MODULES" 'validation'
15+
. "$_GO_USE_MODULES" 'strings' 'validation'
16+
17+
# Reads a line, trims leading/trailing space, and sets a default if empty
18+
#
19+
# Arguments:
20+
# var_name: Name of the caller's variable into which to read value
21+
# default: (Optional) Default value if the input line is empty
22+
@go.read_prompt_response() {
23+
@go.validate_identifier_or_die 'Input prompt response variable name' "$1"
24+
read -r "$1"
25+
@go.trim "$1"
26+
printf -v "$1" -- '%s' "${!1:-$2}"
27+
}
28+
29+
# Prompts the user for a line of input
30+
#
31+
# If the prompt doesn't end with a whitespace character, a space will be added
32+
# between the prompt and the input cursor. Otherwise the existing character will
33+
# be preserved.
34+
#
35+
# If a default value is specified, a space will be added to the prompt, followed
36+
# by the default value in square brackets; the caller should not add the default
37+
# value to the prompt directly. If the prompt ends with a whitespace character,
38+
# it will be preserved and added after the default value.
39+
#
40+
# Arguments:
41+
# result_var Name of the caller-declared variable for the result
42+
# prompt Text prompt for user input
43+
# default (Optional) Default value if response is empty
44+
# fail_msg (Optional) Failure message if empty input isn't valid
45+
@go.prompt_for_input() {
46+
@go.validate_identifier_or_die 'Input prompt response variable name' "$1"
47+
48+
if [[ "$2" =~ [[:space:]]$ ]]; then
49+
@go.printf '%s%s%s' "${2%?}" "${3:+ [default: $3]}" "${BASH_REMATCH[0]}" >&2
50+
else
51+
@go.printf '%s %s' "$2" "${3:+[default: $3] }" >&2
52+
fi
53+
@go.read_prompt_response "$1" "$3"
54+
55+
if [[ -z "${!1}" && -n "$4" ]]; then
56+
@go.printf '%s\n' "$4" >&2
57+
return 1
58+
fi
59+
}
1060

1161
# Prompts the user to select one item from a list of options.
1262
#

tests/prompt/prompt-for-input.bats

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#! /usr/bin/env bats
2+
3+
load ../environment
4+
5+
setup() {
6+
test_filter
7+
@go.create_test_go_script '. "$_GO_USE_MODULES" "prompt"' \
8+
'declare prompt="$1"' \
9+
'declare default="$2"' \
10+
'declare fail_msg="$3"' \
11+
'declare response="initial value"' \
12+
'declare result' \
13+
'@go.prompt_for_input "response" "$prompt" "$default" "$fail_msg"' \
14+
'result="$?"' \
15+
'printf -- "%s\n" "$response"' \
16+
'exit "$result"'
17+
}
18+
19+
teardown() {
20+
@go.remove_test_go_rootdir
21+
}
22+
23+
@test "$SUITE: error if variable not a valid identifier" {
24+
@go.create_test_go_script '. "$_GO_USE_MODULES" "prompt"' \
25+
'@go.prompt_for_input "invalid;"'
26+
27+
run "$TEST_GO_SCRIPT"
28+
assert_failure
29+
30+
local err_msg='Input prompt response variable name "invalid;" for '
31+
err_msg+='@go.prompt_for_input contains invalid identifier characters at:'
32+
33+
assert_lines_match "^${err_msg}\$" \
34+
"^ $TEST_GO_SCRIPT:[0-9] main$"
35+
}
36+
37+
@test "$SUITE: reads and trims value" {
38+
run "$TEST_GO_SCRIPT" $'What is your quest?\n' <<<' To seek the grail! '
39+
assert_success 'What is your quest?' \
40+
'To seek the grail!'
41+
}
42+
43+
@test "$SUITE: with default preserves prompt space" {
44+
run "$TEST_GO_SCRIPT" $'What is your quest?\n' 'To seek the grail!' <<<''
45+
assert_success 'What is your quest? [default: To seek the grail!]' \
46+
'To seek the grail!'
47+
}
48+
49+
@test "$SUITE: with default adds prompt space if missing" {
50+
run "$TEST_GO_SCRIPT" 'What is your quest?' 'To seek the grail!' <<<''
51+
assert_success \
52+
'What is your quest? [default: To seek the grail!] To seek the grail!'
53+
}
54+
55+
@test "$SUITE: reads empty input if no error message" {
56+
run "$TEST_GO_SCRIPT" $'What is your quest?\n' <<<''
57+
assert_success 'What is your quest?'
58+
}
59+
60+
@test "$SUITE: fails with error message on empty input" {
61+
run "$TEST_GO_SCRIPT" $'What is your quest?\n' '' 'Auuuuuuuugh!' <<<''
62+
assert_failure 'What is your quest?' \
63+
'Auuuuuuuugh!'
64+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#! /usr/bin/env bats
2+
3+
load ../environment
4+
5+
setup() {
6+
test_filter
7+
}
8+
9+
teardown() {
10+
@go.remove_test_go_rootdir
11+
}
12+
13+
@test "$SUITE: error if response variable not a valid identifier" {
14+
@go.create_test_go_script '. "$_GO_USE_MODULES" "prompt"' \
15+
'@go.read_prompt_response "invalid;"'
16+
17+
run "$TEST_GO_SCRIPT"
18+
assert_failure
19+
20+
local err_msg='Input prompt response variable name "invalid;" for '
21+
err_msg+='@go.read_prompt_response contains invalid identifier characters at:'
22+
23+
assert_lines_match "^${err_msg}\$" \
24+
"^ $TEST_GO_SCRIPT:[0-9] main$"
25+
}
26+
27+
@test "$SUITE: reads and trims variable value, backslashes aren't special" {
28+
@go.create_test_go_script '. "$_GO_USE_MODULES" "prompt"' \
29+
'declare response="initial value"' \
30+
'@go.read_prompt_response "response"' \
31+
'printf -- "%s\n" "$response"'
32+
33+
run "$TEST_GO_SCRIPT" <<<" Hello, World! \ Goodbye, World! "
34+
assert_success 'Hello, World! \ Goodbye, World!'
35+
}

0 commit comments

Comments
 (0)