I'm wanting to customize the BASH completion functionality of my Python Click CLI program to include not only the commands / subcommands of the script, but also objects that the script creates.
Let's say my program is called cli-tool
, and it can create object foo
using the command:
cli-tool object create foo
For simplicity, let's say the command simply concatenates the argument string (foo
in this case) to a text file of the same name located in ~/.cli-tool/objects/foo
. Doing cat ~/.cli-tool/objects/foo
would then print foo
in your terminal.
What I would like for the tool to do is when I then type:
cli-tool object get <TAB><TAB>
The terminal would then list foo
and any other files that live inside ~/.cli-tool/objects
.
For the record, I have read the Python Click 6.x stable documentation, which clearly states:
Currently, Bash completion is an internal feature that is not customizable. This might be relaxed in future versions.
What I was hoping is that there would be a way to extract the full BASH completion script from the following command:
eval "$(_CLI_TOOL_COMPLETE=source cli-tool)"
And then customize it myself. I've also seen the click-completion project, but I'm not sure what it does beyond extending the completion for Zsh and Fish shells.
Has anyone achieved the type of completion I mention above?
Bash completion is a functionality through which Bash helps users type their commands more quickly and easily. It does this by presenting possible options when users press the Tab key while typing a command.
Bash completion is a bash function that allows you to auto complete commands or arguments by typing partially commands or arguments, then pressing the [Tab] key. This will help you when writing the bash command in terminal.
Shell completion suggests command names, option names, and values for choice, file, and path parameter types. Options are only listed if at least a dash has been entered. Hidden commands and options are not shown.
Using click-completion, this is quite straight forward.
Import and init()
Click Completion:
import click
import click_completion
click_completion.init()
Then instantiate a click.Choice
object:
option_type = click.Choice('obj1 obj2 obj3'.split())
In the case of your option directory, pass in a list of the appropriate items instead of the example obj1-obj3.
Then pass the option type to the click.argument()
decorator like:
@click.argument('option', type=option_type)
And don't forget to activate your completion with your shell. The click variation for bash is here:
import click
import click_completion
click_completion.init()
option_type = click.Choice('obj1 obj2 obj3'.split())
@click.group()
def cli():
"""My Cool Tool"""
@cli.group(name='object')
def object_group():
"""Object subcommand"""
@object_group.command()
@click.argument('option', type=option_type)
def get(option):
click.echo('option: {}'.format(option))
commands = (
('"" object get ""', 1),
('"" object get ""', 2),
('"" object get ""', 3),
'object get obj1',
'--help',
'object --help',
'object get --help',
)
os.environ['BASH_COMP'] = 'complete'
import sys, time
time.sleep(1)
print('Click Version: {}'.format(click.__version__))
print('Click Completion Version: {}'.format(click_completion.__version__))
print('Python Version: {}'.format(sys.version))
for cmd in commands:
try:
time.sleep(0.1)
print('\n-----------')
print('> ' + str(cmd))
time.sleep(0.1)
if len(cmd) == 2:
os.environ['COMP_WORDS'] = cmd[0]
os.environ['COMP_CWORD'] = str(cmd[1])
cli(complete_var='BASH_COMP')
else:
try:
del os.environ['COMP_WORDS']
del os.environ['COMP_CWORD']
except:
pass
cli(cmd.split())
except BaseException as exc:
if str(exc) != '0' and \
not isinstance(exc, (click.ClickException, SystemExit)):
raise
Click Version: 6.7
Click Completion Version: 0.4.1
Python Version: 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
-----------
> ('"" object get ""', 1)
object
-----------
> ('"" object get ""', 2)
get
-----------
> ('"" object get ""', 3)
obj1 obj2 obj3
-----------
> object get obj1
option: obj1
-----------
> --help
Usage: test.py [OPTIONS] COMMAND [ARGS]...
My Cool Tool
Options:
--help Show this message and exit.
Commands:
object Object subcommand
-----------
> object --help
Usage: test.py object [OPTIONS] COMMAND [ARGS]...
Object subcommand
Options:
--help Show this message and exit.
Commands:
get
-----------
> object get --help
Usage: test.py object get [OPTIONS] OPTION
Options:
--help Show this message and exit.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With