From bd2610d2757336c5582218ae0d53bc69fe2dd9d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20H=C3=B6ppner?= Date: Wed, 11 Mar 2026 19:07:07 +0100 Subject: [PATCH] libutil/util_autocomp: Fix default file completion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For Bash, when compspecs are found the generated script is returned as the full set of possible completions and default completions are disabled [1]. This leads to the behaviour that command line arguments are not completed, only options defined by the script. Zsh has the same issue. Fix the issue by always adding the bash defaults to the generated script. For zsh the corresponding file completion is always added to the end of the argument list and the -A "*" option is added to allow completion after positional arguments. [1] https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html#Programmable-Completion-1 Fixes: 638cbbe332c2 ("libutil: Implement zsh and bash autocompletion") Reported-by: Stefan Haberland Reviewed-by: Szabina Korbai Signed-off-by: Jan Höppner --- libutil/util_autocomp_host.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/libutil/util_autocomp_host.c b/libutil/util_autocomp_host.c index 5b617cdd..3ac6834a 100644 --- a/libutil/util_autocomp_host.c +++ b/libutil/util_autocomp_host.c @@ -28,10 +28,12 @@ static const char *bash_script_part1 = "() {\n\ \tcurrent_word=\"${COMP_WORDS[COMP_CWORD]}\"\n\ \toptions_array=\""; -static const char *bash_script_part2 = "\tif [[ ${current_word} == -* || ${COMP_CWORD} -eq 1 ]] ; then\n\ +static const char *bash_script_part2 = "\tif [[ ${current_word} == -* ]] ; then\n\ \t\tmapfile -t \"COMPREPLY\" < <(compgen -W \"${options_array}\" -- \"$current_word\")\n\ -\t\treturn 0\n\ +\telse\n\ +\t\tcompopt -o bashdefault -o default\n\ \tfi\n\ +\treturn 0\n\ }\n\ complete -F "; @@ -85,7 +87,7 @@ static int start_bash_scriptfile(int fd, char *func_name) static int start_zsh_scriptfile(int fd, char *func_name, char *tool_name) { - const char *part3 = " {\n\n\t_arguments -C \\\n"; + const char *part3 = " {\n\n\t_arguments -C -A \"*\" \\\n"; const char *part2 = "\n\nfunction "; const char *part1 = "#compdef "; int len, ret = 0; @@ -126,6 +128,7 @@ static int write_bash_command_options(struct util_opt *opt_vec, int fd) static int write_zsh_command_options(struct util_opt *opt_vec, int fd) { + const char *end = "\t\t\"*:files:_files\"\n}\n"; const char *name, *desc; char *str; int len; @@ -144,8 +147,14 @@ static int write_zsh_command_options(struct util_opt *opt_vec, int fd) free(str); } } - if (write(fd, "\n}\n", 3) != 3) + len = asprintf(&str, "%s", end); + if (len == -1) return -EIO; + if (write(fd, str, len) != len) { + free(str); + return -EIO; + } + free(str); return 0; }