Extended implementation of ”YesNoPrompt” shell function, fully POSIX compliant
Designed, developed and tested in 2023 by Juliy V. Chirkov juliyvchirkov@gmail.com under the MIT license.
##################################
# shellcheck shell=sh enable=all #
##################################
yesnoprompt() {
[ $# -eq 0 ] || printf -- "%s " "${*}" >&2
printf "(Y/N)?%s" " " >&2
if [ -t 0 ]; then
stty -echo -icanon -isig
while true; do
REPLY="$(dd bs=1 count=1 2>/dev/null)"
expr "${REPLY}" : "[^yYnN]" >/dev/null 2>&1 || break
done
stty echo icanon isig
fi
expr "${REPLY}" : "[yY]" >/dev/null 2>&1 && REPLY=Y || REPLY=N
printf "%s\n" "${REPLY}" >&2
[ "${REPLY}" = Y ]
}
The above is the extended implementation of ”YesNoPrompt” shell function made fully POSIX compliant
with the triple goal.
- To cover the most common shell interpreters in their ”minimal” (”strict”) mode, when these shells meet the
POSIX specification
likesh
, the standard command language interpreter. - To provide a decent reasonable alternative to the most widespread for years ”YesNoPrompt” implementation because of so called ”bashism”. The thing is the most common solution one can google thru the Internets is based on
bash
builtin commandread
, which is kinda superset over the classicread
. Long story short,read -srn1
, the key of ”YesNoPrompt” implementation inbash
, is totally not portable, ʼcause neither-s
nor-n
option exists in the classic. - To preserve nice look and feel of the UI produced by
read -srn1
inbash
with no use ofread
indeed because of the above on one hand and to implement the function at once as much ubique as possible and flexible to make ”YesNoPrompt” alternative really decent.
Tested and confirmed to run the same cool way with the next shell interpreters: ash
, bash
, dash
, ksh
, mksh
, posh
, rbash
, rksh
, yash
, zsh
and busybox sh
.
Depends on external base system binaries printf
, stty
, dd
and expr
(this oldschool quad should definitely be available anywhere out of the box).
Can be used along with a free style prompt like
yesnoprompt "Lorem ipsum dolor sit amet"
as well as just like yesnoprompt
.
”(Y/N)?” is appended in the first case or displayed alone in the second one automatically.
^C ^D and other control sequences as well as any input symbols except yYnN
are silently ignored while the function waits for a choice.
When one of yYnN
keys is pressed, the function displays the choice and quits with the standard return code - 0
for Y
and 1
for N
.
If the standard input stdin
is not attached to a terminal (i.e. a script with ”YesNoPrompt” is running in non-interactive mode), the function does not wait for the input and quits immediately with N
choice and return code 1
by default.
However, one can alter this behaviour by prepending REPLY
variable with the value of lower y
or upper Y
to the command like
REPLY=Y yesnoprompt "Lorem ipsum dolor sit amet"
The default routine in non-ineractive mode will stay the same, the function wonʼt wait for the input and will immediately quit, but this time the choice will turn to Y
and one will get 0
on return.
If you are facing some bug or want to make a feature request, please leave a comment under this gist or drop a line to my e-mail, and thank you for your time and contribution in advance.
If you like the above, you can follow the links below to support the creator
Thanks from my heart to everyone who supports ✊🏻
Juliy V. Chirkov juliyvchirkov