#主题 #yaml #toml #ron #配置 #日志级别 #配置文件

app tomlyre-cli

此 CLI 工具简化了 TOML、YAML、JSON 和 RON 文件的操控和探索

1 个不稳定版本

0.0.1-beta.12023年4月24日

#441 in 命令行界面

Apache-2.0

3MB
33K SLoC

TomLyre

库:crates.io

cli:crates.io

Documentation

Apache-2 licensed

中文

提供了一种处理配置文件的工具,您可以使用它自由地探索 toml、yaml、json、ron、bson、Lisp S-exp 和 xml,并发现其中的乐趣。

默认情况下,bson 和 xml 功能未启用。

功能

此工具的核心功能仅三个

  1. 转换 (conv)
  2. 获取 (get)
  3. 设置/修改 (set)

其他所有功能都是附加功能,例如设置主题和表格样式。

使用 --帮助 获取详细信息。

  • tomlyre set 等同于 tomlyre set -h,它输出简明扼要的帮助信息。
  • tomlyre set --help 输出非常详细的信息。
  • 同样,其他子命令也可以调用 --帮助
set_helpget --help conv_helpconv --help

它甚至支持 L10n(本地化)(资源位于 assets/l10n 目录)。遗憾的是,目前存在许多翻译错误。😭

如果您喜欢它,任何人都可以改善翻译。

如果您不知道如何操作,请随时提交问题。

es_set_help西班牙语(西班牙) de_set_help德语(德国)
ja_set_help日语 ar_set_help阿拉伯语
pt_get_help葡萄牙语(巴西) fr_get_help法语(法国)

主题

使用 --theme 参数(可以缩写为 -t)来指定主题,例如 tomlyre -t "One Dark" conv test.yml -t json

子命令 conv 中的 -t 指的是 --to,而根命令中的 -t--theme

未指定主题名称时,将列出所有主题。

以下为内置主题,但您也可以手动加载一组主题并指定名称,而不是使用内置主题。

大多数这些主题使用 MIT 许可证,您可以在 assets/theme 目录中找到内置主题和相关许可证文件。

dracula monokai
onedark onehalf
ayu-dark ayu

表格样式

使用 --table-style(可以缩写为 --ts)来指定表格样式。例如,使用 --table-style markdown--ts md 可以指定表格样式为 markdown。

tomlyre --ts md get Cargo.toml -k profile.fat
profile.fat 类型
继承 字符串
lto 字符串 fat
opt-level 字符串 z

以下为内置表格样式:(非等宽字体可能会引起布局问题。)


style: default

╭─────────┬──────────┬────────────╮
│ Version ┆ Codename ┆ Created    │
├─────────┼──────────┼────────────┤
│ 10      ┆ Buster   ┆ 2017-06-17 │
├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 11      ┆ Bullseye ┆ 2019-07-16 │
├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 12      ┆ Bookworm ┆ 2021-08-14 │
├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 13      ┆ Trixie   ┆ 2023       │
├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 14      ┆ Forky    ┆ 2025       │
╰─────────┴──────────┴────────────╯


style: nothing

 Version  Codename  Created
 10       Buster    2017-06-17
 11       Bullseye  2019-07-16
 12       Bookworm  2021-08-14
 13       Trixie    2023
 14       Forky     2025


style: ascii

+---------+----------+------------+
| Version | Codename | Created    |
+=================================+
| 10      | Buster   | 2017-06-17 |
|---------+----------+------------|
| 11      | Bullseye | 2019-07-16 |
|---------+----------+------------|
| 12      | Bookworm | 2021-08-14 |
|---------+----------+------------|
| 13      | Trixie   | 2023       |
|---------+----------+------------|
| 14      | Forky    | 2025       |
+---------+----------+------------+


style: ascii-borders

+---------------------------------+
| Version   Codename   Created    |
+=================================+
| 10        Buster     2017-06-17 |
| 11        Bullseye   2019-07-16 |
| 12        Bookworm   2021-08-14 |
| 13        Trixie     2023       |
| 14        Forky      2025       |
+---------------------------------+


style: right-u8-fat

┌─────────┬──────────┬────────────┐
│ Version │ Codename │ Created    │
╞═════════╪══════════╪════════════╡
│ 10      │ Buster   │ 2017-06-17 │
├─────────┼──────────┼────────────┤
│ 11      │ Bullseye │ 2019-07-16 │
├─────────┼──────────┼────────────┤
│ 12      │ Bookworm │ 2021-08-14 │
├─────────┼──────────┼────────────┤
│ 13      │ Trixie   │ 2023       │
├─────────┼──────────┼────────────┤
│ 14      │ Forky    │ 2025       │
└─────────┴──────────┴────────────┘


