Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions lib/bash/cli/lib_cli.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1622,10 +1622,9 @@ base_cli_completion_script() {
printf '%s\n' ' if [[ "$cursor" =~ ^[0-9]+$ ]]; then cursor=$((10#$cursor)); else cursor=0; fi'
printf '%s\n' ' word_count="${#completion_words[@]}"'
printf '%s\n' ' if ((cursor > 0)); then'
printf '%s\n' ' if ((cursor < word_count)); then'
printf '%s\n' ' cli_words=( "${completion_words[@]:1:cursor}" )'
printf '%s\n' ' else'
printf '%s\n' ' cli_words=( "${completion_words[@]:1}" )'
printf '%s\n' ' cli_words=( "${completion_words[@]:1:cursor}" )'
printf '%s\n' ' if ((cursor >= word_count)); then'

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Altitude — the code edit is a behavior no-op; it does not deliver the hardening the issue asked for.

Swapping if ((cursor < word_count)) ... else ... to if ((cursor >= word_count)) ... else ... (with the two branch bodies swapped to match) produces byte-for-byte the same runtime behavior as before, for every value of cursor/word_count — cursor >= word_count is the exact negation of cursor < word_count, so branch A and branch B still fire under exactly the same conditions as on main.

Verified empirically: checking out this PR's new lib_cli.bats tests against the pre-PR lib_cli.sh (i.e. reverting only the .sh change, keeping the new regression tests) still passes all 40 tests, including the new cursor-boundary and set -u cases. That confirms the .sh change carries zero behavioral difference — the only thing this PR actually adds is test coverage.

Issue #527 explicitly asks for "an implementation shape that cannot lose the empty current word during future completion changes," but the new shape has the identical risk surface as the old one (a future edit can drop the cli_words+=("") line just as easily in either ordering). The tests are valuable and should be kept, but the .sh hunk doesn't structurally reduce the regression risk it claims to close — consider a comment pinning the invariant next to line 1625/1629, or extracting the clamp logic so it can be exercised directly instead of only through the printf-generated string.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in e255cc4. The generated adapter now slices the words once and appends the empty current word under an explicit cursor-at/end invariant, with the invariant documented beside the append. The focused 40-test CLI suite and the full 683-test repository gate pass.

printf '%s\n' ' # COMP_CWORD at or beyond the array end means the current word is empty.'
printf '%s\n' ' cli_words+=("")'
printf '%s\n' ' fi'
printf '%s\n' ' fi'
Expand Down
12 changes: 12 additions & 0 deletions lib/bash/cli/tests/lib_cli.bats
Original file line number Diff line number Diff line change
Expand Up @@ -760,10 +760,22 @@ EOF
_cursor_complete
[ "${COMPREPLY[*]}" = user ]

COMP_CWORD=99
_cursor_complete
[ "${COMPREPLY[*]}" = user ]

COMP_WORDS=(cursor)
COMP_CWORD=1
_cursor_complete
[ "${COMPREPLY[*]}" = admin ]

unset COMP_WORDS COMP_CWORD
set -u
_cursor_complete
status=$?
set +u
[ "$status" -eq 0 ]
[ "${COMPREPLY[*]}" = admin ]
}

@test "completion consumes option values and honors the double-dash boundary" {
Expand Down
Loading