-
Notifications
You must be signed in to change notification settings - Fork 425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Honor spaces in autocomplete candidates #1759
Changes from 5 commits
4bc3a48
568fc33
eb1a7c8
5c00bc0
aed23ba
37f5849
10e97ff
de32d72
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -422,6 +422,41 @@ private static class CommandDescriptor { | |
" done\n" + | ||
" echo \"$result\"\n" + | ||
"}\n" + | ||
"\n" + | ||
"# compReplyArray generates a list of completion suggestions based on an array, ensuring all values are properly escaped.\n" + | ||
"#\n" + | ||
"# compReplyArray takes a single parameter: the array of options to be displayed\n" + | ||
"#\n" + | ||
"# The output is echoed to std_out, one option per line.\n" | ||
+ "#\n" | ||
+ "# Example usage:\n" | ||
+ "# local options=(\"foo\", \"bar\", \"baz\")\n" | ||
+ "# local IFS=$'\\n'\n" | ||
+ "# COMPREPLY=($(compReplyArray \"${options[@]}\"))\n" + | ||
"function compReplyArray() {\n" + | ||
" declare -a options\n" + | ||
" options=(\"$@\")\n" + | ||
" local curr_word=${COMP_WORDS[COMP_CWORD]}\n" + | ||
" local i\n" + | ||
" local quoted\n" + | ||
" local optionList=()\n" + | ||
"\n" + | ||
" for (( i=0; i<${#options[@]}; i++ )); do\n" + | ||
" # Double escape, since we want escaped values, but compgen -W expands the argument\n" + | ||
" printf -v quoted %%q \"${options[i]}\"\n" + | ||
" quoted=\\'${quoted//\\'/\\'\\\\\\'\\'}\\'\n" + | ||
"\n" + | ||
" optionList[i]=$quoted\n" + | ||
" done\n" + | ||
"\n" + | ||
" # We also have to add another round of escaping to $curr_word.\n" + | ||
" curr_word=${curr_word//\\\\/\\\\\\\\}\n" + | ||
" curr_word=${curr_word//\\'/\\\\\\'}\n" + | ||
"\n" + | ||
" # Actually generate completions.\n" + | ||
" local IFS=$'\\n'\n" + | ||
" echo -e \"$(compgen -W \"${optionList[*]}\" -- \"$curr_word\")\"\n" + | ||
"}\n" + | ||
"\n"; | ||
|
||
private static final String SCRIPT_FOOTER = "" + | ||
|
@@ -641,7 +676,8 @@ private static String generateFunctionForCommand(String functionName, String com | |
" else\n" + | ||
" local positionals=\"\"\n" + | ||
"%s" + | ||
" COMPREPLY=( $(compgen -W \"${commands} ${positionals}\" -- \"${curr_word}\") )\n" + | ||
" local IFS=$'\\n'\n" + | ||
" COMPREPLY=( $(compgen -W \"${commands// /$'\\n'}${IFS}${positionals}\" -- \"${curr_word}\") )\n" + | ||
" fi\n" + | ||
"}\n"; | ||
|
||
|
@@ -715,16 +751,16 @@ private static String generateFunctionForCommand(String functionName, String com | |
|
||
private static void generatePositionParamCompletionCandidates(StringBuilder buff, PositionalParamSpec f) { | ||
String paramName = bashify(f.paramLabel()); | ||
buff.append(format(" local %s_pos_param_args=\"%s\" # %d-%d values\n", | ||
buff.append(format(" local %s_pos_param_args=(\"%s\") # %d-%d values\n", | ||
paramName, | ||
concat(" ", extract(f.completionCandidates())).trim(), | ||
concat("\" \"", extract(f.completionCandidates())).trim(), | ||
f.index().min(), f.index().max())); | ||
} | ||
|
||
private static void generateCompletionCandidates(StringBuilder buff, OptionSpec f) { | ||
buff.append(format(" local %s_option_args=\"%s\" # %s values\n", | ||
buff.append(format(" local %s_option_args=(\"%s\") # %s values\n", | ||
bashify(f.paramLabel()), | ||
concat(" ", extract(f.completionCandidates())).trim(), | ||
concat("\" \"", extract(f.completionCandidates())).trim(), | ||
f.longestName())); | ||
} | ||
private static List<String> extract(Iterable<String> generator) { | ||
|
@@ -749,7 +785,7 @@ private static String generatePositionalParamsCases(List<PositionalParamSpec> po | |
int max = param.index().max(); | ||
if (param.completionCandidates() != null) { | ||
buff.append(format("%s %s (( currIndex >= %d && currIndex <= %d )); then\n", indent, ifOrElif, min, max)); | ||
buff.append(format("%s positionals=$( compgen -W \"$%s_pos_param_args\" -- \"%s\" )\n", indent, paramName, currWord)); | ||
buff.append(format("%s positionals=$( compReplyArray \"${%s_pos_param_args[@]}\" )\n", indent, paramName, currWord)); | ||
} else if (type.equals(File.class) || "java.nio.file.Path".equals(type.getName())) { | ||
buff.append(format("%s %s (( currIndex >= %d && currIndex <= %d )); then\n", indent, ifOrElif, min, max)); | ||
buff.append(format("%s local IFS=$'\\n'\n", indent)); | ||
|
@@ -792,7 +828,8 @@ private static String generateOptionsCases(List<OptionSpec> argOptionFields, Str | |
} | ||
if (option.completionCandidates() != null) { | ||
buff.append(format("%s %s)\n", indent, concat("|", option.names()))); // " -u|--timeUnit)\n" | ||
buff.append(format("%s COMPREPLY=( $( compgen -W \"${%s_option_args}\" -- \"%s\" ) )\n", indent, bashify(option.paramLabel()), currWord)); | ||
buff.append(format("%s local IFS=$'\\n'\n", indent)); | ||
buff.append(format("%s COMPREPLY=( $( compReplyArray \"${%s_option_args[@]}\" ) )\n", indent, bashify(option.paramLabel()), currWord)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We recently discovered that the format string has only 2 This means that the last parameter ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed in #2175 |
||
buff.append(format("%s return $?\n", indent)); | ||
buff.append(format("%s ;;\n", indent)); | ||
} else if (type.equals(File.class) || "java.nio.file.Path".equals(type.getName())) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We recently discovered that the format string has only 2
%s
variables, but we specify 3 parameters (indent
,paramName
,currWord
)...This means that the last parameter (
currWord
) is not used.Is that correct? Can the
currWord
parameter be removed?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it can be removed. Sorry for missing that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in #2175