style: right-u8

┌─────────┬──────────┬────────────┐
│ Version │ Codename │ Created    │
├─────────┼──────────┼────────────┤
│ 10      │ Buster   │ 2017-06-17 │
├─────────┼──────────┼────────────┤
│ 11      │ Bullseye │ 2019-07-16 │
├─────────┼──────────┼────────────┤
│ 12      │ Bookworm │ 2021-08-14 │
├─────────┼──────────┼────────────┤
│ 13      │ Trixie   │ 2023       │
├─────────┼──────────┼────────────┤
│ 14      │ Forky    │ 2025       │
└─────────┴──────────┴────────────┘


style: right-u8-thin

┌─────────┬──────────┬────────────┐
│ Version ┆ Codename ┆ Created    │
├─────────┼──────────┼────────────┤
│ 10      ┆ Buster   ┆ 2017-06-17 │
├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 11      ┆ Bullseye ┆ 2019-07-16 │
├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 12      ┆ Bookworm ┆ 2021-08-14 │
├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 13      ┆ Trixie   ┆ 2023       │
├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 14      ┆ Forky    ┆ 2025       │
└─────────┴──────────┴────────────┘


style: u8

┌─────────┬──────────┬────────────┐
│ Version ┆ Codename ┆ Created    │
╞═════════╪══════════╪════════════╡
│ 10      ┆ Buster   ┆ 2017-06-17 │
├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 11      ┆ Bullseye ┆ 2019-07-16 │
├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 12      ┆ Bookworm ┆ 2021-08-14 │
├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 13      ┆ Trixie   ┆ 2023       │
├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 14      ┆ Forky    ┆ 2025       │
└─────────┴──────────┴────────────┘


style: u8-no-dividers

┌─────────┬──────────┬────────────┐
│ Version ┆ Codename ┆ Created    │
╞═════════╪══════════╪════════════╡
│ 10      ┆ Buster   ┆ 2017-06-17 │
│ 11      ┆ Bullseye ┆ 2019-07-16 │
│ 12      ┆ Bookworm ┆ 2021-08-14 │
│ 13      ┆ Trixie   ┆ 2023       │
│ 14      ┆ Forky    ┆ 2025       │
└─────────┴──────────┴────────────┘


style: u8-borders

┌─────────────────────────────────┐
│ Version   Codename   Created    │
╞═════════════════════════════════╡
│ 10        Buster     2017-06-17 │
│ 11        Bullseye   2019-07-16 │
│ 12        Bookworm   2021-08-14 │
│ 13        Trixie     2023       │
│ 14        Forky      2025       │
└─────────────────────────────────┘


style: u8-no-borders

 Version ┆ Codename ┆ Created
═════════╪══════════╪════════════
 10      ┆ Buster   ┆ 2017-06-17
╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌
 11      ┆ Bullseye ┆ 2019-07-16
╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌
 12      ┆ Bookworm ┆ 2021-08-14
╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌
 13      ┆ Trixie   ┆ 2023
╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌
 14      ┆ Forky    ┆ 2025


style: horizontal

---------------------------------
 Version   Codename   Created
=================================
 10        Buster     2017-06-17
---------------------------------
 11        Bullseye   2019-07-16
---------------------------------
 12        Bookworm   2021-08-14
---------------------------------
 13        Trixie     2023
---------------------------------
 14        Forky      2025
---------------------------------


style: round-u8

╭─────────┬──────────┬────────────╮
│ Version │ Codename │ Created    │
├─────────┼──────────┼────────────┤
│ 10      │ Buster   │ 2017-06-17 │
├─────────┼──────────┼────────────┤
│ 11      │ Bullseye │ 2019-07-16 │
├─────────┼──────────┼────────────┤
│ 12      │ Bookworm │ 2021-08-14 │
├─────────┼──────────┼────────────┤
│ 13      │ Trixie   │ 2023       │
├─────────┼──────────┼────────────┤
│ 14      │ Forky    │ 2025       │
╰─────────┴──────────┴────────────╯


style: round-u8-fat

╭─────────┬──────────┬────────────╮
│ Version ┆ Codename ┆ Created    │
╞═════════╪══════════╪════════════╡
│ 10      ┆ Buster   ┆ 2017-06-17 │
├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 11      ┆ Bullseye ┆ 2019-07-16 │
├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 12      ┆ Bookworm ┆ 2021-08-14 │
├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 13      ┆ Trixie   ┆ 2023       │
├╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 14      ┆ Forky    ┆ 2025       │
╰─────────┴──────────┴────────────╯


style: markdown

