Skip to content

Commit f3b0afd

Browse files
committed
feat(completions/zsh.rs): Implement postional argument possible values completion
1 parent a652260 commit f3b0afd

File tree

2 files changed

+22
-8
lines changed

2 files changed

+22
-8
lines changed

src/completions/zsh.rs

+20-6
Original file line numberDiff line numberDiff line change
@@ -322,21 +322,31 @@ fn get_args_of(p: &Parser) -> String {
322322
ret.join("\n")
323323
}
324324

325-
// Escape string inside single quotes and brackets
326-
fn escape_string(string: &str) -> String {
325+
// Escape help string inside single quotes and brackets
326+
fn escape_help(string: &str) -> String {
327327
string
328328
.replace("\\", "\\\\")
329329
.replace("'", "'\\''")
330330
.replace("[", "\\[")
331331
.replace("]", "\\]")
332332
}
333333

334+
// Escape value string inside single quotes and parentheses
335+
fn escape_value(string: &str) -> String {
336+
string
337+
.replace("\\", "\\\\")
338+
.replace("'", "'\\''")
339+
.replace("(", "\\(")
340+
.replace(")", "\\)")
341+
.replace(" ", "\\ ")
342+
}
343+
334344
fn write_opts_of(p: &Parser) -> String {
335345
debugln!("write_opts_of;");
336346
let mut ret = vec![];
337347
for o in p.opts() {
338348
debugln!("write_opts_of:iter: o={}", o.name());
339-
let help = o.help().map_or(String::new(), escape_string);
349+
let help = o.help().map_or(String::new(), escape_help);
340350
let mut conflicts = get_zsh_arg_conflicts!(p, o, INTERNAL_ERROR_MSG);
341351
conflicts = if conflicts.is_empty() {
342352
String::new()
@@ -390,7 +400,7 @@ fn write_flags_of(p: &Parser) -> String {
390400
let mut ret = vec![];
391401
for f in p.flags() {
392402
debugln!("write_flags_of:iter: f={}", f.name());
393-
let help = f.help().map_or(String::new(), escape_string);
403+
let help = f.help().map_or(String::new(), escape_help);
394404
let mut conflicts = get_zsh_arg_conflicts!(p, f, INTERNAL_ERROR_MSG);
395405
conflicts = if conflicts.is_empty() {
396406
String::new()
@@ -439,14 +449,18 @@ fn write_positionals_of(p: &Parser) -> String {
439449
for arg in p.positionals() {
440450
debugln!("write_positionals_of:iter: arg={}", arg.b.name);
441451
let a = format!(
442-
"\"{optional}:{name}{help}:_files\" \\",
452+
"'{optional}:{name}{help}:{action}' \\",
443453
optional = if !arg.b.is_set(ArgSettings::Required) { ":" } else { "" },
444454
name = arg.b.name,
445455
help = arg.b
446456
.help
447457
.map_or("".to_owned(), |v| " -- ".to_owned() + v)
448458
.replace("[", "\\[")
449-
.replace("]", "\\]")
459+
.replace("]", "\\]"),
460+
action = arg.possible_vals().map_or("_files".to_owned(), |values| {
461+
format!("({})",
462+
values.iter().map(|v| escape_value(*v)).collect::<Vec<String>>().join(" "))
463+
})
450464
);
451465

452466
debugln!("write_positionals_of:iter: Wrote...{}", a);

tests/completions.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ _myapp() {
108108
'--help[Prints help information]' \
109109
'-V[Prints version information]' \
110110
'--version[Prints version information]' \
111-
"::file -- some input file:_files" \
111+
'::file -- some input file:_files' \
112112
":: :_myapp_commands" \
113113
"*::: :->myapp" \
114114
&& ret=0
@@ -408,7 +408,7 @@ _my_app() {
408408
'--help[Prints help information]' \
409409
'-V[Prints version information]' \
410410
'--version[Prints version information]' \
411-
"::file -- some input file:_files" \
411+
'::file -- some input file:_files' \
412412
":: :_my_app_commands" \
413413
"*::: :->my_app" \
414414
&& ret=0

0 commit comments

Comments
 (0)