#themes #yaml #toml #ron #configuration #config-file #json-toml

app tomlyre-cli

This CLI utility facilitates effortless manipulation and exploration of TOML, YAML, JSON and RON files

1 unstable release

0.0.1-beta.1 Apr 24, 2023

#472 in Command-line interface

Apache-2.0

3MB
33K SLoC

TomLyre

library: crates.io

cli: crates.io

Documentation

Apache-2 licensed

中文

A tool for handling configuration files is available, with which you can explore toml, yaml, json, ron, bson, Lisp S-exp and xml freely and discover the fun in them.

By default, the bson & xml features are not enabled.

Features

The core features of this tool are only three:

  1. Conversion (conv)
  2. Getting (get)
  3. Setting/modifying (set)

Everything else is an additional feature, like setting themes and table styles.

Use --help to get detailed help information.

  • tomlyre set is equivalent to tomlyre set -h, which outputs concise help information.
  • tomlyre set --help outputs very detailed information.
  • Similarly, other subcommands can also call --help.
set_helpget --help conv_helpconv --help

It even supports L10n(localization/localisation) (with resources located in the assets/l10n directory). Unfortunately, there are currently many translation errors. 😭

If you like it, anyone is welcome to improve the translation.

If you don't know how to do it, please feel free to submit an issue.

es_set_helpespañol(España) de_set_helpDeutsch(Deutschland)
ja_set_help日本語 ar_set_helpالعربية
pt_get_helpportuguês(Brasil) fr_get_helpfrançais(France)

Theme

Use the --theme parameter (can be abbreviated as -t) to specify a theme, for example tomlyre -t "One Dark" conv test.yml -t json.

The -t of the conv subcommand refers to --to, while the -t of the root command is --theme.

When no theme name is specified, all themes will be listed.

The following are built-in themes, but you can also manually load a collection of themes and specify the name instead of using the built-in ones.

Most of these themes use the MIT License, and you can find the built-in themes and related license files in the assets/theme directory.

dracula monokai
onedark onehalf
ayu-dark ayu

Table Styles

Use --table-style (can be abbreviated as --ts) to specify the table style. For example, --table-style markdown or --ts md can be used to specify the table style as markdown.

tomlyre --ts md get Cargo.toml -k profile.fat
profile.fat Type Value
inherits str thin
lto str fat
opt-level str z

The following are built-in table styles: (Non-monospace fonts may cause layout issues.)


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

Warning: If the data types between two configurations are not fully compatible, the data type will change after conversion.


For example, ron has a char type, which represents a single character.

Take hello, 世界 as an example. This is a string. 'h' is char, "h" is string. "世界" is string, '世' is char.

However, both json 1.0 and toml 1.0 do not have a char type.

hello.ron:

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

json:

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

Therefore, converting a char from ron to json 1.0 will result in a string.


For example, currently many configuration formats support two special floating-point numbers: NaN and inf, but json 1.0 does not support them.

In json 1.0, they will both become 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 refers to 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 } }

Q: What is the data type that json has but other formats do not have?

A: null

For example, toml 1.0 and ron do not support null values. If you convert a json 1.0 configuration containing null, toml will report an error directly, while ron will convert it to an empty tuple (), which is commonly known as the Unit type.

Note: ron uses the Option<T> type, with a value of Some(T) or None, rather than null.

In addition, there are many differences between different configuration formats, and we have not listed them all.

get and set

When you use the set subcommand to specify a key and do not specify a value, it is equivalent to a more detailed version of set.

For example, we use the following command to read and parse data from stdin:

The - after get means that the source is stdin instead of a specific file

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

When using get, stdout will output true.

But when we change get to set, it will output:

true

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

Q: Is it better to have more information in the output?

A: Not necessarily!
This mainly depends on our intended use.
When we need to get specific values with a script, only valid information is needed. Extra information is not only useless, but can also interfere with data retrieval.
On the contrary, when we need to modify the data manually, having specific information is often better.

set

We can use --help with the set subcommand to get detailed information.

The basic usage is: set [source file] -k [keys separated by "."] [options for specifying data type] [value(s) for the specified data type (may be empty or multiple)]

For example, set test.toml --key package.edition --str 2024.


Note:
Only when the format of src is toml will the comments be preserved, otherwise they will not. Other formats will first be converted to toml before modification, and the converted file will not preserve comments.


Here are some of the data types that it supports:

Basic data types