| Version | Codename | Created    |
|---------|----------|------------|
| 10      | Buster   | 2017-06-17 |
| 11      | Bullseye | 2019-07-16 |
| 12      | Bookworm | 2021-08-14 |
| 13      | Trixie   | 2023       |
| 14      | Forky    | 2025       |

conv

警告:如果两个配置之间的数据类型不完全兼容,数据类型将在转换后更改。


例如,ron 有一个 char 类型,表示一个字符。

hello, 世界 为例。这是一个字符串。'h' 是 char,"h" 是字符串。 "世界" 是字符串,'世' 是 char。

但是,json 1.0toml 1.0 都没有 char 类型。

hello.ron

{
   "s": '',
   "j": '',
}
tomlyre c hello.ron -t json

json

{
  "j": "",
  "s": ""
}

因此,将 charron 转换为 json 1.0 将得到一个字符串。


例如,目前许多配置格式支持两个特殊浮点数: NaNinf,但 json 1.0 不支持它们。

json 1.0 中,它们都将变为 null

f64-map.toml

[double-float-map]
not-a-num = nan
infinity = inf
tomlyre conv f64-map.toml -t ./f.yaml --save

f.yaml

double-float-map:
  infinity: .inf
  not-a-num: .nan
tomlyre conv f.yaml -t ron --sv

f.ron

{
    "double-float-map": {
        "infinity": inf,
        "not-a-num": NaN,
    },
}
tomlyre conv f.ron -t sexp

sexp 指的是 Lisp S-Expressions。

(("double-float-map" ("infinity" . inf) ("not-a-num" . NaN)))
tomlyre conv f.ron -t json
{
  "double-float-map": {
    "infinity": null,
    "not-a-num": null
  }
}
tomlyre conv f.ron -t json5
{ "double-float-map": { infinity: Infinity, "not-a-num": NaN } }

问题:JSON类型具有,而其他格式没有的数据类型是什么?

答案:null

例如,toml 1.0ron 不支持 null 值。如果您将包含 nulljson 1.0 配置转换为 tomltoml 将直接报告错误,而 ron 将将其转换为空元组 (),这通常被称为 单元 类型。

注意:ron 使用 Option<T> 类型,其值为 Some(T)None,而不是 null

此外,不同的配置格式之间存在许多差异,我们并没有列出所有。

获取和设置

当您使用 set 子命令指定一个键但未指定值时,它等同于更详细的 set 版本。

例如,我们使用以下命令从 stdin 读取和解析数据

- 后的 get 表示源是 stdin 而不是特定文件

curl -sL https://raw.githubusercontent.com/2moe/tomlyre/main/Cargo.toml | tomlyre get -  -k profile.thin.strip

当使用 get 时,stdout 将输出 true

但是当我们把 get 改为 set,它将输出

true

key:    ["profile", "thin", "strip"]
type:   boolean
value:
 true

问题:输出更多信息更好吗?

答案:不一定!
这主要取决于我们的预期用途。
当我们需要用脚本来获取特定值时,只需要有效信息。额外信息不仅无用,还可能干扰数据检索。
相反,当我们需要手动修改数据时,有具体信息通常更好。

设置

我们可以使用 --helpset 子命令来获取详细信息。

基本用法是:set [source file] -k [keys separated by "."] [options for specifying data type] [value(s) for the specified data type (may be empty or multiple)]

例如,set test.toml --key package.edition --str 2024


注意
只有当 src 的格式为 toml 时,才会保留注释,否则不会。其他格式在修改之前将首先转换为 toml,并且转换后的文件将不会保留注释。


以下是它支持的一些数据类型

基本数据类型

选项 别名 值类型 描述 示例
-s --str 字符串 字符串类型 -s"1.114.5-beta.1"
-b --bool 布尔型 布尔类型 -btrue
--f64 f64 双精度浮点数 64位浮点数 314e-2
-n --num/--int i64 64位有符号整数 -n2048
-a --arr Vec<字符串> 字符串数组 -a hello-a world
--num-arr --na Vec<i64> i64数组 --na11--na -3
--f64-arr --fa Vec<f64> 双精度浮点数数组 --fa3.14--fa2.71828182
--bool-arr --ba Vec<布尔型> 布尔数组 --ba true --ba false
-i --inline-table Vec<(键,值)> 内联表 -i name sd-i os android
--rm 删除指定的键及其值

此外,还有一些不是“基本”的数据类型,例如“标准表”、“表数组”和DateTime。

标准表与内联表非常相似。如果您不知道该使用哪一个,请使用内联表(-i)而不是标准表(-m)。

对于除了toml之外的格式,请使用-i创建新表,而不是使用-m

