From 327f3fa441ee049e906c716775458bec81356ee0 Mon Sep 17 00:00:00 2001
From: Tarrailt <3165388245@qq.com>
Date: Fri, 4 Aug 2023 17:32:43 +0800
Subject: [PATCH] =?UTF-8?q?:memo:=20Docs:=20=E6=9B=B4=E6=96=B0=E6=9C=80?=
=?UTF-8?q?=E4=BD=B3=E5=AE=9E=E8=B7=B5=E9=83=A8=E5=88=86=E7=9A=84=20Alconn?=
=?UTF-8?q?a=20=E7=AB=A0=E8=8A=82=20(#2237)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
---
website/docs/advanced/matcher.md | 2 +-
website/docs/best-practice/alconna.md | 288 --------------
website/docs/best-practice/alconna/README.mdx | 120 ++++++
.../best-practice/alconna/_category_.json | 4 +
website/docs/best-practice/alconna/alconna.md | 372 ++++++++++++++++++
website/docs/best-practice/alconna/config.md | 34 ++
website/docs/best-practice/alconna/matcher.md | 238 +++++++++++
7 files changed, 769 insertions(+), 289 deletions(-)
delete mode 100644 website/docs/best-practice/alconna.md
create mode 100644 website/docs/best-practice/alconna/README.mdx
create mode 100644 website/docs/best-practice/alconna/_category_.json
create mode 100644 website/docs/best-practice/alconna/alconna.md
create mode 100644 website/docs/best-practice/alconna/config.md
create mode 100644 website/docs/best-practice/alconna/matcher.md
diff --git a/website/docs/advanced/matcher.md b/website/docs/advanced/matcher.md
index bd84196f..3d64131b 100644
--- a/website/docs/advanced/matcher.md
+++ b/website/docs/advanced/matcher.md
@@ -333,4 +333,4 @@ matcher2 = group.on_message()
基于 `Alconna` 的特性,该插件同时提供了一系列便捷的消息段标注。
标注可用于在 `Alconna` 中匹配消息中除 text 外的其他消息段,也可用于快速创建各适配器下的消息段。所有标注位于 `nonebot_plugin_alconna.adapters` 中。
-详情请阅读最佳实践中的 [命令解析拓展](../best-practice/alconna.md) 章节。
+详情请阅读最佳实践中的 [命令解析拓展](../best-practice/alconna/README.mdx) 章节。
diff --git a/website/docs/best-practice/alconna.md b/website/docs/best-practice/alconna.md
deleted file mode 100644
index a44dd656..00000000
--- a/website/docs/best-practice/alconna.md
+++ /dev/null
@@ -1,288 +0,0 @@
----
-sidebar_position: 6
-description: Alconna 命令解析拓展
----
-
-# Alconna 命令解析
-
-[`nonebot-plugin-alconna`](https://github.com/nonebot/plugin-alconna) 是一类提供了拓展响应规则的插件。
-该插件使用 [Alconna](https://github.com/ArcletProject/Alconna) 作为命令解析器,
-是一个简单、灵活、高效的命令参数解析器, 并且不局限于解析命令式字符串。
-
-特点包括:
-
-- 高效
-- 直观的命令组件创建方式
-- 强大的类型解析与类型转换功能
-- 自定义的帮助信息格式
-- 多语言支持
-- 易用的快捷命令创建与使用
-- 可创建命令补全会话, 以实现多轮连续的补全提示
-- 可嵌套的多级子命令
-- 正则匹配支持
-
-该插件提供了一类新的事件响应器辅助函数 `on_alconna`,以及 `AlconnaResult` 等依赖注入函数。
-
-同时,基于 [Annotated 支持](https://github.com/nonebot/nonebot2/pull/1832), 添加了两类注解 `AlcMatches` 与 `AlcResult`
-
-该插件还可以通过 `handle(parameterless)` 来控制一个具体的响应函数是否在不满足条件时跳过响应:
-
-- `pip.handle([Check(assign("add.name", "nb"))])` 表示仅在命令为 `role-group add` 并且 name 为 `nb` 时响应
-- `pip.handle([Check(assign("list"))])` 表示仅在命令为 `role-group list` 时响应
-- `pip.handle([Check(assign("add"))])` 表示仅在命令为 `role-group add` 时响应
-
-基于 `Alconna` 的特性,该插件同时提供了一系列便捷的消息段标注。
-标注可用于在 `Alconna` 中匹配消息中除 text 外的其他消息段,也可用于快速创建各适配器下的消息段。所有标注位于 `nonebot_plugin_alconna.adapters` 中。
-
-## 安装插件
-
-在使用前请先安装 `nonebot-plugin-alconna` 插件至项目环境中,可参考[获取商店插件](../tutorial/store.mdx#安装插件)来了解并选择安装插件的方式。如:
-
-在**项目目录**下执行以下命令:
-
-```shell
-nb plugin install nonebot-plugin-alconna
-```
-
-或
-
-```shell
-pip install nonebot-plugin-alconna
-```
-
-## 使用插件
-
-以下为一个简单的使用示例:
-
-```python
-from nonebot_plugin_alconna.adapters import At
-from nonebot.adapters.onebot.v12 import Message
-from nonebot_plugin_alconna.adapters.onebot12 import Image
-from nonebot_plugin_alconna import AlconnaMatches, on_alconna
-from nonebot.adapters.onebot.v12 import MessageSegment as Ob12MS
-from arclet.alconna import Args, Option, Alconna, Arparma, MultiVar, Subcommand
-
-alc = Alconna(
- ["/", "!"],
- "role-group",
- Subcommand(
- "add",
- Args["name", str],
- Option("member", Args["target", MultiVar(At)]),
- ),
- Option("list"),
-)
-rg = on_alconna(alc, auto_send_output=True)
-
-
-@rg.handle()
-async def _(result: Arparma = AlconnaMatches()):
- if result.find("list"):
- img = await gen_role_group_list_image()
- await rg.finish(Message([Image(img)]))
- if result.find("add"):
- group = await create_role_group(result["add.name"])
- if result.find("add.member"):
- ats: tuple[Ob12MS, ...] = result["add.member.target"]
- group.extend(member.data["user_id"] for member in ats)
- await rg.finish("添加成功")
-```
-
-### 导入插件
-
-由于 `nonebot-plugin-alconna` 作为插件,因此需要在使用前对其进行**加载**并**导入**其中的 `on_alconna` 来使用命令拓展。使用 `require` 方法可轻松完成这一过程,可参考 [跨插件访问](../advanced/requiring.md) 一节进行了解。
-
-```python
-from nonebot import require
-
-require("nonebot_plugin_alconna")
-
-from nonebot_plugin_alconna import on_alconna
-```
-
-### 命令编写
-
-我们可以看到主要的两大组件:`Option` 与 `Subcommand`。
-
-`Option` 可以传入一组别名,如 `Option("--foo|-F|--FOO|-f")` 或 `Option("--foo", alias=["-F"]`
-
-`Subcommand` 则可以传入自己的 `Option` 与 `Subcommand`:
-
-他们拥有如下共同参数:
-
-- `help_text`: 传入该组件的帮助信息
-- `dest`: 被指定为解析完成时标注匹配结果的标识符,不传入时默认为选项或子命令的名称 (name)
-- `requires`: 一段指定顺序的字符串列表,作为唯一的前置序列与命令嵌套替换
-- `default`: 默认值,在该组件未被解析时使用使用该值替换。
-
-然后是 `Args` 与 `MultiVar`,他们是用于解析参数的组件。
-
-`Args` 是参数解析的基础组件,构造方法形如 `Args["foo", str]["bar", int]["baz", bool, False]`,
-与函数签名类似,但是允许含有默认值的参数在前;同时支持 keyword-only 参数不依照构造顺序传入 (但是仍需要在非 keyword-only 参数之后)。
-
-`MultiVar` 则是一个特殊的标注,用于告知解析器该参数可以接受多个值,其构造方法形如 `MultiVar(str)`。
-同样的还有 `KeyWordVar`,其构造方法形如 `KeyWordVar(str)`,用于告知解析器该参数为一个 keyword-only 参数。
-
-:::tip
-`MultiVar` 与 `KeyWordVar` 组合时,代表该参数为一个可接受多个 key-value 的参数,其构造方法形如 `MultiVar(KeyWordVar(str))`
-
-`MultiVar` 与 `KeyWordVar` 也可以传入 `default` 参数,用于指定默认值。
-
-`MultiVar` 不能在 `KeyWordVar` 之后传入。
-:::
-
-### 参数标注
-
-`Args` 的参数类型表面上看需要传入一个 `type`,但实际上它需要的是一个 `nepattern.BasePattern` 的实例。
-
-```python
-from arclet.alconna import Args
-from nepattern import BasePattern
-
-# 表示 foo 参数需要匹配一个 @number 样式的字符串
-args = Args["foo", BasePattern("@\d+")]
-```
-
-示例中传入的 `str` 是因为 `str` 已经注册在了 `nepattern.global_patterns` 中,因此会替换为 `nepattern.global_patterns[str]`。
-
-默认支持的类型有:
-
-- `str`: 匹配任意字符串
-- `int`: 匹配整数
-- `float`: 匹配浮点数
-- `bool`: 匹配 `True` 与 `False` 以及他们小写形式
-- `hex`: 匹配 `0x` 开头的十六进制字符串
-- `url`: 匹配网址
-- `email`: 匹配 `xxxx@xxx` 的字符串
-- `ipv4`: 匹配 `xxx.xxx.xxx.xxx` 的字符串
-- `list`: 匹配类似 `["foo","bar","baz"]` 的字符串
-- `dict`: 匹配类似 `{"foo":"bar","baz":"qux"}` 的字符串
-- `datetime`: 传入一个 `datetime` 支持的格式字符串,或时间戳
-- `Any`: 匹配任意类型
-- `AnyString`: 匹配任意类型,转为 `str`
-- `Number`: 匹配 `int` 与 `float`,转为 `int`
-
-同时可以使用 typing 中的类型:
-
-- `Literal[X]`: 匹配其中的任意一个值
-- `Union[X, Y]`: 匹配其中的任意一个类型
-- `Optional[xxx]`: 会自动将默认值设为 `None`,并在解析失败时使用默认值
-- `List[X]`: 匹配一个列表,其中的元素为 `X` 类型
-- `Dict[X, Y]`: 匹配一个字典,其中的 key 为 `X` 类型,value 为 `Y` 类型
-- ...
-
-:::tip
-几类特殊的传入标记:
-
-- `"foo"`: 匹配字符串 "foo" (若没有某个 `BasePattern` 与之关联)
-- `RawStr("foo")`: 匹配字符串 "foo" (不会被 `BasePattern` 替换)
-- `"foo|bar|baz"`: 匹配 "foo" 或 "bar" 或 "baz"
-- `[foo, bar, Baz, ...]`: 匹配其中的任意一个值或类型
-- `Callable[[X], Y]`: 匹配一个参数为 `X` 类型的值,并返回通过该函数调用得到的 `Y` 类型的值
-- `"re:xxx"`: 匹配一个正则表达式 `xxx`,会返回 Match[0]
-- `"rep:xxx"`: 匹配一个正则表达式 `xxx`,会返回 `re.Match` 对象
-- `{foo: bar, baz: qux}`: 匹配字典中的任意一个键, 并返回对应的值 (特殊的键 ... 会匹配任意的值)
-- ...
-
-:::
-
-### 消息段标注
-
-示例中使用了消息段标注,其中 `At` 属于通用标注,而 `Image` 属于 `onebot12` 适配器下的标注。
-
-消息段标注会匹配特定的 `MessageSegment`:
-
-```python
-...
-ats: tuple[Ob12MS, ...] = result["add.member.target"]
-group.extend(member.data["user_id"] for member in ats)
-```
-
-:::tip
-通用标注与适配器标注的区别在于,通用标注会匹配多个适配器中相似类型的消息段。
-
-通用标注返回的是 `nonebot_plugin_alconna.adapters` 中定义的 `Segment` 模型:
-
-```python
-class Segment:
- """基类标注"""
- origin: MessageSegment
-
-class At(Segment):
- """At对象, 表示一类提醒某用户的元素"""
- target: str
-
-class Emoji(Segment):
- """Emoji对象, 表示一类表情元素"""
- id: str
- name: Optional[str]
-
-class Media(Segment):
- url: Optional[str]
- id: Optional[str]
-
-class Image(Media):
- """Image对象, 表示一类图片元素"""
-
-class Audio(Media):
- """Audio对象, 表示一类音频元素"""
-
-class Voice(Media):
- """Voice对象, 表示一类语音元素"""
-
-class Video(Media):
- """Video对象, 表示一类视频元素"""
-
-class File(Segment):
- """File对象, 表示一类文件元素"""
- id: str
- name: Optional[str] = field(default=None)
-```
-
-:::
-
-### 响应器使用
-
-`on_alconna` 的所有参数如下:
-
-- `command: Alconna | str`: Alconna 命令
-- `skip_for_unmatch: bool = True`: 是否在命令不匹配时跳过该响应
-- `auto_send_output: bool = False`: 是否自动发送输出信息并跳过响应
-- `output_converter: TConvert | None = None`: 输出信息字符串转换为消息序列方法
-- `aliases: set[str | tuple[str, ...]] | None = None`: 命令别名, 作用类似于 `on_command` 中的 aliases
-- `comp_config: CompConfig | None = None`: 补全会话配置, 不传入则不启用补全会话
-
-`AlconnaMatches` 是一个依赖注入函数,可注入 `Alconna` 命令解析结果。
-
-### 配置项
-
-#### alconna_auto_send_output
-
-- **类型**: `bool`
-- **默认值**: `False`
-
-"是否全局启用输出信息自动发送,不启用则会在触特殊内置选项后仍然将解析结果传递至响应器。
-
-#### alconna_use_command_start
-
-- **类型**: `bool`
-- **默认值**: `False`
-
-是否读取 Nonebot 的配置项 `COMMAND_START` 来作为全局的 Alconna 命令前缀
-
-#### alconna_auto_completion
-
-- **类型**: `bool`
-- **默认值**: `False`
-
-是否全局启用命令自动补全,启用后会在参数缺失或触发 `--comp` 选项时自自动启用交互式补全。
-
-## 文档参考
-
-插件文档: [📦 这里](https://github.com/nonebot/plugin-alconna/blob/master/docs.md)
-
-官方文档: [👉 指路](https://arclet.top/)
-
-QQ 交流群: [🔗 链接](https://jq.qq.com/?_wv=1027&k=PUPOnCSH)
-
-友链: [📚 文档](https://graiax.cn/guide/message_parser/alconna.html)
diff --git a/website/docs/best-practice/alconna/README.mdx b/website/docs/best-practice/alconna/README.mdx
new file mode 100644
index 00000000..9b8805eb
--- /dev/null
+++ b/website/docs/best-practice/alconna/README.mdx
@@ -0,0 +1,120 @@
+---
+sidebar_position: 1
+description: Alconna 命令解析拓展
+
+slug: /best-practice/alconna/
+---
+
+# Alconna 插件
+
+[`nonebot-plugin-alconna`](https://github.com/nonebot/plugin-alconna) 是一类提供了拓展响应规则的插件。
+该插件使用 [Alconna](https://github.com/ArcletProject/Alconna) 作为命令解析器,
+是一个简单、灵活、高效的命令参数解析器, 并且不局限于解析命令式字符串。
+
+该插件提供了一类新的事件响应器辅助函数 `on_alconna`,以及 `AlconnaResult` 等依赖注入函数。
+
+同时,基于 [Annotated 支持](https://github.com/nonebot/nonebot2/pull/1832), 添加了两类注解 `AlcMatches` 与 `AlcResult`
+
+该插件还可以通过 `handle(parameterless)` 来控制一个具体的响应函数是否在不满足条件时跳过响应:
+
+- `pip.handle([Check(assign("add.name", "nb"))])` 表示仅在命令为 `role-group add` 并且 name 为 `nb` 时响应
+- `pip.handle([Check(assign("list"))])` 表示仅在命令为 `role-group list` 时响应
+- `pip.handle([Check(assign("add"))])` 表示仅在命令为 `role-group add` 时响应
+
+基于 `Alconna` 的特性,该插件同时提供了一系列便捷的消息段标注。
+标注可用于在 `Alconna` 中匹配消息中除 text 外的其他消息段,也可用于快速创建各适配器下的消息段。所有标注位于 `nonebot_plugin_alconna.adapters` 中。
+
+## 安装插件
+
+在使用前请先安装 `nonebot-plugin-alconna` 插件至项目环境中,可参考[获取商店插件](../../tutorial/store.mdx#安装插件)来了解并选择安装插件的方式。如:
+
+在**项目目录**下执行以下命令:
+
+```shell
+nb plugin install nonebot-plugin-alconna
+```
+
+或
+
+```shell
+pip install nonebot-plugin-alconna
+```
+
+## 导入插件
+
+由于 `nonebot-plugin-alconna` 作为插件,因此需要在使用前对其进行**加载**并**导入**其中的 `on_alconna` 来使用命令拓展。使用 `require` 方法可轻松完成这一过程,可参考 [跨插件访问](../../advanced/requiring.md) 一节进行了解。
+
+```python
+from nonebot import require
+
+require("nonebot_plugin_alconna")
+
+from nonebot_plugin_alconna import on_alconna
+```
+
+## 使用插件
+
+在前面的[深入指南](../../appendices/session-control.mdx)中,我们已经得到了一个天气插件。
+现在我们将使用 `Alconna` 来改写这个插件。
+
+
+ 插件示例
+
+```python title=weather/__init__.py
+from nonebot import on_command
+from nonebot.rule import to_me
+from nonebot.matcher import Matcher
+from nonebot.adapters import Message
+from nonebot.params import CommandArg, ArgPlainText
+
+weather = on_command("天气", rule=to_me(), aliases={"weather", "天气预报"})
+
+@weather.handle()
+async def handle_function(matcher: Matcher, args: Message = CommandArg()):
+ if args.extract_plain_text():
+ matcher.set_arg("location", args)
+
+@weather.got("location", prompt="请输入地名")
+async def got_location(location: str = ArgPlainText()):
+ if location not in ["北京", "上海", "广州", "深圳"]:
+ await weather.reject(f"你想查询的城市 {location} 暂不支持,请重新输入!")
+ await weather.finish(f"今天{location}的天气是...")
+```
+
+
+
+```python {5-8,11-13,15-16}
+from nonebot.rule import to_me
+from arclet.alconna import Alconna, Args
+from nonebot_plugin_alconna import Match, AlconnaMatch, on_alconna, AlconnaMatcher, AlconnaArg
+
+weather = on_alconna(
+ Alconna(["天气", "weather", "天气预报"], Args["location?", str]),
+ rule=to_me(),
+)
+
+@weather.handle()
+async def handle_function(matcher: AlconnaMatcher, location: Match[str] = AlconnaMatch("location")):
+ if location.available:
+ matcher.set_path_arg("location", location.value)
+
+@weather.got_path("location", prompt="请输入地名")
+async def got_location(location: str = AlconnaArg("location")):
+ if location not in ["北京", "上海", "广州", "深圳"]:
+ await weather.reject(f"你想查询的城市 {location} 暂不支持,请重新输入!")
+ await weather.finish(f"今天{location}的天气是...")
+```
+
+在上面的代码中,我们使用 `Alconna` 来解析命令,`on_alconna` 用来创建响应器,使用 `AlconnaMatch` 来获取解析结果。
+
+关于更多 `Alconna` 的使用方法,可参考 [Alconna 文档](https://arclet.top/docs/tutorial/alconna),
+或阅读 [Alconna 基本介绍](./alconna.md) 一节。
+
+关于更多 `on_alconna` 的使用方法,可参考 [插件文档](https://github.com/nonebot/plugin-alconna/blob/master/docs.md),
+或阅读 [响应规则的使用](./matcher.md) 一节。
+
+## 交流与反馈
+
+QQ 交流群: [🔗 链接](https://jq.qq.com/?_wv=1027&k=PUPOnCSH)
+
+友链: [📚 文档](https://graiax.cn/guide/message_parser/alconna.html)
diff --git a/website/docs/best-practice/alconna/_category_.json b/website/docs/best-practice/alconna/_category_.json
new file mode 100644
index 00000000..d8e7367f
--- /dev/null
+++ b/website/docs/best-practice/alconna/_category_.json
@@ -0,0 +1,4 @@
+{
+ "label": "Alconna 命令解析拓展",
+ "position": 6
+}
diff --git a/website/docs/best-practice/alconna/alconna.md b/website/docs/best-practice/alconna/alconna.md
new file mode 100644
index 00000000..5f3d8805
--- /dev/null
+++ b/website/docs/best-practice/alconna/alconna.md
@@ -0,0 +1,372 @@
+---
+sidebar_position: 2
+description: Alconna 基本介绍
+---
+
+# Alconna 命令解析
+
+[Alconna](https://github.com/ArcletProject/Alconna) 作为命令解析器,
+是一个简单、灵活、高效的命令参数解析器, 并且不局限于解析命令式字符串。
+
+特点包括:
+
+- 高效
+- 直观的命令组件创建方式
+- 强大的类型解析与类型转换功能
+- 自定义的帮助信息格式
+- 多语言支持
+- 易用的快捷命令创建与使用
+- 可创建命令补全会话, 以实现多轮连续的补全提示
+- 可嵌套的多级子命令
+- 正则匹配支持
+
+## 命令编写
+
+### 命令头
+
+命令头是指命令的前缀 (Prefix) 与命令名 (Command) 的组合,例如 `!help` 中的 `!` 与 `help`。
+
+在 Alconna 中,你可以传入多种类型的命令头,例如:
+
+| 前缀 | 命令名 | 匹配内容 | 说明 |
+| :--------------------------: | :--------: | :---------------------------------------------------------: | :--------------: |
+| - | "foo" | `"foo"` | 无前缀的纯文字头 |
+| - | 123 | `123` | 无前缀的元素头 |
+| - | "re:\d{2}" | `"32"` | 无前缀的正则头 |
+| - | int | `123` 或 `"456"` | 无前缀的类型头 |
+| [int, bool] | - | `True` 或 `123` | 无名的元素类头 |
+| ["foo", "bar"] | - | `"foo"` 或 `"bar"` | 无名的纯文字头 |
+| ["foo", "bar"] | "baz" | `"foobaz"` 或 `"barbaz"` | 纯文字头 |
+| [int, bool] | "foo" | `[123, "foo"]` 或 `[False, "foo"]` | 类型头 |
+| [123, 4567] | "foo" | `[123, "foo"]` 或 `[4567, "foo"]` | 元素头 |
+| [nepattern.NUMBER] | "bar" | `[123, "bar"]` 或 `[123.456, "bar"]` | 表达式头 |
+| [123, "foo"] | "bar" | `[123, "bar"]` 或 `"foobar"` 或 `["foo", "bar"]` | 混合头 |
+| [(int, "foo"), (456, "bar")] | "baz" | `[123, "foobaz"]` 或 `[456, "foobaz"]` 或 `[456, "barbaz"]` | 对头 |
+
+其中
+
+- 元素头:只会匹配对应的值,例如 `[123, 456]` 只会匹配 `123` 或 `456`,不会匹配 `789`。
+- 纯文字头:只会匹配对应的字符串,例如 `["foo", "bar"]` 只会匹配 `"foo"` 或 `"bar"`,不会匹配 `"baz"`。
+- 正则头:`re:xxx` 会将 `xxx` 转为正则表达式,然后匹配对应的字符串,例如 `re:\d{2}` 只会匹配 `"12"` 或 `"34"`,不会匹配 `"foo"`。
+ **正则只在命令名上生效,命令前缀中的正则会被转义**。
+- 类型头:只会匹配对应的类型,例如 `[int, bool]` 只会匹配 `123` 或 `True`,不会匹配 `"foo"`。
+ - 无前缀的类型头:此时会将传入的值尝试转为 BasePattern,例如 `int` 会转为 `nepattern.INTEGER`。此时命令头会匹配对应的类型,
+ 例如 `int` 会匹配 `123` 或 `"456"`,但不会匹配 `"foo"`。同时,Alconna 会将命令头匹配到的值转为对应的类型,例如 `int` 会将 `"123"` 转为 `123`。
+- 表达式头:只会匹配对应的表达式,例如 `[nepattern.NUMBER]` 只会匹配 `123` 或 `123.456`,不会匹配 `"foo"`。
+- 混合头:
+
+除了通过传入 `re:xxx` 来使用正则表达式外,Alconna 还提供了一种更加简洁的方式来使用正则表达式,那就是 Bracket Header。
+
+```python
+from alconna import Alconna
+
+alc = Alconna(".rd{roll:int}")
+assert alc.parse(".rd123").header["roll"] == 123
+```
+
+### 组件
+
+我们可以看到主要的两大组件:`Option` 与 `Subcommand`。
+
+`Option` 可以传入一组 `alias`,如 `Option("--foo|-F|--FOO|-f")` 或 `Option("--foo", alias=["-F"])`
+
+传入别名后,Option 会选择其中长度最长的作为选项名称。若传入为 "--foo|-f",则命令名称为 "--foo"。
+
+`Subcommand` 则可以传入自己的 **Option** 与 **Subcommand**。
+
+他们拥有如下共同参数:
+
+- `help_text`: 传入该组件的帮助信息
+- `dest`: 被指定为解析完成时标注匹配结果的标识符,不传入时默认为选项或子命令的名称 (name)
+- `requires`: 一段指定顺序的字符串列表,作为唯一的前置序列与命令嵌套替换
+ 对于命令 `test foo bar baz qux ` 来讲,因为`foo bar baz` 仅需要判断是否相等, 所以可以这么编写:
+
+ ```python
+ Alconna("test", Option("qux", Args.a[int], requires=["foo", "bar", "baz"]))
+ ```
+
+- `default`: 默认值,在该组件未被解析时使用使用该值替换。
+
+ 特别的,使用 `OptionResult` 或 `SubcomanndResult` 可以设置包括参数字典在内的默认值:
+
+ ```python
+ from arclet.alconna import Option, OptionResult
+
+ opt1 = Option("--foo", default=False)
+ opt2 = Option("--foo", default=OptionResult(value=False, args={"bar": 1}))
+ ```
+
+### 选项操作
+
+`Option` 可以特别设置传入一类 `Action`,作为解析操作
+
+`Action` 分为三类:
+
+- `store`: 无 Args 时, 仅存储一个值, 默认为 Ellipsis; 有 Args 时, 后续的解析结果会覆盖之前的值
+- `append`: 无 Args 时, 将多个值存为列表, 默认为 Ellipsis; 有 Args 时, 每个解析结果会追加到列表中
+
+ 当存在默认值并且不为列表时, 会自动将默认值变成列表, 以保证追加的正确性
+
+- `count`: 无 Args 时, 计数器加一; 有 Args 时, 表现与 STORE 相同
+
+ 当存在默认值并且不为数字时, 会自动将默认值变成 1, 以保证计数器的正确性。
+
+`Alconna` 提供了预制的几类 `action`:
+
+- `store`,`store_value`,`store_true`,`store_false`
+- `append`,`append_value`
+- `count`
+
+### 参数声明
+
+`Args` 是用于声明命令参数的组件。
+
+`Args` 是参数解析的基础组件,构造方法形如 `Args["foo", str]["bar", int]["baz", bool, False]`,
+与函数签名类似,但是允许含有默认值的参数在前;同时支持 keyword-only 参数不依照构造顺序传入 (但是仍需要在非 keyword-only 参数之后)。
+
+`Args` 中的 `name` 是用以标记解析出来的参数并存放于 **Arparma** 中,以方便用户调用。
+
+其有三种为 Args 注解的标识符: `?`、`/` 与 `!`。标识符与 key 之间建议以 `;` 分隔:
+
+- `!` 标识符表示该处传入的参数应不是规定的类型,或不在指定的值中。
+- `?` 标识符表示该参数为可选参数,会在无参数匹配时跳过。
+- `/` 标识符表示该参数的类型注解需要隐藏。
+
+另外,对于参数的注释也可以标记在 `name` 中,其与 name 或者标识符 以 `#` 分割:
+
+`foo#这是注释;?` 或 `foo?#这是注释`
+
+:::tip
+`Args` 中的 `name` 在实际命令中并不需要传入(keyword 参数除外):
+
+```python
+from arclet.alconna import Alconna, Args
+
+alc = Alconna("test", Args["foo", str])
+alc.parse("test --foo abc") # 错误
+alc.parse("test abc") # 之前
+```
+
+若需要 `test --foo abc`,你应该使用 `Option`:
+
+```python
+from arclet.alconna import Alconna, Args, Option
+
+alc = Alconna("test", Option("--foo", Args["foo", str]))
+```
+
+:::
+
+`Args` 的参数类型表面上看需要传入一个 `type`,但实际上它需要的是一个 `nepattern.BasePattern` 的实例。
+
+```python
+from arclet.alconna import Args
+from nepattern import BasePattern
+
+# 表示 foo 参数需要匹配一个 @number 样式的字符串
+args = Args["foo", BasePattern("@\d+")]
+```
+
+示例中传入的 `str` 是因为 `str` 已经注册在了 `nepattern.global_patterns` 中,因此会替换为 `nepattern.global_patterns[str]`。
+
+默认支持的类型有:
+
+- `str`: 匹配任意字符串
+- `int`: 匹配整数
+- `float`: 匹配浮点数
+- `bool`: 匹配 `True` 与 `False` 以及他们小写形式
+- `hex`: 匹配 `0x` 开头的十六进制字符串
+- `url`: 匹配网址
+- `email`: 匹配 `xxxx@xxx` 的字符串
+- `ipv4`: 匹配 `xxx.xxx.xxx.xxx` 的字符串
+- `list`: 匹配类似 `["foo","bar","baz"]` 的字符串
+- `dict`: 匹配类似 `{"foo":"bar","baz":"qux"}` 的字符串
+- `datetime`: 传入一个 `datetime` 支持的格式字符串,或时间戳
+- `Any`: 匹配任意类型
+- `AnyString`: 匹配任意类型,转为 `str`
+- `Number`: 匹配 `int` 与 `float`,转为 `int`
+
+同时可以使用 typing 中的类型:
+
+- `Literal[X]`: 匹配其中的任意一个值
+- `Union[X, Y]`: 匹配其中的任意一个类型
+- `Optional[xxx]`: 会自动将默认值设为 `None`,并在解析失败时使用默认值
+- `List[X]`: 匹配一个列表,其中的元素为 `X` 类型
+- `Dict[X, Y]`: 匹配一个字典,其中的 key 为 `X` 类型,value 为 `Y` 类型
+- ...
+
+:::tip
+几类特殊的传入标记:
+
+- `"foo"`: 匹配字符串 "foo" (若没有某个 `BasePattern` 与之关联)
+- `RawStr("foo")`: 匹配字符串 "foo" (不会被 `BasePattern` 替换)
+- `"foo|bar|baz"`: 匹配 "foo" 或 "bar" 或 "baz"
+- `[foo, bar, Baz, ...]`: 匹配其中的任意一个值或类型
+- `Callable[[X], Y]`: 匹配一个参数为 `X` 类型的值,并返回通过该函数调用得到的 `Y` 类型的值
+- `"re:xxx"`: 匹配一个正则表达式 `xxx`,会返回 Match[0]
+- `"rep:xxx"`: 匹配一个正则表达式 `xxx`,会返回 `re.Match` 对象
+- `{foo: bar, baz: qux}`: 匹配字典中的任意一个键, 并返回对应的值 (特殊的键 ... 会匹配任意的值)
+- ...
+
+:::
+
+`MultiVar` 则是一个特殊的标注,用于告知解析器该参数可以接受多个值,其构造方法形如 `MultiVar(str)`。
+同样的还有 `KeyWordVar`,其构造方法形如 `KeyWordVar(str)`,用于告知解析器该参数为一个 keyword-only 参数。
+
+:::tip
+`MultiVar` 与 `KeyWordVar` 组合时,代表该参数为一个可接受多个 key-value 的参数,其构造方法形如 `MultiVar(KeyWordVar(str))`
+
+`MultiVar` 与 `KeyWordVar` 也可以传入 `default` 参数,用于指定默认值。
+
+`MultiVar` 不能在 `KeyWordVar` 之后传入。
+:::
+
+### 紧凑命令
+
+`Alconna`, `Option` 与 `Subcommand` 可以设置 `compact=True` 使得解析命令时允许名称与后随参数之间没有分隔:
+
+```python
+from arclet.alconna import Alconna, Option, CommandMeta, Args
+
+alc = Alconna("test", Args["foo", int], Option("BAR", Args["baz", str], compact=True), meta=CommandMeta(compact=True))
+
+assert alc.parse("test123 BARabc").matched
+```
+
+这使得我们可以实现如下命令:
+
+```python
+>>> from arclet.alconna import Alconna, Option, Args, append
+>>> alc = Alconna("gcc", Option("--flag|-F", Args["content", str], action=append))
+>>> alc.parse("gcc -Fabc -Fdef -Fxyz").query("flag.content")
+['abc', 'def', 'xyz']
+```
+
+当 `Option` 的 `action` 为 `count` 时,其自动支持 `compact` 特性:
+
+```python
+>>> from arclet.alconna import Alconna, Option, Args, count
+>>> alc = Alconna("pp", Option("--verbose|-v", action=count, default=0))
+>>> alc.parse("pp -vvv").query("verbose.value")
+3
+```
+
+## 命令特性
+
+### 配置
+
+`arclet.alconna.Namespace` 表示某一命名空间下的默认配置:
+
+```python
+from arclet.alconna import config, namespace, Namespace
+from arclet.alconna.tools import ShellTextFormatter
+
+
+np = Namespace("foo", prefixes=["/"]) # 创建 Namespace 对象,并进行初始配置
+
+with namespace("bar") as np1:
+ np1.prefixes = ["!"] # 以上下文管理器方式配置命名空间,此时配置会自动注入上下文内创建的命令
+ np1.formatter_type = ShellTextFormatter # 设置此命名空间下的命令的 formatter 默认为 ShellTextFormatter
+ np1.builtin_option_name["help"] = {"帮助", "-h"} # 设置此命名空间下的命令的帮助选项名称
+
+config.namespaces["foo"] = np # 将命名空间挂载到 config 上
+```
+
+同时也提供了默认命名空间配置与修改方法:
+
+```python
+from arclet.alconna import config, namespace, Namespace
+
+
+config.default_namespace.prefixes = [...] # 直接修改默认配置
+
+np = Namespace("xxx", prefixes=[...])
+config.default_namespace = np # 更换默认的命名空间
+
+with namespace(config.default_namespace.name) as np:
+ np.prefixes = [...]
+```
+
+### 半自动补全
+
+半自动补全为用户提供了推荐后续输入的功能。
+
+补全默认通过 `--comp` 或 `-cp` 触发:(命名空间配置可修改名称)
+
+```python
+from arclet.alconna import Alconna, Args, Option
+
+alc = Alconna("test", Args["abc", int]) + Option("foo") + Option("bar")
+alc.parse("test --comp")
+
+'''
+output
+
+以下是建议的输入:
+*
+* --help
+* -h
+* -sct
+* --shortcut
+* foo
+* bar
+'''
+```
+
+### 快捷指令
+
+快捷指令顾名思义,可以为基础指令创建便捷的触发方式
+
+一般情况下你可以通过 `Alconna.shortcut` 进行快捷指令操作 (创建,删除);
+
+```python
+>>> from arclet.alconna import Alconna, Args
+>>> alc = Alconna("setu", Args["count", int])
+>>> alc.shortcut("涩图(\d+)张", {"args": ["{0}"]})
+'Alconna::setu 的快截指令: "涩图(\\d+)张" 添加成功'
+>>> alc.parse("涩图3张").query("count")
+3
+```
+
+`shortcut` 的第一个参数为快捷指令名称,第二个参数为 `ShortcutArgs`,作为快捷指令的配置
+
+```python
+class ShortcutArgs(TypedDict, Generic[TDC]):
+ """快捷指令参数"""
+
+ command: NotRequired[TDC]
+ """快捷指令的命令"""
+ args: NotRequired[list[Any]]
+ """快捷指令的附带参数"""
+ fuzzy: NotRequired[bool]
+ """是否允许命令后随参数"""
+```
+
+当 `fuzzy` 为 False 时,传入 `"涩图1张 abc"` 之类的快捷指令将视为解析失败
+
+快捷指令允许三类特殊的 placeholder:
+
+- `{%X}`: 只用于 `command`, 如 `setu {%0}`,表示此处填入快截指令后随的第 X 个参数。
+
+ 例如,若快捷指令为 `涩图`, 配置为 `{"command": "setu {%0}"}`, 则指令 `涩图 1` 相当于 `setu 1`
+
+- `{*}`: 只用于 `command`, 表示此处填入所有后随参数,并且可以通过 `{*X}` 的方式指定组合参数之间的分隔符。
+- `{X}`: 用于 `command` 与 `args`, 表示此处填入可能的正则匹配的组:
+ - 若 `command` 中存在匹配组 `(xxx)`,则 `{X}` 表示第 X 个匹配组的内容
+ - 若 `command` 中存储匹配组 `(?P...)`, 则 `{X}` 表示名字为 X 的匹配结果
+
+除此之外, 通过内置选项 `--shortcut` 可以动态操作快捷指令。
+
+### 使用模糊匹配
+
+模糊匹配通过在 Alconna 中设置其 CommandMeta 开启。
+
+模糊匹配会应用在任意需要进行名称判断的地方,如**命令名称**,**选项名称**和**参数名称**(如指定需要传入参数名称)。
+
+```python
+from arclet.alconna import Alconna, CommandMeta
+
+alc = Alconna("test_fuzzy", meta=CommandMeta(fuzzy_match=True))
+alc.parse("test_fuzy")
+# output: test_fuzy is not matched. Do you mean "test_fuzzy"?
+```
diff --git a/website/docs/best-practice/alconna/config.md b/website/docs/best-practice/alconna/config.md
new file mode 100644
index 00000000..65595277
--- /dev/null
+++ b/website/docs/best-practice/alconna/config.md
@@ -0,0 +1,34 @@
+---
+sidebar_position: 4
+description: 配置项
+---
+
+# 配置项
+
+## alconna_auto_send_output
+
+- **类型**: `bool`
+- **默认值**: `False`
+
+"是否全局启用输出信息自动发送,不启用则会在触特殊内置选项后仍然将解析结果传递至响应器。
+
+## alconna_use_command_start
+
+- **类型**: `bool`
+- **默认值**: `False`
+
+是否读取 Nonebot 的配置项 `COMMAND_START` 来作为全局的 Alconna 命令前缀
+
+## alconna_auto_completion
+
+- **类型**: `bool`
+- **默认值**: `False`
+
+是否全局启用命令自动补全,启用后会在参数缺失或触发 `--comp` 选项时自自动启用交互式补全。
+
+## alconna_use_origin
+
+- **类型**: `bool`
+- **默认值**: `False`
+
+是否全局使用原始消息 (即未经过 to_me 等处理的), 该选项会影响到 Alconna 的匹配行为。
diff --git a/website/docs/best-practice/alconna/matcher.md b/website/docs/best-practice/alconna/matcher.md
new file mode 100644
index 00000000..e51aec5e
--- /dev/null
+++ b/website/docs/best-practice/alconna/matcher.md
@@ -0,0 +1,238 @@
+---
+sidebar_position: 3
+description: 响应规则的使用
+---
+
+# Alconna 响应规则
+
+以下为一个简单的使用示例:
+
+```python
+from nonebot_plugin_alconna.adapters import At
+from nonebot.adapters.onebot.v12 import Message
+from nonebot_plugin_alconna.adapters.onebot12 import Image
+from nonebot_plugin_alconna import AlconnaMatches, on_alconna
+from nonebot.adapters.onebot.v12 import MessageSegment as Ob12MS
+from arclet.alconna import Args, Option, Alconna, Arparma, MultiVar, Subcommand
+
+alc = Alconna(
+ ["/", "!"],
+ "role-group",
+ Subcommand(
+ "add",
+ Args["name", str],
+ Option("member", Args["target", MultiVar(At)]),
+ ),
+ Option("list"),
+)
+rg = on_alconna(alc, auto_send_output=True)
+
+
+@rg.handle()
+async def _(result: Arparma = AlconnaMatches()):
+ if result.find("list"):
+ img = await gen_role_group_list_image()
+ await rg.finish(Message([Image(img)]))
+ if result.find("add"):
+ group = await create_role_group(result["add.name"])
+ if result.find("add.member"):
+ ats: tuple[Ob12MS, ...] = result["add.member.target"]
+ group.extend(member.data["user_id"] for member in ats)
+ await rg.finish("添加成功")
+```
+
+## 响应器使用
+
+`on_alconna` 的所有参数如下:
+
+- `command: Alconna | str`: Alconna 命令
+- `skip_for_unmatch: bool = True`: 是否在命令不匹配时跳过该响应
+- `auto_send_output: bool = False`: 是否自动发送输出信息并跳过响应
+- `output_converter: TConvert | None = None`: 输出信息字符串转换为消息序列方法
+- `aliases: set[str | tuple[str, ...]] | None = None`: 命令别名, 作用类似于 `on_command` 中的 aliases
+- `comp_config: CompConfig | None = None`: 补全会话配置, 不传入则不启用补全会话
+- `use_origin: bool = False`: 是否使用未经 to_me 等处理过的消息
+
+`on_alconna` 返回的是 `Matcher` 的子类 `AlconnaMatcher`,其拓展了四类方法:
+
+- `.assign(path, value, or_not)`: 用于对包含多个选项/子命令的命令的分派处理
+- `.got_path(path, prompt)`: 在 `got` 方法的基础上,会以 path 对应的参数为准,读取传入 message 的最后一个消息段并验证转换
+- `.set_path_arg(key, value)`, `.get_path_arg(key)`: 类似 `set_arg` 和 `got_arg`,为 `got_path` 的特化版本
+
+用例:
+
+```python
+from arclet.alconna import Alconna, Option, Args
+from nonebot_plugin_alconna import on_alconna, AlconnaMatch, Match, AlconnaMatcher, AlconnaArg
+
+login = on_alconna(Alconna(["/"], "login", Args["password?", str], Option("-r|--recall")))
+
+@login.assign("recall")
+async def login_exit():
+ await login.finish("已退出")
+
+@login.assign("password")
+async def login_handle(matcher: AlconnaMatcher, pw: Match[str] = AlconnaMatch("password")):
+ matcher.set_path_arg("password", pw.result)
+
+@login.got_path("password", prompt="请输入密码")
+async def login_got(password: str = AlconnaArg("password")):
+ assert password
+ await login.send("登录成功")
+```
+
+## 依赖注入
+
+`Alconna` 的解析结果会放入 `Arparma` 类中,或用户指定的 `Duplication` 类。
+
+`nonebot_plugin_alconna` 提供了一系列的依赖注入函数,他们包括:
+
+- `AlconnaResult`: `CommandResult` 类型的依赖注入函数
+- `AlconnaMatches`: `Arparma` 类型的依赖注入函数
+- `AlconnaDuplication`: `Duplication` 类型的依赖注入函数
+- `AlconnaMatch`: `Match` 类型的依赖注入函数
+- `AlconnaQuery`: `Query` 类型的依赖注入函数
+- `AlconnaExecResult`: 提供挂载在命令上的 callback 的返回结果 (`Dict[str, Any]`) 的依赖注入函数
+
+可以看到,本插件提供了几类额外的模型:
+
+- `CommandResult`: 解析结果,包括了源命令 `command: Alconna` ,解析结果 `result: Arparma`,以及可能的输出信息 `output: str | None` 字段
+- `Match`: 匹配项,表示参数是否存在于 `all_matched_args` 内,可用 `Match.available` 判断是否匹配,`Match.result` 获取匹配的值
+- `Query`: 查询项,表示参数是否可由 `Arparma.query` 查询并获得结果,可用 `Query.available` 判断是否查询成功,`Query.result` 获取查询结果
+
+同时,基于 [`Annotated` 支持](https://github.com/nonebot/nonebot2/pull/1832), 添加了两类注解:
+
+- `AlcMatches`:同 `AlconnaMatches`
+- `AlcResult`:同 `AlconnaResult`
+- `AlcExecResult`: 同 `AlconnaExecResult`
+
+实例:
+
+```python
+...
+from nonebot import require
+require("nonebot_plugin_alconna")
+...
+
+from nonebot_plugin_alconna import (
+ on_alconna,
+ Match,
+ Query,
+ AlconnaMatch,
+ AlconnaQuery,
+ AlconnaMatches,
+ AlcResult
+)
+from arclet.alconna import Alconna, Args, Option, Arparma
+
+test = on_alconna(
+ Alconna(
+ "test",
+ Option("foo", Args["bar", int]),
+ Option("baz", Args["qux", bool, False])
+ ),
+ auto_send_output=True
+)
+
+
+@test.handle()
+async def handle_test1(result: AlcResult):
+ await test.send(f"matched: {result.matched}")
+ await test.send(f"maybe output: {result.output}")
+
+@test.handle()
+async def handle_test2(result: Arparma = AlconnaMatches()):
+ await test.send(f"head result: {result.header_result}")
+ await test.send(f"args: {result.all_matched_args}")
+
+@test.handle()
+async def handle_test3(bar: Match[int] = AlconnaMatch("bar")):
+ if bar.available:
+ await test.send(f"foo={bar.result}")
+
+@test.handle()
+async def handle_test4(qux: Query[bool] = AlconnaQuery("baz.qux", False)):
+ if qux.available:
+ await test.send(f"baz.qux={qux.result}")
+```
+
+## 消息段标注
+
+示例中使用了消息段标注,其中 `At` 属于通用标注,而 `Image` 属于 `onebot12` 适配器下的标注。
+
+消息段标注会匹配特定的 `MessageSegment`:
+
+```python
+...
+ats: tuple[Ob12MS, ...] = result["add.member.target"]
+group.extend(member.data["user_id"] for member in ats)
+```
+
+:::tip
+通用标注与适配器标注的区别在于,通用标注会匹配多个适配器中相似类型的消息段。
+
+通用标注返回的是 `nonebot_plugin_alconna.adapters` 中定义的 `Segment` 模型:
+
+```python
+class Segment:
+ """基类标注"""
+ origin: MessageSegment
+
+class At(Segment):
+ """At对象, 表示一类提醒某用户的元素"""
+ target: str
+
+class Emoji(Segment):
+ """Emoji对象, 表示一类表情元素"""
+ id: str
+ name: Optional[str]
+
+class Media(Segment):
+ url: Optional[str]
+ id: Optional[str]
+
+class Image(Media):
+ """Image对象, 表示一类图片元素"""
+
+class Audio(Media):
+ """Audio对象, 表示一类音频元素"""
+
+class Voice(Media):
+ """Voice对象, 表示一类语音元素"""
+
+class Video(Media):
+ """Video对象, 表示一类视频元素"""
+
+class File(Segment):
+ """File对象, 表示一类文件元素"""
+ id: str
+ name: Optional[str] = field(default=None)
+```
+
+:::
+
+## 特殊装饰器
+
+`nonebot_plugin_alconna` 提供 了一个 `funcommand` 装饰器, 其用于将一个接受任意参数,
+返回 `str` 或 `Message` 或 `MessageSegment` 的函数转换为命令响应器。
+
+```python
+from nonebot_plugin_alconna import funcommand
+
+@funcommand()
+async def echo(msg: str):
+ return msg
+```
+
+其等同于
+
+```python
+from arclet.alconna import Alconna, Args
+from nonebot_plugin_alconna import on_alconna, AlconnaMatch, Match
+
+echo = on_alconna(Alconna("echo", Args["msg", str]))
+
+@echo.handle()
+async def echo_exit(msg: Match[str] = AlconnaMatch("msg")):
+ await echo.finish(msg.result)
+```