fix: unbound variables in bash completion (#1321)

when `set -o nounset` in Bash,
the warnings of unbound variables will break the bash completion.

use `kubectl` as example:

```sh
$ set -o nounset
$ my-cli <Tab>-bash: BASH_COMP_DEBUG_FILE: unbound variable
$
```

the warning break bash completion without any completion result,
and cause my cursor move to the newline.

Use `${variable:-}` substitution in Bash,
that assign an empty string as default for unbound variables to fix the warnings.
This commit is contained in:
Eden Tsai 2021-12-08 06:44:39 +08:00 committed by GitHub
parent d65ba125a3
commit 6f19fa9f61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -24,7 +24,7 @@ func writePreamble(buf io.StringWriter, name string) {
WriteStringAndCheck(buf, fmt.Sprintf(`
__%[1]s_debug()
{
if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
if [[ -n ${BASH_COMP_DEBUG_FILE:-} ]]; then
echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
fi
}
@ -187,7 +187,7 @@ __%[1]s_handle_reply()
PREFIX=""
cur="${cur#*=}"
${flags_completion[${index}]}
if [ -n "${ZSH_VERSION}" ]; then
if [ -n "${ZSH_VERSION:-}" ]; then
# zsh completion needs --flag= prefix
eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )"
fi
@ -278,7 +278,7 @@ __%[1]s_handle_flag()
# if a command required a flag, and we found it, unset must_have_one_flag()
local flagname=${words[c]}
local flagvalue
local flagvalue=""
# if the word contained an =
if [[ ${words[c]} == *"="* ]]; then
flagvalue=${flagname#*=} # take in as flagvalue after the =
@ -297,7 +297,7 @@ __%[1]s_handle_flag()
# keep flag value with flagname as flaghash
# flaghash variable is an associative array which is only supported in bash > 3.
if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then
if [[ -z "${BASH_VERSION:-}" || "${BASH_VERSINFO[0]:-}" -gt 3 ]]; then
if [ -n "${flagvalue}" ] ; then
flaghash[${flagname}]=${flagvalue}
elif [ -n "${words[ $((c+1)) ]}" ] ; then
@ -369,7 +369,7 @@ __%[1]s_handle_word()
__%[1]s_handle_command
elif __%[1]s_contains_word "${words[c]}" "${command_aliases[@]}"; then
# aliashash variable is an associative array which is only supported in bash > 3.
if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then
if [[ -z "${BASH_VERSION:-}" || "${BASH_VERSINFO[0]:-}" -gt 3 ]]; then
words[c]=${aliashash[${words[c]}]}
__%[1]s_handle_command
else
@ -410,8 +410,8 @@ func writePostscript(buf io.StringWriter, name string) {
local command_aliases=()
local must_have_one_flag=()
local must_have_one_noun=()
local has_completion_function
local last_command
local has_completion_function=""
local last_command=""
local nouns=()
local noun_aliases=()
@ -621,7 +621,7 @@ func writeCmdAliases(buf io.StringWriter, cmd *Command) {
sort.Strings(cmd.Aliases)
WriteStringAndCheck(buf, fmt.Sprint(` if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then`, "\n"))
WriteStringAndCheck(buf, fmt.Sprint(` if [[ -z "${BASH_VERSION:-}" || "${BASH_VERSINFO[0]:-}" -gt 3 ]]; then`, "\n"))
for _, value := range cmd.Aliases {
WriteStringAndCheck(buf, fmt.Sprintf(" command_aliases+=(%q)\n", value))
WriteStringAndCheck(buf, fmt.Sprintf(" aliashash[%q]=%q\n", value, cmd.Name()))