Shell completion
pyparam
supports shell completions for bash
, zsh
and fish
. It also supports the script to be ran as a python script (in the format of python myscript.py
) and as a python module (in the format of python -m myscript
).
To enable the completions, you will have to print the code generated by params.shellcode(...)
, and let the user save it at required locations for the shell to initiate the completion.
params.shellcode
has 3 arguments that generates codes for direct executables, python scripts and python modules.
- Argument
shell
: Specifies the shell (One ofbash
,zsh
andfish
) - Argument
python
: Once specified, program will be ran as a python script or a module. It specifies the path or name to the python you used to run your script or your module. For example, if your python executable ispython3.8
, you will need to specifypython3.8
. In this case, your program name has to be the path tomyscript.py
, for example. - Argument
module
: Whether the program is running as a python module.python
will be used if specified and your program name need to be the name of the module (myscript
, for example).
Let's say you have $ myscript shellcode
calling params.shellcode(...)
and printing the code:
Completions for bash
$ myscript shellcode >> ~/.bashrc
Completions for fish
For direct executable:
$ myscript shellcode >> ~/.config/fish/completions/myscript.fish
$ myscript shellcode >> ~/.config/fish/completions/python.fish
$ # corresponding to your python executable: ^^^^^^
Completions for zsh
$ myscript shellcode >> ~/.zshrc
If you encounter command not found: compdef
, make sure you have this before the inserted code:
autoload -Uz compinit
compinit
Completion value callback
When define a parameter, you can also specify a callback to modify how the completion works for the values. For example, to add some description for a choice
parameter:
def complete_callback(current, prefix):
completes = []
for value in ['xsmall', 'small', 'medium', 'large', 'xlarge']:
# only show the value matches user's incomplete input
if value.startswith(current):
# prefix makes it works with `--choice=...`
# Add some description for each value
completes.append((f'{prefix}{value}', f'Cup size: {value}'))
return completes
params.add_param('choice', type='choice',
choices=['xsmall', 'small', 'medium', 'large', 'xlarge'],
complete_callback=complete_callback)
This is how it looks like in fish
:
> python -m pyparam complete --choice <tab>
large (Cup size: large) small (Cup size: small)
xsmall (Cup size: xsmall) medium (Cup size: medium)
xlarge (Cup size: xlarge)
> python -m pyparam complete --choice x<tab>
xlarge (Cup size: xlarge) xsmall (Cup size: xsmall)
Without the callback:
> python -m pyparam complete --choice <tab>
large medium small xlarge xsmall
> python -m pyparam complete --choice x<tab>
xlarge xsmall
The callback should return:
None
: no completion candidates given, meaning it's requiring user to input a value''
: An empty string, meaning we are done with the this parameter, go ahead to next available ones.-
A list of tuple of:
- 1-element: Shows just the value, without description
- 2-element: Shows both the value and the description
- 3-element: Shows the value, type and the description
There are 3 types of completion candidates.
plain
,file
anddir
. In most cases, it'splain
. But if you want to completefile
ordir
, you should return a list of 3-element tuples. Those 3 elements should be:-
current
: the current incomplete user-input, used to filter the paths (thecurrent
argument). -
type
: eitherfile
ordir
-
prefix
: theprefix
argument, used to do completion for--path=...
Note
file
type of completions will also show directories.
Note
When a command has required parameters uncompleted, no subcommands will show in the candidates.
For example, in your script:
params.add_param('i', required=True)
params.add_command('command')
Then:
> script <tab>
-i (No description)
Enabling completion in your script
Make sure you call params.parse(...)
after all parameters/commands defined to make those shell code work.