Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add YAML/TOML parsers for Lua configuration API #4969

Merged
merged 5 commits into from
Feb 8, 2024
Merged

Add YAML/TOML parsers for Lua configuration API #4969

merged 5 commits into from
Feb 8, 2024

Conversation

expnn
Copy link
Contributor

@expnn expnn commented Feb 6, 2024

This PR adds the following two features to the configuration Lua API:

  • Parsing of strings in yaml/toml formats.
  • Serialization of Lua objects into yaml/toml strings.

I renamed the original lua-api-crates/json to lua-api-crates/serde-funcs and added support for yaml/toml formats on top of the existing json format support. These functions are registered under the wezterm.serde submodule and include:

  • yaml_encode/yaml_decode
  • toml_encode/toml_decode
  • json_encode/json_decode (copied and renamed from the original functions)

Additionally, I re-registered json_decode and json_encode under wezterm.json_parse and wezterm.json_encode, respectively, for backward compatibility.

Since both the toml and serde_yaml crates are already in the original project's dependency list, the added functionality has minimal impact on the program's size.

This functionality is particularly useful when configuration files need to store or access data in yaml/toml formats.
Some users may prefer using yaml/toml as the configuration language, and this feature provides convenience for that purpose.
For example, users may want to write some static configuration items in a yaml file and then parse that file in the wezterm.lua configuration file to obtain the final configuration result.
In practice, most static configurations can be accomplished using languages like yaml.
Below is a fragment of my yaml configuration file and the corresponding Lua parsing code:

default_domain_type: "ssh"
domains:
  unix:
    type: "unix"
  node33:
    remote_address: 'x.y.z.33'
  node34:
    remote_address: 'x.y.z.34'
  node36:
    remote_address: 'x.y.z.36'
  node37:
    remote_address: 'x.y.z.37'
  slurm-test:
    remote_address: 'x.y.z.27'
    username: 'slurm1605101085899980801'
    remote_wezterm_path: '/home/slurm1605101085899980801/bin/wezterm'
-- Omitted a lot of lines.

local yaml_cfg = wezterm.serde.yaml_decode(yaml_content)

local ssh_domains = {}
local unix_domains = {}
local tls_domains = {}
local default_domain_type = pop_item(yaml_cfg, "default_domain_type") or "ssh"
for name, args in pairs(pop_item(yaml_cfg, "domains")) do
    args.name = name
    local domain_type = pop_item(args, "type") or default_domain_type

    if domain_type == "ssh" then
        if not args.username then
            args.username = default_user
        end
        local ssh_option = args.ssh_option or {}
        local no_default_identity = pop_item(ssh_option, "no_default_identity")
        if not ssh_option.identity_file and default_identity_file ~= nil and not no_default_identity then
            ssh_option.identity_file = default_identity_file
        end
        if is_empty(ssh_option) then
            args.ssh_option = ssh_option
        end
        table.insert(ssh_domains, args)
        wezterm.log_info(string.format("Added SSH domain: %s: %s@%s", args.name, args.username, args.remote_address))
    elseif domain_type == "unix" then
        table.insert(unix_domains, args)
        wezterm.log_info(string.format("Added Unix domain: %s", args.name))
    else
        table.insert(tls_domains, args)
    end
end

In this configuration, I organize domains of different types under the same yaml object and use the domain name as the key to ensure the uniqueness domain names, even if they belong to different domains. Otherwise, a modern text editor would issue a warning.

Copy link
Owner

@wez wez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this! I think this sounds reasonable.
Please also add docs for this new module. I'd suggest looking at https://github.com/wez/wezterm/tree/main/docs/config/lua/wezterm.url for an example of how to lay it out.

The since macro is important for tracking the version; you can use {{since('nightly')}} as a placeholder for the version. That will get replaced by the actual version when I make a release.

You can link your new docs into the toc by adding something similar to this:

wezterm/ci/generate-docs.py

Lines 401 to 404 in 39d2b6c

Gen(
"module: wezterm.url",
"config/lua/wezterm.url",
),

You can run the doc build locally using:

./ci/build-docs.sh serve

it will spawn a webserver and print out the port number for you to open it in your browser, and will auto-rebuild and reload your browser as you edit existing doc pages. If you add docs or change the generate-docs.py script, you will need to ctrl-c and re-run ci/build-docs.sh for those changes to take effect.

lua-api-crates/serde-funcs/src/lib.rs Outdated Show resolved Hide resolved
lua-api-crates/serde-funcs/src/lib.rs Outdated Show resolved Hide resolved
lua-api-crates/serde-funcs/src/lib.rs Outdated Show resolved Hide resolved
@expnn
Copy link
Contributor Author

expnn commented Feb 8, 2024

Thanks for this! I think this sounds reasonable. Please also add docs for this new module. I'd suggest looking at https://github.com/wez/wezterm/tree/main/docs/config/lua/wezterm.url for an example of how to lay it out.

The since macro is important for tracking the version; you can use {{since('nightly')}} as a placeholder for the version. That will get replaced by the actual version when I make a release.

You can link your new docs into the toc by adding something similar to this:

wezterm/ci/generate-docs.py

Lines 401 to 404 in 39d2b6c

Gen(
"module: wezterm.url",
"config/lua/wezterm.url",
),

You can run the doc build locally using:

./ci/build-docs.sh serve

it will spawn a webserver and print out the port number for you to open it in your browser, and will auto-rebuild and reload your browser as you edit existing doc pages. If you add docs or change the generate-docs.py script, you will need to ctrl-c and re-run ci/build-docs.sh for those changes to take effect.

Thank you for your suggestions!

Docs, unit tests, and the *_encode_pretty variants for toml and json are added.
Redundant imports are removed.
The yaml serializer is pretty by default (see dtolnay/serde-yaml#226 (comment)), so there is no need to add yaml_encode_pretty.

@wez wez merged commit f671a9a into wez:main Feb 8, 2024
15 of 16 checks passed
wez added a commit that referenced this pull request Feb 8, 2024
@wez
Copy link
Owner

wez commented Feb 8, 2024

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants