Skip to content

fix(bash): clear required flags supplied in two-word form - #2488

Open
kratos0718 wants to merge 1 commit into
spf13:mainfrom
kratos0718:fix/2465-clear-required-flag-two-word-form
Open

kratos0718 wants to merge 1 commit into
spf13:mainfrom
kratos0718:fix/2465-clear-required-flag-two-word-form

Conversation

@kratos0718

Copy link
Copy Markdown

Fixes #2465

Problem

writeRequiredFlag records a required flag that takes a value with a trailing =:

format := "    must_have_one_flag+=(\"--%s"
if flag.Value.Type() != "bool" {
    format += "="
}

so a required --host is emitted as:

must_have_one_flag+=("--host=")

__handle_flag only appends that = to flagname when the word itself contained one:

if [[ ${words[c]} == *"="* ]]; then
    flagvalue=${flagname#*=}
    flagname=${flagname%%=*}
    flagname="${flagname}="   # but put the = back
fi
if __%[1]s_contains_word "${flagname}" "${must_have_one_flag[@]}"; then
    must_have_one_flag=()
fi
  • --host=valueflagname becomes --host= → matches → cleared ✅
  • --host valueflagname stays --host → no match → not cleared

In the two-word case must_have_one_flag survives, and __handle_reply then keeps completion pinned to the required set:

if [ ${#must_have_one_flag[@]} -ne 0 ]; then
    allflags=("${must_have_one_flag[@]}")

so after myapp --host localhost <TAB> the user is still offered only --host=, despite having already supplied it.

Fix

Also match the --flag= spelling when clearing:

if __%[1]s_contains_word "${flagname}" "${must_have_one_flag[@]}" || __%[1]s_contains_word "${flagname}=" "${must_have_one_flag[@]}"; then

Only the clearing branch changes — the suggestion list is untouched, so what gets offered is exactly as before. For the --flag=value path flagname already ends in =, making the added probe --flag==, which matches nothing and is harmless. Bool flags are registered without the = and continue to match on the first test.

Testing

Confirmed the behaviour directly in bash rather than only asserting on generated text — reproducing __contains_word and the clearing branch against the real registration must_have_one_flag=("--host="):

--host=value  (flagname becomes '--host=')
  OLD: cleared          NEW: cleared
--host value  (flagname stays '--host')
  OLD: NOT cleared  <-- bug        NEW: cleared

Added TestBashCompletionRequiredFlagClearedForTwoWordForm, which pins both the --host= registration and the new clearing check. It fails on current main and passes with the change.

go test ./..., go vet ./... and gofmt are clean.

writeRequiredFlag records a required flag that takes a value with a
trailing "=", so --host is emitted as must_have_one_flag+=("--host=").

__handle_flag only appends that "=" to flagname when the word itself
contained one. Given "--host=value" flagname becomes "--host=" and
matches, but given "--host value" it stays "--host" and never does, so
must_have_one_flag is not cleared and completion stays restricted to the
required set even though the flag has already been supplied.

Match the "--flag=" spelling as well when clearing. The suggestion list
is untouched, since only the clearing branch changes.

Fixes spf13#2465
@CLAassistant

CLAassistant commented Aug 18, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bash completion does not clear required flags when supplied as --flag value

2 participants