Atuin中的Clap实现

之前学习了Rust中的Clap crate, 前几天又接触了Rust实现的一个命令行记录工具Atuin, 他的命令行参数就是使用Clap实现, 并且参数众多, 做了不同的分层. 今天就扒一扒Atuin的实现方式, 加深一下对Clap的理解.

下图是整理的Atuin部分命令配置:

首先观察紫色的这条线部分, 并结合前部在AtuinCmdclient::Cmd添加的subcommandflatten可以知道, history应该是最上层的命令, 这从帮助信息中可以看到. 再观察紫色框中的内容, 可以知道history会有 start, end, list, last这些命令, 同时需要输入的参数是, command, id, cwd, session等.

再观察酒红色这一部分, 这里使用的是Parser派生. 同时命令参数的类型是enum, 没有附加数据. 这些命令每次只能指定一个, 并且不带有参数.

接下来看绿色方框的部分, 这里使用Commands类型又多做了一层封装. 如果换成红色方框的结构, 也可以编译通过. 在Commands中的类型是命令, 而在比如login::Cmd中的类型就是参数, 使用的是Parser派生.

总结:

Atuin的代码中, 可以看到它是使用#[command(flatten)] #[command(subcomannd)] #[derive(Subcommand)] 来完成层级结构的规划的.

  • 其中 #[command(flatten)]是将字命令提升一级, 相当于用子命令替换了#[command(flatten)]所在的参数.
  • #[command(subcomannd)]#[derive(Subcommand)]组合完成子命令的创建.

同时可以看到的是 #[derive(Parser)]#[derive(Args)]的使用.

在只有具体参数选项的结构中, 使用的是#[derive(Parser)], 比如login::Cmdimport::Cmd. Clap crate的文档中对Parser的解释就是

Parse command-line arguments into Self.

将参数解析到Self(我理解可以是enum或者struct)当中. 也就是最后需要完成参数解析了.

Args的解释是

Parse a set of arguments into a user-defined container.

Implementing this trait lets a parent container delegate argument parsing behavior to Self. with:

  • #[command(flatten)] args: ChildArgs: Attribute can only be used with struct fields that impl Args.
  • Variant(ChildArgs): No attribute is used with enum variants that impl Args.(适用当前account::Cmd的情况)

Subcommand的解释是

Parse a sub-command into a user-defined enum.

Implementing this trait lets a parent container delegate subcommand behavior to Self. with:

  • #[command(subcommand)] field: SubCmd: Attribute can be used with either struct fields or enum variants that impl Subcommand.
  • #[command(flatten)] Variant(SubCmd): Attribute can only be used with enum variants that impl Subcommand.

从两个官方给出的解释可以看到, Args是解析参数集合到用户定义的容器中(只要求容器类型), Subcommand是解析子命令到用户定义的枚举中(只能是枚举). 还有的不同是(这块还没理解到, 后面补充)

rust 复制代码
#[command(flatten)]
args: ChildArgs  --> ChildArgs必须是实现了Args的struct

#[command(flatten)]
Variant(SubCmd)  --> SubCmd必须是实现了Subcommand的enum
相关推荐
星栈18 小时前
我用 Rust + Dioxus 做了个全栈跨平台笔记应用:再把新建、编辑和交付补上
前端·rust·前端框架
独孤留白1 天前
从C到Rust:基本类型 C 的隐式不确定 vs Rust 的显式确定
rust
清晨很温柔啊1 天前
# 用 Rust 手搓 AI 自演化主板:当 18 个异构器官长出 C++ 骨骼
rust
星栈2 天前
我用 Rust + Dioxus 做了个全栈跨平台笔记应用:第一版先把列表和详情跑通
前端·rust·前端框架
doiito2 天前
【Agent Harness】Gliding Horse 工具结果压缩体系:如何用“指针”驯服上下文膨胀
ai·rust·架构设计·系统设计·ai agent
星栈3 天前
Dioxus 接数据库最容易写歪的 3 个地方:sqlx + SQLite 怎么接才顺
前端·rust·前端框架
独孤留白3 天前
从C到Rust:移动语义、引用传递与生命周期——一次讲清楚
rust
星栈3 天前
Dioxus 表单处理:从输入、校验到文件上传,一条链路讲透
前端·rust·前端框架
doiito3 天前
【Agent Harness】Gliding Horse 上下文动态感知与智能压缩:让 Agent 真正“听得进”每一句话
ai·rust·架构设计·系统设计·ai agent