pythonclickcommand-line-interface

Shell completion dependent on arguments already provided


I was wondering if it's possible using Click 8 to implement shell completion may depend on commands, options, and arguments that have already been specified earlier on the command line. I see that ctx.params does not include them, however. In any case, consider the following example.

./foo.py --global-opt foo my_command --command-opt <TAB>

I am wondering how to have tab completion for --command-opt depend on the value of --global-opt (a callback, i.e. global, option). Ideally, one could do the usual processing for --global-opt first, before doing shell completion for --command-opt.

In fact, I was told by one of the maintainers that this is possible, but he failed to explain how. Any advice or example would be appreciated.


Solution

  • I don't think there's a proper solution within click. There are questions 1,2 on github about this, without any replies.

    What you can do is implement (partial) command-line parsing yourself and use click's completion facilities:

    def _shell_complete_greeted(ctx, args, incomplete):
        comp_words = os.environ['COMP_WORDS'].split('\n') # potentially unsafe...
        global_opt_val = None
        if '--global-opt' in comp_words:
            idx = comp_words.index('--global-opt')
            global_opt_val = comp_words[idx + 1]
    
        # Compute options based on global_opt_val
        # ...
    
        return options
    

    Of course you'd have to do by hand all the interpretation and checking that click is meant to do for you.