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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ For breaking changes, check [here](#breaking-changes).
## Unreleased

- Populate `:msg` in the `:error-fn` data for `dispatch` command errors (`:no-match`, `:input-exhausted`), like option errors already carry it
- zsh completion: classify an option without a `:desc` as an option. It was added as a value, which offered it where zsh hides described options

## 0.12.81

Expand Down
10 changes: 7 additions & 3 deletions src/babashka/cli.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -1711,7 +1711,7 @@ complete -F " fn " " names-sp "
")
:zsh (str "#compdef " names-sp "
" fn "() {
local -a lines described optdescribed bare
local -a lines described optdescribed bareopt bare
lines=(\"${(@f)$(\"${words[1]}\" org.babashka.cli/completions complete --shell zsh -- \"${(@)words[2,CURRENT]}\" 2>/dev/null)}\")
local do_files= l v d
for l in $lines; do
Expand All @@ -1721,8 +1721,11 @@ complete -F " fn " " names-sp "
# _describe eats backslashes and splits on ':', so escape both
v=\"${v//\\\\/\\\\\\\\}\"; d=\"${d//\\\\/\\\\\\\\}\"
v=\"${v//:/\\\\:}\"; d=\"${d//:/\\\\:}\"
if [[ -z $d ]]; then bare+=(\"$v\")
elif [[ $v == -* ]]; then optdescribed+=(\"$v:$d\")
# an option is an option with or without a description: classifying an
# undescribed one as a value would offer it where zsh hides the rest
if [[ $v == -* ]]; then
if [[ -z $d ]]; then bareopt+=(\"$v\"); else optdescribed+=(\"$v:$d\"); fi
elif [[ -z $d ]]; then bare+=(\"$v\")
else described+=(\"$v:$d\"); fi
done
local ret=1
Expand All @@ -1735,6 +1738,7 @@ complete -F " fn " " names-sp "
# flags-only word), so their merged-alias display lines cannot inflate the
# column layout of another group
(( $#optdescribed )) && { _describe -t options option optdescribed; ret=0; }
(( $#bareopt )) && { _describe -t options option bareopt; ret=0; }
(( $#bare )) && { _describe -t values value bare; ret=0; }
[[ -n $do_files ]] && { _files; ret=0; }
return $ret
Expand Down
9 changes: 9 additions & 0 deletions test/babashka/cli/completion_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,15 @@
(snippet-via-cmd cmd-table {:prog "myprogram"} shell))
shell))))

(deftest zsh-snippet-option-classification-test
(let [zsh (snippet-via-cmd cmd-table {:prog "myprogram"} "zsh")]
(testing "a dash-prefixed candidate is classified as an option before its description is considered"
(is (str/includes? zsh "if [[ $v == -* ]]"))
(is (not (str/includes? zsh "elif [[ $v == -* ]]"))))
(testing "an option without a description is added under the options tag"
(is (str/includes? zsh "bareopt+=(\"$v\")"))
(is (str/includes? zsh "_describe -t options option bareopt")))))

(defn- complete-out
"Run the completion handler for `cmdline` and return its emitted
`value\\tdescription` lines as a set of strings."
Expand Down
10 changes: 7 additions & 3 deletions test/resources/completion/completion.zsh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#compdef myprogram
_babashka_cli_complete_myprogram() {
local -a lines described optdescribed bare
local -a lines described optdescribed bareopt bare
lines=("${(@f)$("${words[1]}" org.babashka.cli/completions complete --shell zsh -- "${(@)words[2,CURRENT]}" 2>/dev/null)}")
local do_files= l v d
for l in $lines; do
Expand All @@ -10,8 +10,11 @@ _babashka_cli_complete_myprogram() {
# _describe eats backslashes and splits on ':', so escape both
v="${v//\\/\\\\}"; d="${d//\\/\\\\}"
v="${v//:/\\:}"; d="${d//:/\\:}"
if [[ -z $d ]]; then bare+=("$v")
elif [[ $v == -* ]]; then optdescribed+=("$v:$d")
# an option is an option with or without a description: classifying an
# undescribed one as a value would offer it where zsh hides the rest
if [[ $v == -* ]]; then
if [[ -z $d ]]; then bareopt+=("$v"); else optdescribed+=("$v:$d"); fi
elif [[ -z $d ]]; then bare+=("$v")
else described+=("$v:$d"); fi
done
local ret=1
Expand All @@ -24,6 +27,7 @@ _babashka_cli_complete_myprogram() {
# flags-only word), so their merged-alias display lines cannot inflate the
# column layout of another group
(( $#optdescribed )) && { _describe -t options option optdescribed; ret=0; }
(( $#bareopt )) && { _describe -t options option bareopt; ret=0; }
(( $#bare )) && { _describe -t values value bare; ret=0; }
[[ -n $do_files ]] && { _files; ret=0; }
return $ret
Expand Down