Option Alias Value Type Description Example
-s --str String String type -s "1.114.5-beta.1"
-b --bool bool Boolean type -b true
--f64 f64 Double-precision float --f64 314e-2
-n --num/--int i64 64-bit signed integer -n 2048
-a --arr Vec<String> Array of strings -a hello -a world
--num-arr --na Vec<i64> Array of i64 --na 11 --na -3
--f64-arr --fa Vec<f64> Array of double-precision floats --fa 3.14 --fa 2.71828182
--bool-arr --ba Vec<bool> Array of boolean --ba true --ba false
-i --inline-table Vec<(key, value)> Inline table -i name sd -i os android
--rm Delete the specified key and its value

In addition, there are some data types that are not as "basic", such as "standard table", "table array", and DateTime.

The standard table is very similar to the inline table. If you don't know which one to use, use inline table(-i) instead of standard table(-m).

For formats other than toml, use -i to create a new table instead of -m!

Suppose that in hello.toml, there is a table array named test, and the map at index 0 has a key named kk with a value of v.

[[test]]
kk = "v"
set hello.toml -k test.
test. Type Value
0.kk str v
key:    ["test"]
type:   array of tables
value:
[{ kk = "v" }]

Let's create a sub-table using -m or --table.

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

Output:

key: ["test", "0", "a"]
type: table
new value: hello = "world"
test.0 Type New Value
kk str v
a.hello str world
[[test]]
kk = "v"

[test.a]
hello = "world"

It looks like there is no problem. Let's try using an inline table.

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

Output:

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

For this case, the standard table and the inline table are the same. (Although they look different, their parsing results are the same.)

However, when the key is test.0.x.y.z and there are multiple nonexistent nested sub-tables inside, you can try using -m and -i separately.

After trying it out myself, I believe you will understand why not to use -m.

Log Levels

The level of detail from high to low is trace > debug > info > warn > error.

trace is the most detailed.

The default level is info.

We can modify the log level by setting an environment variable:

env RUST_LOG=debug tomlyre

Off-topic

Original Design Intention

Q: What was the original design intention of this tool?

A: The original intention was to allow everyone to query and modify configuration files in a simple and elegant way in the CLI.

About a year or two ago, I mentioned in the documentation of another project:

  • That project would subsequently use the toml format for configuration.
    • And introduced some specific details
      • Such as using the get subcommand to retrieve
      • Use set to modify

When designing, I was struggling with whether to use toml, yaml, ron, or go further and use a database directly.

At first, I had already written code that supports both toml and yaml at the same time.
This involves the problem of parsing priority.
When the following files exist at the same time, which one should the program parse first?

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

At this point, there needs to be a core configuration to specify the user configuration.
So the question is, what format should the core configuration be?
We can use environment variables to specify the format of the core configuration.

It doesn't seem to be very difficult to look at it like this!

Note: different formats have different specifications, and compatibility with different formats requires an understanding of their differences.
If you want to support more formats, it will become a bit cumbersome.

Some things are not very difficult in themselves, but they require a lot of time and effort to deal with.

In the end, I separated it into a separate small tool.

In this way, everyone can indirectly support multiple formats through this small tool. (What we see is yaml, but the actual modification is a toml file)

yaml

Q: Why support multiple configuration formats? Many people say that yaml is more readable. Can't we just support yaml?

Although I would like to firmly answer, "No!", it actually depends on the needs of you and your users.

YAML supports more advanced features than TOML and JSON, such as references, includes, and tags.

  1. Anchor and Alias: Allows reusing the same data structure or node within the same document.
  2. References: Allows referencing values from other nodes within a YAML document.
  3. Custom Tags: Allows defining custom tags to better control the parsing of YAML data types.
  4. Includes: Allows combining multiple YAML files into one file, improving code reusability.

If you need these features, then using YAML is an excellent choice.

If you don't need these features, is it worth choosing YAML?

This question is worth discussing.

Pro-side: The more features, the better. I may not use them, but you can't be without them.

Con-side: Too many features increase complexity and confusion.

In addition to balancing readability and functionality, the feelings of ordinary users should also be considered.

If a configuration file contains complex nested structures, and your users do not have an "advanced" editor, then the indentation feature of YAML may easily lead to errors.

If your users may write configurations in notepad on early Windows, would TOML be better than YAML?

Early refers to before 2022 on Windows 10, when notepad.exe only had basic functions.
Windows tools are constantly evolving, and perhaps one day notepad will also have advanced features such as syntax highlighting, displaying whitespace characters, and code completion. Therefore, I limited it to "early".

Taking Windows as an example may not be appropriate because there are many editor software.

Even if you find a kid on the street, he can easily help you install editor software.

So, we have turned the question into: "Hi, my environment is RISC-V architecture, uClibc Linux, with no package manager. Could you help me set up a cross-compiling environment on your computer? Then compile an ultra-lightweight editor, which needs syntax highlighting and can highlight whitespace characters."

Hmm, let's not make it too difficult for that kid.

Dependencies

~15–25MB
~360K SLoC