diff --git a/cli.carp b/cli.carp index d9a6d45..47c8a59 100644 --- a/cli.carp +++ b/cli.carp @@ -826,9 +826,12 @@ the `App` `app`, or an error if there is no such subcommand.") ; the list goes in on newlines rather than on `$IFS`, and `mapfile` reads ; the results back out as whole lines, so a candidate containing a space or ; a glob character stays one literal candidate + ; + ; only the file arm is marked `-o filenames`: it would mangle a value list (defn bash-values [vs] (if (empty? vs) - [@"mapfile -t COMPREPLY < <(compgen -f -- \"$cur\")"] + [@"compopt -o filenames" + @"mapfile -t COMPREPLY < <(compgen -f -- \"$cur\")"] [@"local IFS=$'\\n'" (fmt "local vals=(%s)" &(quoted-words vs)) @"mapfile -t COMPREPLY < <(compgen -W \"${vals[*]}\" -- \"$cur\")"])) diff --git a/test/cli.carp b/test/cli.carp index 7ed530a..4f4a8fb 100644 --- a/test/cli.carp +++ b/test/cli.carp @@ -1111,6 +1111,7 @@ (has? &(completion-bash) &(String.join &(String.from-chars &[\newline]) &[@" --out|-o)" + @" compopt -o filenames" @" mapfile -t COMPREPLY < <(compgen -f -- \"$cur\")"])) "a flag without a declared value set falls back to file completion") @@ -1259,4 +1260,32 @@ &(String.join &(String.from-chars &[\newline]) &[@" local IFS=$'\\n'" @" local vals=('run\\ it' '--help' '-h')"])) - "a subcommand name containing a space is one candidate at the first position")) + "a subcommand name containing a space is one candidate at the first position") + + ; --- Completion: what bash does to a completed file name --- + + (assert-true test + (has? &(completion-bash) + &(String.join &(String.from-chars &[\newline]) + &[@" compopt -o filenames" + @" mapfile -t COMPREPLY < <(compgen -f -- \"$cur\")" + @"}"])) + "the fallback for a positional argument is marked as file names") + + (assert-true test + (has? &(completion-app-bash) + &(String.join &(String.from-chars &[\newline]) + &[@" --out|-o)" @" compopt -o filenames"])) + "a subcommand’s own file completion is marked as file names") + + (assert-true test + (has? &(completion-bash) + &(String.join &(String.from-chars &[\newline]) + &[@" --mode)" @" local IFS=$'\\n'"])) + "a declared value set is not marked as file names") + + (assert-true test + (has? &(completion-app-bash) + &(String.join &(String.from-chars &[\newline]) + &[@" *)" @" local IFS=$'\\n'"])) + "the subcommand name list is not marked as file names"))