diff --git a/interp/builtin.go b/interp/builtin.go index dcbe26bac..8fd464177 100644 --- a/interp/builtin.go +++ b/interp/builtin.go @@ -518,12 +518,19 @@ func (r *Runner) builtinCode(ctx context.Context, pos syntax.Pos, name string, a } r.setErr(returnStatus(code)) case "read": + var prompt string raw := false fp := flagParser{remaining: args} for fp.more() { switch flag := fp.flag(); flag { case "-r": raw = true + case "-p": + prompt = fp.value() + if prompt == "" { + r.errf("read: -p: option requires an argument\n") + return 2 + } default: r.errf("read: invalid option %q\n", flag) return 2 @@ -538,6 +545,10 @@ func (r *Runner) builtinCode(ctx context.Context, pos syntax.Pos, name string, a } } + if prompt != "" { + r.out(prompt) + } + line, err := r.readLine(raw) if err != nil { return 1 diff --git a/interp/interp_test.go b/interp/interp_test.go index 3a7b6565f..92d2441a7 100644 --- a/interp/interp_test.go +++ b/interp/interp_test.go @@ -2587,6 +2587,22 @@ set +o pipefail "IFS=: read a b c <<< '1\\:2:3'; echo \"$a\"; echo $b; echo $c", "1:2\n3\n\n", }, + { + "read -p", + "read: -p: option requires an argument\nexit status 2 #JUSTERR", + }, + { + "read -X -p", + "read: invalid option \"-X\"\nexit status 2 #JUSTERR", + }, + { + "read -p 'Display me as a prompt. Continue? (y/n) ' choice <<< 'y'; echo $choice", + "Display me as a prompt. Continue? (y/n) y\n", + }, + { + "read -r -p 'Prompt and raw flag together: ' a <<< '\\a\\b\\c'; echo $a", + "Prompt and raw flag together: \\a\\b\\c\n", + }, // getopts {