picocli icon indicating copy to clipboard operation
picocli copied to clipboard

Support Path/Host completion in AutoComplete for custom types

Open loicrouchon opened this issue 3 years ago • 2 comments

Hello,

I have an @Option being a List<Repository> where Repository is a custom type injected through a TypeConverter.

I recently integrated the AutoComplete bash completions generation and since then, I do have command completions, but I lost the path completions for this option.

I suspect the bash completion to complete overrule the shell built-in path completion and that the solution for this is to integrate the path completion within the completion generated by AutoComplete.

Looking at the documentation I see support for java.io.File/java.nio.file.Path when it comes to path completion. I wasn't however able to find a way to force it for custom types. Looking at the code in picocli.AutoComplete generatePositionalParamsCases/generateOptionsCases I see the java.io.File/java.nio.file.Path cases are hardcoded.

Do you think it would be valuable to make this configurable?

If yes, what would be the recommended approach?

  1. Through a new field in the @Option and @Parameters annotations?
  2. Through an annotation/default method on the TypeConverter? I don't know if this approach is compatible with the AutoComplete, but I assume, it could be possible to scan the classpath for type converters of a given @Option/@Parameters without instantiating the command line itself.
  3. Through an additional optional parameter picocli.CommandLine#registerConverter method? This seems not really compatible with the AutoComplete command that does not instanciate the command line but only needs the main command and the factory.

From an API point of view, I like option 2 because you declare the behavior once and it applies everywhere it is used, but it might be more complex to implement/not matching the philosophy.

Regards,

PS: I might be able to find some time to work on this topic if you deem it valuable

loicrouchon avatar Mar 15 '21 22:03 loicrouchon

I like the idea to make this configurable.

One additional way to accomplish this that I thought of was to have a command line option for the AutoComplete.App and AutoComplete.GenerateCompletion commands. Something like this:

@Option(names = "--fileTypes", split=",", 
    description = "Comma-separated list of fully qualified custom types for which to delegate to built-in file name completion.")
List<Class<?>> fileTypes = new ArrayList<>();

Then the logic could change to this:

} else if (type.equals(File.class) || "java.nio.file.Path".equals(type.getName()) || fileTypes.contains(type)) { //<-- check custom types
    buff.append(format("%s    %s (( currIndex >= %d && currIndex <= %d )); then\n", indent, ifOrElif, min, max)); // as before
    buff.append(format("%s      compopt -o filenames\n", indent));                                    // as before
    buff.append(format("%s      positionals=$( compgen -f -- \"%s\" ) # files\n", indent, currWord)); // as before

We would have to test this, and there may be other ideas.

What do you think?

If you have time to work on this, that would be great!

remkop avatar Mar 15 '21 23:03 remkop

So your proposal is to not have this information as part of the command spec, but to have it as a parameter when calling the AutoComplete command. Did I get this right?

Sounds way easier to implement than to actually make it part of the model but maybe not as declarative in the approach. Still it can a be a fairly decent first step, I like it. Later on, if need be we could still add auto-determination from the model for that new option. But KISS first!

I'll give it a try this week.

loicrouchon avatar Mar 16 '21 07:03 loicrouchon