Skip to content

Commit b946871

Browse files
jsotuyodremkop
authored andcommitted
Rework to use a helper and support positional params
1 parent 8c471fe commit b946871

File tree

1 file changed

+37
-5
lines changed

1 file changed

+37
-5
lines changed

src/main/java/picocli/AutoComplete.java

+37-5
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,41 @@ private static class CommandDescriptor {
422422
" done\n" +
423423
" echo \"$result\"\n" +
424424
"}\n" +
425+
"\n" +
426+
"# compReplyArray generates a list of completion suggestions based on an array, ensuring all values are properly escaped.\n" +
427+
"#\n" +
428+
"# compReplyArray takes a single parameter: the array of options to be displayed\n" +
429+
"#\n" +
430+
"# The output is echoed to std_out, one option per line.\n"
431+
+ "#\n"
432+
+ "# Example usage:\n"
433+
+ "# local options=(\"foo\", \"bar\", \"baz\")\n"
434+
+ "# local IFS=$'\\n'\n"
435+
+ "# COMPREPLY=$(compReplyArray \"${options[@]}\")\n" +
436+
"function compReplyArray() {\n" +
437+
" declare -a options\n" +
438+
" options=(\"$@\")\n" +
439+
" local curr_word=${COMP_WORDS[COMP_CWORD]}\n" +
440+
" local i\n" +
441+
" local quoted\n" +
442+
" local optionList=()\n" +
443+
"\n" +
444+
" for (( i=0; i<${#options[@]}; i++ )); do\n" +
445+
" # Double escape, since we want escaped values, but compgen -W expands the argument\n" +
446+
" printf -v quoted %%q \"${options[i]}\"\n" +
447+
" quoted=\\'${quoted//\\'/\\'\\\\\\'\\'}\\'\n" +
448+
"\n" +
449+
" optionList[i]=$quoted\n" +
450+
" done\n" +
451+
"\n" +
452+
" # We also have to add another round of escaping to $curr_word.\n" +
453+
" curr_word=${curr_word//\\\\/\\\\\\\\}\n" +
454+
" curr_word=${curr_word//\\'/\\\\\\'}\n" +
455+
"\n" +
456+
" # Actually generate completions.\n" +
457+
" local IFS=$'\\n'\n" +
458+
" echo -e \"$(compgen -W \"${optionList[*]}\" -- \"$curr_word\")\"\n" +
459+
"}\n" +
425460
"\n";
426461

427462
private static final String SCRIPT_FOOTER = "" +
@@ -750,9 +785,7 @@ private static String generatePositionalParamsCases(List<PositionalParamSpec> po
750785
int max = param.index().max();
751786
if (param.completionCandidates() != null) {
752787
buff.append(format("%s %s (( currIndex >= %d && currIndex <= %d )); then\n", indent, ifOrElif, min, max));
753-
buff.append(format("%s local IFS=$'\\n'\n", indent));
754-
buff.append(format("%s positionals=$( compgen -W \"${%s_pos_param_args[*]}\" -- \"%s\" )\n",
755-
indent, paramName, currWord));
788+
buff.append(format("%s positionals=$( compReplyArray \"${%s_pos_param_args[@]}\" )\n", indent, paramName, currWord));
756789
} else if (type.equals(File.class) || "java.nio.file.Path".equals(type.getName())) {
757790
buff.append(format("%s %s (( currIndex >= %d && currIndex <= %d )); then\n", indent, ifOrElif, min, max));
758791
buff.append(format("%s local IFS=$'\\n'\n", indent));
@@ -796,8 +829,7 @@ private static String generateOptionsCases(List<OptionSpec> argOptionFields, Str
796829
if (option.completionCandidates() != null) {
797830
buff.append(format("%s %s)\n", indent, concat("|", option.names()))); // " -u|--timeUnit)\n"
798831
buff.append(format("%s local IFS=$'\\n'\n", indent));
799-
buff.append(format("%s COMPREPLY=( $( compgen -W \"${%s_option_args[*]}\" -- \"%s\" ) )\n", indent,
800-
bashify(option.paramLabel()), currWord));
832+
buff.append(format("%s COMPREPLY=( $( compReplyArray \"${%s_option_args[@]}\" ) )\n", indent, bashify(option.paramLabel()), currWord));
801833
buff.append(format("%s return $?\n", indent));
802834
buff.append(format("%s ;;\n", indent));
803835
} else if (type.equals(File.class) || "java.nio.file.Path".equals(type.getName())) {

0 commit comments

Comments
 (0)