使用 Python 扩展 BASH 完成点击
Extending BASH completion with Python Click
我想自定义 BASH 我的 Python Click CLI 程序的完成功能,不仅包括脚本的命令/子命令,还包括脚本创建的对象。
假设我的程序名为 cli-tool
,它可以使用以下命令创建对象 foo
:
cli-tool object create foo
为简单起见,假设该命令只是将参数字符串(在本例中为 foo
)连接到位于 ~/.cli-tool/objects/foo
中的同名文本文件。然后执行 cat ~/.cli-tool/objects/foo
会在您的终端中打印 foo
。
我希望该工具执行的操作是当我输入以下内容时:
cli-tool object get <TAB><TAB>
终端将列出 foo
和 ~/.cli-tool/objects
中的任何其他文件。
郑重声明,我已阅读 Python Click 6.x stable documentation,其中明确指出:
Currently, Bash completion is an internal feature that is not
customizable. This might be relaxed in future versions.
我希望有一种方法可以从以下命令中提取 完整 BASH 完成脚本:
eval "$(_CLI_TOOL_COMPLETE=source cli-tool)"
然后自己定制。我也看过 click-completion 项目,但我不确定它除了扩展 Zsh 和 Fish shells 的完成之外还有什么作用。
有没有人达到我上面提到的那种完成度?
使用 click-completion,这非常简单。
代码:
导入并init()
点击完成:
import click
import click_completion
click_completion.init()
然后实例化一个click.Choice
对象:
option_type = click.Choice('obj1 obj2 obj3'.split())
对于您的选项目录,传入适当项目的列表而不是示例 obj1-obj3.
然后将选项类型传递给 click.argument()
装饰器,如:
@click.argument('option', type=option_type)
并且不要忘记使用 shell 激活您的完成。 bash 的点击变化是 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.
对于 Click 8.1.3,您可以使用 Overriding Value Completion or Custom Type Completion。
这是来自 docs where you can use a custom shell_complete
function. It must return a list of CompletionItem
对象的示例,或者作为快捷方式,它可以 return 字符串列表。
def complete_env_vars(ctx, param, incomplete):
return [k for k in os.environ if k.startswith(incomplete)]
@click.command()
@click.argument("name", shell_complete=complete_env_vars)
def cli(name):
click.echo(f"Name: {name}")
click.echo(f"Value: {os.environ[name]}")
我想自定义 BASH 我的 Python Click CLI 程序的完成功能,不仅包括脚本的命令/子命令,还包括脚本创建的对象。
假设我的程序名为 cli-tool
,它可以使用以下命令创建对象 foo
:
cli-tool object create foo
为简单起见,假设该命令只是将参数字符串(在本例中为 foo
)连接到位于 ~/.cli-tool/objects/foo
中的同名文本文件。然后执行 cat ~/.cli-tool/objects/foo
会在您的终端中打印 foo
。
我希望该工具执行的操作是当我输入以下内容时:
cli-tool object get <TAB><TAB>
终端将列出 foo
和 ~/.cli-tool/objects
中的任何其他文件。
郑重声明,我已阅读 Python Click 6.x stable documentation,其中明确指出:
Currently, Bash completion is an internal feature that is not customizable. This might be relaxed in future versions.
我希望有一种方法可以从以下命令中提取 完整 BASH 完成脚本:
eval "$(_CLI_TOOL_COMPLETE=source cli-tool)"
然后自己定制。我也看过 click-completion 项目,但我不确定它除了扩展 Zsh 和 Fish shells 的完成之外还有什么作用。
有没有人达到我上面提到的那种完成度?
使用 click-completion,这非常简单。
代码:
导入并init()
点击完成:
import click
import click_completion
click_completion.init()
然后实例化一个click.Choice
对象:
option_type = click.Choice('obj1 obj2 obj3'.split())
对于您的选项目录,传入适当项目的列表而不是示例 obj1-obj3.
然后将选项类型传递给 click.argument()
装饰器,如:
@click.argument('option', type=option_type)
并且不要忘记使用 shell 激活您的完成。 bash 的点击变化是 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.
对于 Click 8.1.3,您可以使用 Overriding Value Completion or Custom Type Completion。
这是来自 docs where you can use a custom shell_complete
function. It must return a list of CompletionItem
对象的示例,或者作为快捷方式,它可以 return 字符串列表。
def complete_env_vars(ctx, param, incomplete):
return [k for k in os.environ if k.startswith(incomplete)]
@click.command()
@click.argument("name", shell_complete=complete_env_vars)
def cli(name):
click.echo(f"Name: {name}")
click.echo(f"Value: {os.environ[name]}")