假设在hello.toml中,有一个名为test的表数组,索引0处的映射有一个名为kk的键,其值为v

[[test]]
kk = "v"
set hello.toml -k test.
test. 类型
0.kk 字符串 v
key:    ["test"]
type:   array of tables
value:
[{ kk = "v" }]

让我们使用-m--table创建一个子表。

set hello.toml --key test.0.a --map hello world --pre

输出

key: ["test", "0", "a"]
type: table
new value: hello = "world"
test.0 类型 新值
kk 字符串 v
a.hello 字符串 world
[[test]]
kk = "v"

[test.a]
hello = "world"

看起来没有问题。让我们尝试使用内联表。

set hello.toml -k test.0.a -i hello world --pre

输出

[[test]]
kk = "v"
a = { hello = "world" }

对于这个案例,标准表和内联表是相同的。(虽然它们看起来不同,但它们的解析结果相同。)

然而,当键是test.0.x.y.z并且内部有多个不存在的嵌套子表时,您可以尝试分别使用-m-i

亲自尝试后,我相信您会明白为什么不要使用-m

日志级别

从高到低,详细程度为trace > debug > info > warn > error

trace是最详细的。

默认级别是info

我们可以通过设置环境变量来修改日志级别

env RUST_LOG=debug tomlyre

无关话题

原始设计意图

问题:这个工具的原始设计意图是什么?

答案:原始意图是允许每个人都能以简单优雅的方式在CLI中查询和修改配置文件。

大约一年或两年前,我在另一个项目的文档中提到

  • 该项目随后将使用toml格式进行配置。
    • 并介绍了一些具体细节
      • 例如使用get子命令来检索
      • 使用set来修改

在设计时,我在是否使用toml、yaml、ron或更进一步直接使用数据库之间犹豫。

起初,我已经编写了同时支持toml和yaml的代码。
这涉及到解析优先级的问题。
当以下文件同时存在时,程序应该先解析哪一个?

  • cfg.toml
  • cfg.Toml
  • cfg.yaml
  • cfg.yml
  • cfg.YAML
  • cfg.YML
  • cfg.Yaml

此时,需要有一个核心配置来指定用户配置。
所以问题是,核心配置应该是什么格式?
我们可以使用环境变量来指定核心配置的格式。

这样看起来似乎并不困难!

注意:不同的格式有不同的规范,而与不同格式的兼容性需要了解它们之间的差异。
如果您想支持更多格式,这将变得有些繁琐。

有些事情本身并不难,但处理起来需要大量的时间和努力。

最后,我将它分离成了单独的小工具。

这样,每个人都可以通过这个小工具间接支持多种格式。(我们看到的是yaml,但实际上修改的是toml文件)

yaml

问:为什么支持多种配置格式?很多人说yaml更易读。我们难道只能支持yaml吗?

虽然我愿意坚定地回答“不”,但实际上这取决于您和您的用户的需求。

YAML支持的特性比TOMLJSON更高级,例如引用、包含和标签。

  1. 锚点和别名:允许在同一个文档中重复使用相同的数据结构或节点。
  2. 引用:允许从YAML文档中的其他节点引用值。
  3. 自定义标签:允许定义自定义标签以更好地控制YAML数据类型的解析。
  4. 包含:允许将多个YAML文件合并到一个文件中,提高代码复用性。

如果您需要这些功能,那么使用YAML是一个很好的选择。

如果您不需要这些功能,选择YAML是否值得呢?

这个问题值得讨论。

支持方:特性越多越好。我可能不会使用它们,但您不能没有它们。

反对方:太多的特性会增加复杂性和困惑。

除了平衡可读性和功能性之外,还应考虑普通用户的感受。

如果配置文件包含复杂嵌套的结构,而您的用户没有“高级”编辑器,那么yaml的缩进功能可能很容易导致错误。

如果您的用户可能在早期的Windows上使用notepad编写配置,那么TOML是否比yaml更好?

早期是指2022年之前在Windows 10上,当时notepad.exe只有基本功能。
Windows工具不断进化,也许有一天notepad也会拥有像语法高亮、显示空白字符和代码补全这样的高级功能。因此,我将它限制在“早期”。

以Windows为例可能不合适,因为有很多编辑器软件。

即使你在街上找到一个孩子,他也能轻松地帮助你安装编辑器软件。

所以,我们将问题转化为:“嗨,我的环境是RISC-V架构,uClibc Linux,没有包管理器。你能帮我在你的电脑上设置一个交叉编译环境吗?然后编译一个超轻量级的编辑器,它需要语法高亮和可以突出显示空白字符。”

嗯,不要让那个孩子太难了。

依赖项

~15–26MB
~361K SLoC