Cleo 允许您创建美观且可测试的命令行界面。
项目描述
Cleo
创建美观且可测试的命令行界面。
资源
使用方法
要创建一个从命令行问候您的命令,创建 greet_command.py
并将以下内容添加到其中
from cleo.commands.command import Command
from cleo.helpers import argument, option
class GreetCommand(Command):
name = "greet"
description = "Greets someone"
arguments = [
argument(
"name",
description="Who do you want to greet?",
optional=True
)
]
options = [
option(
"yell",
"y",
description="If set, the task will yell in uppercase letters",
flag=True
)
]
def handle(self):
name = self.argument("name")
if name:
text = f"Hello {name}"
else:
text = "Hello"
if self.option("yell"):
text = text.upper()
self.line(text)
您还需要创建一个名为 application.py
的文件,以便在命令行中运行,它将创建一个 Application
并向其中添加命令
#!/usr/bin/env python
from greet_command import GreetCommand
from cleo.application import Application
application = Application()
application.add(GreetCommand())
if __name__ == "__main__":
application.run()
通过运行以下命令来测试新命令
$ python application.py greet John
这将打印以下内容到命令行
Hello John
您还可以使用 --yell
选项将所有内容转换为大写
$ python application.py greet John --yell
这会打印
HELLO JOHN
输出着色
每次输出文本时,您都可以用标签将其包围以着色输出。例如
# blue text
self.line("<info>foo</info>")
# green text
self.line("<comment>foo</comment>")
# cyan text
self.line("<question>foo</question>")
# bold red text
self.line("<error>foo</error>")
关闭标签可以用 </>
替换,这将取消由最后一个打开的标签建立的任何格式化选项。
您可以使用 add_style()
方法定义自己的样式
self.add_style("fire", fg="red", bg="yellow", options=["bold", "blink"])
self.line("<fire>foo</fire>")
可用的前景色和背景色有:black
(黑色)、red
(红色)、green
(绿色)、yellow
(黄色)、blue
(蓝色)、magenta
(洋红色)、cyan
(青色)和 white
(白色)。
可用的选项有:bold
(加粗)、underscore
(下划线)、blink
(闪烁)、reverse
(反转)和 conceal
(隐藏)。
您也可以在标签名称内设置这些颜色和选项
# green text
self.line("<fg=green>foo</>")
# black text on a cyan background
self.line("<fg=black;bg=cyan>foo</>")
# bold text on a yellow background
self.line("<bg=yellow;options=bold>foo</>")
详细程度级别
Cleo 有四个详细程度级别。这些在 Output
类中定义
模式 | 含义 | 控制台选项 |
---|---|---|
Verbosity.QUIET |
不输出任何消息 | -q 或 --quiet |
Verbosity.NORMAL |
默认详细程度级别 | (无) |
Verbosity.VERBOSE |
消息的详细程度增加 | -v |
Verbosity.VERY_VERBOSE |
信息性非必要消息 | -vv |
Verbosity.DEBUG |
调试消息 | -vvv |
您可以在命令中打印仅在特定详细程度级别上显示的消息。例如
if Verbosity.VERBOSE <= self.io.verbosity:
self.line(...)
还有更多语义方法可以用来测试每个详细程度级别
if self.output.is_quiet():
# ...
if self.output.is_verbose():
# ...
您也可以直接将详细程度标志传递给 line()
。
self.line("", verbosity=Verbosity.VERBOSE)
当使用安静级别时,所有输出都将被抑制。
使用参数
命令最有意思的部分是您可以提供的参数和选项。参数是命令名称之后由空格分隔的字符串。它们是有序的,可以是可选的或必需的。例如,向命令添加一个可选的 last_name
参数并使 name
参数成为必需的
class GreetCommand(Command):
name = "greet"
description = "Greets someone"
arguments = [
argument(
"name",
description="Who do you want to greet?",
),
argument(
"last_name",
description="Your last name?",
optional=True
)
]
options = [
option(
"yell",
"y",
description="If set, the task will yell in uppercase letters",
flag=True
)
]
现在您可以在您的命令中访问 last_name
参数
last_name = self.argument("last_name")
if last_name:
text += f" {last_name}"
命令现在可以使用以下两种方式之一使用
$ python application.py greet John
$ python application.py greet John Doe
您还可以让一个参数接受一系列值(假设您想问候所有的朋友)。为此,必须在参数列表的末尾指定
class GreetCommand(Command):
name = "greet"
description = "Greets someone"
arguments = [
argument(
"names",
description="Who do you want to greet?",
multiple=True
)
]
options = [
option(
"yell",
"y",
description="If set, the task will yell in uppercase letters",
flag=True
)
]
要使用此功能,只需指定您想要的名称数量即可
$ python application.py greet John Jane
您可以将 names
参数作为列表访问
names = self.argument("names")
if names:
text = "Hello " + ", ".join(names)
使用选项
与参数不同,选项是无序的(这意味着您可以用任何顺序指定它们),并且用两个短横线指定(例如 --yell
- 您也可以声明一个单字母快捷键,您可以用单个短横线调用它,如 -y
)。选项总是可选的,并且可以设置为接受一个值(例如 --dir=src
)或简单地作为一个没有值的布尔标志(例如 --yell
)。
提示:您也可以使一个选项 可选地 接受一个值(这样
--yell
或--yell=loud
都可以工作)。选项也可以配置为接受值的列表。
例如,向命令添加一个新选项,用于指定消息应连续打印多少次
class GreetCommand(Command):
name = "greet"
description = "Greets someone"
arguments = [
argument(
"name",
description="Who do you want to greet?",
optional=True
)
]
options = [
option(
"yell",
"y",
description="If set, the task will yell in uppercase letters",
flag=True
),
option(
"iterations",
description="How many times should the message be printed?",
default=1
)
]
接下来,在命令中使用此功能来多次打印消息
for _ in range(int(self.option("iterations"))):
self.line(text)
现在,当您运行任务时,您可以可选地指定一个 --iterations
标志
$ python application.py greet John
$ python application.py greet John --iterations=5
第一个示例只会打印一次,因为iterations
为空,默认为1
。第二个示例将打印五次。
请记住,选项不关心它们的顺序。因此,以下两种方式都可以工作
$ python application.py greet John --iterations=5 --yell
$ python application.py greet John --yell --iterations=5
测试命令
Cleo提供了一些工具来帮助您测试命令。其中最有用的是CommandTester
类。它使用特殊的IO类来简化测试,而无需真实的控制台
from greet_command import GreetCommand
from cleo.application import Application
from cleo.testers.command_tester import CommandTester
def test_execute():
application = Application()
application.add(GreetCommand())
command = application.find("greet")
command_tester = CommandTester(command)
command_tester.execute()
assert "..." == command_tester.io.fetch_output()
CommandTester.io.fetch_output()
方法返回在正常控制台调用期间将被显示的内容。CommandTester.io.fetch_error()
也可用,用于获取写入到stderr的内容。
您可以通过将参数和选项作为字符串传递给CommandTester.execute()
方法来测试向命令发送参数和选项
from greet_command import GreetCommand
from cleo.application import Application
from cleo.testers.command_tester import CommandTester
def test_execute():
application = Application()
application.add(GreetCommand())
command = application.find("greet")
command_tester = CommandTester(command)
command_tester.execute("John")
assert "John" in command_tester.io.fetch_output()
您还可以使用ApplicationTester
类来测试整个控制台应用程序。
调用现有命令
如果一个命令依赖于另一个命令先运行,而不是让用户记住执行顺序,您可以直接自己调用它。如果您想要创建一个仅运行其他命令的“元”命令,这也很有用。
从一个命令中调用另一个命令非常简单
def handle(self):
return_code = self.call("greet", "John --yell")
return return_code
如果您想抑制已执行命令的输出,可以使用call_silent()
方法。
自动补全
Cleo支持在bash
、zsh
和fish
中的自动(Tab)补全。
默认情况下,您的应用程序将有一个completions
命令。要在终端中注册这些补全命令,请运行以下之一(将[program]
替换为您运行应用程序的命令)
# Bash
[program] completions bash | sudo tee /etc/bash_completion.d/[program].bash-completion
# Bash - macOS/Homebrew (requires `brew install bash-completion`)
[program] completions bash > $(brew --prefix)/etc/bash_completion.d/[program].bash-completion
# Zsh
mkdir ~/.zfunc
echo "fpath+=~/.zfunc" >> ~/.zshrc
[program] completions zsh > ~/.zfunc/_[program]
# Zsh - macOS/Homebrew
[program] completions zsh > $(brew --prefix)/share/zsh/site-functions/_[program]
# Fish
[program] completions fish > ~/.config/fish/completions/[program].fish
项目详情
下载文件
下载适用于您的平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。