Skip to content

Commit 0609ae5

Browse files
committed
feat: Group options by tag (in zsh)
1 parent d3a6729 commit 0609ae5

2 files changed

Lines changed: 49 additions & 14 deletions

File tree

clap_complete/src/env/shells.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::ffi::OsString;
22
use std::str::FromStr;
33

44
use super::EnvCompleter;
5+
use clap::builder::StyledStr;
56

67
/// Bash completion adapter
78
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
@@ -376,25 +377,39 @@ function _clap_dynamic_completer_NAME() {
376377
)}")
377378
378379
if [[ -n $completions ]]; then
380+
local -A tag_map
379381
local -a dirs=()
380-
local -a other=()
381382
local completion
383+
local tag
384+
local value
385+
382386
for completion in $completions; do
383-
local value="${completion%%:*}"
387+
IFS=: read -r tag value <<< "$completion"
384388
if [[ "$value" == */ ]]; then
385389
local dir_no_slash="${value%/}"
386-
if [[ "$completion" == *:* ]]; then
387-
local desc="${completion#*:}"
390+
if [[ "$value" == *:* ]]; then
391+
local desc="${value#*:}"
388392
dirs+=("$dir_no_slash:$desc")
389393
else
390394
dirs+=("$dir_no_slash")
391395
fi
392396
else
393-
other+=("$completion")
397+
if (( ${+tag_map["$tag"]} )); then # key exists?
398+
tag_map["$tag"]+=$'\n'"$value"
399+
else
400+
tag_map["$tag"]="$value"
401+
fi
402+
fi
403+
done
404+
[[ -n $dirs ]] && _describe -t dirs 'values' dirs -S '/' -r '/'
405+
for tag in ${(k)tag_map}; do
406+
values=("${(@f)tag_map[$tag]}") # split on newline
407+
if [[ -n $tag ]]; then
408+
_describe -t "$tag" "$tag options" values
409+
else
410+
_describe "options" values
394411
fi
395412
done
396-
[[ -n $dirs ]] && _describe 'values' dirs -S '/' -r '/'
397-
[[ -n $other ]] && _describe 'values' other
398413
fi
399414
}
400415
@@ -431,6 +446,12 @@ compdef _clap_dynamic_completer_NAME BIN"#
431446
if i != 0 {
432447
write!(buf, "{}", ifs.as_deref().unwrap_or("\n"))?;
433448
}
449+
write!(
450+
buf,
451+
"{}:",
452+
candidate.get_tag().unwrap_or(&StyledStr::from("")),
453+
)?;
454+
434455
write!(
435456
buf,
436457
"{}",

clap_complete/tests/snapshots/home/dynamic-env/exhaustive/zsh/zsh/_exhaustive

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,39 @@ function _clap_dynamic_completer_exhaustive() {
1111
)}")
1212

1313
if [[ -n $completions ]]; then
14+
local -A tag_map
1415
local -a dirs=()
15-
local -a other=()
1616
local completion
17+
local tag
18+
local value
19+
1720
for completion in $completions; do
18-
local value="${completion%%:*}"
21+
IFS=: read -r tag value <<< "$completion"
1922
if [[ "$value" == */ ]]; then
2023
local dir_no_slash="${value%/}"
21-
if [[ "$completion" == *:* ]]; then
22-
local desc="${completion#*:}"
24+
if [[ "$value" == *:* ]]; then
25+
local desc="${value#*:}"
2326
dirs+=("$dir_no_slash:$desc")
2427
else
2528
dirs+=("$dir_no_slash")
2629
fi
2730
else
28-
other+=("$completion")
31+
if (( ${+tag_map["$tag"]} )); then # key exists?
32+
tag_map["$tag"]+=$'\n'"$value"
33+
else
34+
tag_map["$tag"]="$value"
35+
fi
36+
fi
37+
done
38+
[[ -n $dirs ]] && _describe -t dirs 'values' dirs -S '/' -r '/'
39+
for tag in ${(k)tag_map}; do
40+
values=("${(@f)tag_map[$tag]}") # split on newline
41+
if [[ -n $tag ]]; then
42+
_describe -t "$tag" "$tag options" values
43+
else
44+
_describe "options" values
2945
fi
3046
done
31-
[[ -n $dirs ]] && _describe 'values' dirs -S '/' -r '/'
32-
[[ -n $other ]] && _describe 'values' other
3347
fi
3448
}
3549

0 commit comments

Comments
 (0)