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
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 24 additions & 7 deletions completions/_mise
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,32 @@ _mise() {
if [[ ! -f "$spec_file" ]]; then
mise usage >| "$spec_file"
fi
local -a completions=() inserts=()
local needs_menu=0 display insert
while IFS=$'\t' read -r display insert; do
completions+=("$display")
inserts+=("$insert")
[[ "$insert" == "'"* ]] && needs_menu=1
local -a values=() descs=() inserts=()
local needs_menu=0 line
while IFS= read -r line; do
local -a parts=("${(@ps:\t:)line}")
values+=("${parts[1]}")
descs+=("${parts[2]}")
inserts+=("${parts[3]}")
[[ "${parts[3]}" == "'"* ]] && needs_menu=1
Comment on lines +34 to +37

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Handle 2-column completion rows before calling compadd -a inserts.

This parser assumes 3 fields, but the provided completion examples are 2-field tab rows (value<TAB>insert). In that case, parts[3] is empty, inserts becomes empty entries, and compadd -a inserts can stop inserting the actual token.

Suggested fix
   while IFS= read -r line; do
     local -a parts=("${(`@ps`:\t:)line}")
-    values+=("${parts[1]}")
-    descs+=("${parts[2]}")
-    inserts+=("${parts[3]}")
-    [[ "${parts[3]}" == "'"* ]] && needs_menu=1
+    local _value="${parts[1]}"
+    local _desc=""
+    local _insert=""
+
+    if (( ${`#parts`[@]} >= 3 )); then
+      _desc="${parts[2]}"
+      _insert="${parts[3]}"
+    elif (( ${`#parts`[@]} == 2 )); then
+      _insert="${parts[2]}"
+    else
+      _insert="${parts[1]}"
+    fi
+
+    values+=("${_value}")
+    descs+=("${_desc}")
+    inserts+=("${_insert}")
+    [[ "${_insert}" == "'"* ]] && needs_menu=1
   done < <(command usage complete-word --shell zsh -f "$spec_file" -- "${(Q)words[@]}")

As per coding guidelines, this is based on the provided runtime evidence snippet showing 2-field completion rows in e2e/tasks/test_task_completion_global_cd:13-48.

Also applies to: 40-55

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@completions/_mise` around lines 34 - 37, The parser currently assumes 3
fields and unconditionally does values+=("${parts[1]}"), descs+=("${parts[2]}"),
inserts+=("${parts[3]}"), which produces empty inserts for 2-column rows; change
the logic around parts to detect when parts[3] is empty and parts[2] exists, and
in that case treat parts[2] as the insert (i.e. append parts[2] to inserts and
append an empty string to descs), otherwise keep the current mapping; also
ensure you only append non-empty inserts to avoid compadd -a inserts receiving
empty entries and keep the needs_menu check using the actual insert value (the
variable inserts / the element that was appended).

done < <(command usage complete-word --shell zsh -f "$spec_file" -- "${(Q)words[@]}")
(( needs_menu )) && compstate[insert]=menu
_describe 'completions' completions inserts -U -Q -S ''
if (( ${#inserts[@]} )); then
local -a _usage_display=()
local _usage_i _usage_max=0 _usage_v _usage_pad
for _usage_v in "${values[@]}"; do
(( ${#_usage_v} > _usage_max )) && _usage_max=${#_usage_v}
done
for ((_usage_i=1; _usage_i<=${#values[@]}; _usage_i++)); do
if [[ -n "${descs[_usage_i]}" ]]; then
_usage_pad=$(( _usage_max - ${#values[_usage_i]} ))
_usage_display+=("${values[_usage_i]}${(l:_usage_pad:: :)} -- ${descs[_usage_i]}")
else
_usage_display+=("${values[_usage_i]}")
fi
done
compadd -l -d _usage_display -U -Q -S '' -a inserts
fi
return 0
}

Expand Down
38 changes: 19 additions & 19 deletions mise.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion mise.usage.kdl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
min_usage_version "3.4"
min_usage_version "3.5"
name mise
bin mise
about "Dev tools, env vars, and tasks in one CLI"
Expand Down
9 changes: 5 additions & 4 deletions src/cli/usage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,11 @@ impl Usage {
promote_orphan_shorts(tasks_run);
}

// Require usage >= 3.4, the release that ships the jdx/usage#649 parser fix
// (see jdx/usage#652). This guards old `usage` CLIs from silently
// re-triggering the mise#10069 mis-parse without the fix.
let min_version = r#"min_usage_version "3.4""#;
// Require usage >= 3.5, the release that ships zsh colon completion
// fixes for task names and insert strings (see jdx/usage#666 and
// jdx/usage#670). This guards old `usage` CLIs from silently
// re-triggering the broken colon completion behavior.
let min_version = r#"min_usage_version "3.5""#;
let extra = include_str!("../assets/mise-extra.usage.kdl").trim();
println!("{min_version}\n{}\n{extra}", spec.to_string().trim());
Ok(())
Expand Down
Loading