diff --git a/README.md b/README.md index c628c4e3..bcf2860f 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ from arclet.alconna import Alconna, Option, Subcommand, Args cmd = Alconna( "/pip", options=[ - Subcommand("install", [Option("-u| --upgrade")], Args.pak_name[str]), + Subcommand("install", [Option("-u|--upgrade")], Args.pak_name[str]), Option("list"), ] ) @@ -53,39 +53,42 @@ print(result.get('install')) # 或者 result.install QQ 交流群: [链接](https://jq.qq.com/?_wv=1027&k=PUPOnCSH) -## 用法 -通过阅读Alconna的签名可以得知,Alconna支持四大类参数: - - `headers` : 呼叫该命令的命令头,一般是你的机器人的名字或者符号,与command至少有一个填写. 例如: /, ! - - `command` : 命令名称,你的命令的名字,与headers至少有一个填写 - - `options` : 命令选项,你的命令可选择的所有option,是一个包含Subcommand与Option的列表 - - `main_args` : 主参数,填入后当且仅当命令中含有该参数时才会成功解析 +## 特点 +* 高效. 在 i5-10210U 处理器上, 性能大约为 `41000~101000 msg/s` +* 精简、多样的构造方法 +* 强大的自动类型转换功能 +* 可传入同步与异步的action函数 +* 高度自定义的HelpFormat、Analyser +* Duplication、FuzzyMatch等一众特性 -解析时,先判断命令头(即 headers + command),再判断options与main argument, 这里options与main argument在输入指令时是不分先后的 - -假设有个Alconna如下: +类型转换示范: ```python -Alconna( - command="name", - main_args="main_args", - headers=["/"], - options=[ - Subcommand( - "sub_name", - Option("sub_opt", sub_opt_arg="sub_arg"), - sub_main_arg="sub_main_arg" - ), - Option("opt", opt_arg="opt_arg") - ], +from arclet.alconna import Alconna, Args +from pathlib import Path + +read = Alconna( + "read", Args["data":bytes], + action=lambda data: print(type(data)) ) + +read.parse(["read", b'hello']) +read.parse("read test_fire.py") +read.parse(["read", Path("test_fire.py")]) + +''' + + + +''' ``` -则它可以解析如下命令: -``` -/name sub_name sub_opt sub_arg sub_main_arg opt arg main_args -/name sub_name sub_main_arg opt arg main_argument -/name main_args opt arg -/name main_args -``` -解析成功的命令的参数会保存在analysis_message方法返回的`Arpamar`实例中 -## 性能参考 -在 i5-10210U 处理器上, `Alconna` 的性能大约为 `31000~101000 msg/s`, 取决于 `Alconna` 的复杂程度 +模糊匹配示范: +```python +from arclet.alconna import Alconna +alc = Alconna('!test_fuzzy', "foo:str", is_fuzzy_match=True) +alc.parse("!test_fuzy foo bar") + +''' +!test_fuzy not matched. Are you mean "!test_fuzzy"? +''' +``` \ No newline at end of file diff --git a/changelog.md b/changelog.md index a4775d66..464d1b20 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,14 @@ +# Alconna 0.8.x: + +## Alconna 0.8.0: +1. `Option`的`alias`现在需要传入List[str],而不是str。 +2. `help_text`内置两个预选板块`Usage`和`Example`, 编写规则为`"xxx Usage:xxx; Example:xxx;"`。 +3. 加入`TypePattern`, 作用为简单的类型转换器, 其可以设置前置转换器, 即可以`str -> Path -> bytes`。 +4. 加入命令的模糊匹配, 在`Alconna`中传入`is_fuzzy_match`参数, 可以设置是否模糊匹配。 +5. `AlconnaString`参数规则修改, 现在``表示必选, `[xx]`表示可选, `&xx`表示action的值。 +6. `ArgparseHelpTextFormatter`相关格式修改 + + # Alconna 0.7.x: ## Alconna 0.7.0: @@ -87,13 +98,12 @@ 6. `Format`中的format slot可以直接写入类型, 如`"{name: str}"` 7. 修复Bug -## Alconna 0.7.7 - 0.7.7.2 +## Alconna 0.7.7 - 0.7.7.4 1. 加入`Argparser`风格的HelpFormatter 2. 加入`AlconnaDuplication`, 旨在提供更好的解析结果使用 3. option的name与alias现在会根据长度自动倒换 4. 修复Bug - # Alconna 0.6.x: ## Alconna 0.6.0: @@ -165,7 +175,6 @@ 2. 规范format方法;from_string现在可以用#加入帮助说明 3. 加入commandManager,帮助管理所有命令;支持解析原始消息链 - # Alconna 0.4.x ## Alconna 0.4.1: diff --git a/dev_tools/test_alconna_1.py b/dev_tools/test_alconna_1.py index 5679fe30..a11965da 100644 --- a/dev_tools/test_alconna_1.py +++ b/dev_tools/test_alconna_1.py @@ -5,6 +5,7 @@ from arclet.alconna.arpamar import Arpamar from arclet.alconna.types import AnyIP, AnyDigit, AnyStr, AnyParam from graia.ariadne.message.chain import MessageChain +from arclet.alconna.builtin.formatter import ArgParserHelpTextFormatter from graia.ariadne.message.element import At @@ -55,7 +56,8 @@ Option("--exists-action", Args["action":str], help_text="添加行为"), Option("--trusted-host", Args["host_name":"url"], help_text="选择可信赖地址") ], - help_text="简单的pip指令" + help_text="简单的pip指令", + formatter=ArgParserHelpTextFormatter() ) print(pip.get_help()) msg = "/pip install ces --upgrade -t 6 --trusted-host http://pypi.douban.com/simple" diff --git a/dev_tools/test_alconna_2.py b/dev_tools/test_alconna_2.py index 71780b3c..2a23a548 100644 --- a/dev_tools/test_alconna_2.py +++ b/dev_tools/test_alconna_2.py @@ -104,4 +104,10 @@ def test(wild, text: str, num: int, boolean: bool = False): print("alc12:", alc12.parse("test_str1 abcd 1234")) alc13 = Alconna("image", Args["@?--width":int:1920, "@?--height":int:1080]) -print("alc13:", alc13.parse("image --height=720")) \ No newline at end of file +print("alc13:", alc13.parse("image --height=720")) + +alc14 = Alconna(main_args="foo:str", headers=['!test_fuzzy'], is_fuzzy_match=True) +print(alc14.parse("test_fuzy foo bar")) + +alc15 = AlconnaString("my_string", "--foo [bar:bool]", "--bar &True") +print(alc15.parse("my_string --foo 123 --bar")) \ No newline at end of file diff --git a/dev_tools/test_help_formatter.py b/dev_tools/test_help_formatter.py index bc9026d2..150350cc 100644 --- a/dev_tools/test_help_formatter.py +++ b/dev_tools/test_help_formatter.py @@ -1,6 +1,6 @@ from arclet.alconna import Alconna, Args, Option, Subcommand from arclet.alconna.visitor import AlconnaNodeVisitor -from arclet.alconna.builtin.formatter import DefaultHelpTextFormatter +from arclet.alconna.builtin.formatter import DefaultHelpTextFormatter, ArgParserHelpTextFormatter alc = Alconna("test_line", main_args="line:'...'") @@ -21,4 +21,5 @@ ] ) ) -print(b.format_node(DefaultHelpTextFormatter(), b.require(["sub"]))) +print(b.format_node(DefaultHelpTextFormatter(), b.require([]))) +print(b.format_node(ArgParserHelpTextFormatter(), b.require([]))) diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..9122dcc2 --- /dev/null +++ b/setup.py @@ -0,0 +1,47 @@ +import setuptools + +with open("README.rst", "r", encoding='utf-8') as fh: + long_description = fh.read() + +setuptools.setup( + name="arclet-alconna", + version="0.8.0", + author="ArcletProject", + author_email="rf_tar_railt@qq.com", + description="A Fast Command Analyser based on Dict", + license='MIT', + long_description=long_description, + long_description_content_type="text/rst", + url="https://github.com/ArcletProject/Alconna", + packages=[ + 'arclet.alconna', + 'arclet.alconna.analysis', + 'arclet.alconna.builtin', + 'arclet.alconna.arpamar', + ], + entry_points={ + 'console_scripts': [ + 'alconna = arclet.alconna.__main__:main' + ] + }, + extras_require={ + 'graia': [ + 'arclet-alconna-graia', + ] + }, + classifiers=[ + "Development Status :: 4 - Beta", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Operating System :: OS Independent", + ], + keywords=['command', 'argparse', 'dict', 'fast', 'alconna', 'cli'], + python_requires='>=3.8', + project_urls={ + 'Documentation': 'https://arcletproject.github.io/docs/alconna/tutorial', + 'Bug Reports': 'https://github.com/ArcletProject/Alconna/issues', + 'Source': 'https://github.com/ArcletProject/Alconna', + }, +)