Crate nccl[][src]

Expand description

A simple configuration language.

Nccl is an easy way to add minimal configuration to your crate without having to deal with complicated interfaces, obnoxious syntax, or outdated languages. Nccl makes it easy for a user to pick up your configuration. It’s as easy as five cents.

Nccl was motivated by the fact that other configuration languages are too complicated for both end-users and developers. Everyone loves types, but in a configuration language, there’s too much room for interpretation There are no types here.

This is a nice approach for smaller, non-semantic configurations; you shouldn’t be accidentally implementing a DSL with nccl, and if you are, it should feel painful.

For interacting with a parsed configuration, see config::Config.


The single most important feature:

let source = r#"
let config = nccl::parse_config(&source).unwrap();
assert_eq!(config["key"].value(), Some("value"));

Results in config["key"].value() == Some("value"). Note that there is no semantic difference between a key and a value, so config.value() == Some("key"). For most of this document and the library source code, the words key, value, and node are used almost interchangeably.

There are no types:

let source = r#"
is this a problem?
    no 🇳🇴
end of the world
let config = nccl::parse_config(&source).unwrap();
assert_eq!(config["is this a problem?"].value(), Some("no 🇳🇴"));

Interpret the data however you want.

Indentation is significant. Each top-level key-value pair must use the same type of indentation for each sub-value. You may mix indentation per-file.

let source = r#"
# tab

# single space
let config = nccl::parse_config(&source).unwrap();
assert_eq!(config["a"].value(), Some("1"));
assert_eq!(config["b"].value(), Some("2"));

Comments exist on their own line or after a quoted value, otherwise they become part of the value.

let source = r#"
hello # this is part of the key!
    # this is not
    "y'all" # this isn't either
let config = nccl::parse_config(&source).unwrap();
assert!(config.has_value("hello # this is part of the key!"));
assert!(!config["hello # this is part of the key!"].has_value("# this is not"));
assert!(config["hello # this is part of the key!"].has_value("y'all"));

Duplicate keys have their values merged.

let source = r#"
oh christmas tree
    o tannenbaum

oh christmas tree
    o tannenbaum
    five golden rings
    wait wrong song
let config = nccl::parse_config(&source).unwrap();
    vec!["o tannenbaum", "five golden rings", "wait wrong song"],
    config["oh christmas tree"].values().collect::<Vec<_>>()

Results in one key “oh christmas tree” with three values. This property enables parse_config_with to merge two configurations together. Say if you wanted to enable an end user to be able to override some default values, first you would parse the user’s configuration, and then parse the default on top of that. config::Config::value always returns the first value, which would be the user’s value.

Values can have quotes if you want escape codes or multiple lines. Supported escape sequences are newlines, carriage returns, both quotes, and line breaks.

let source = r#"
# both single and double quotes work
i can
    # with parse_quoted(), expands to the rust string "show\nyou"
    # backslash followed by newline replaces all following whitespace
    # except newlines with one space character. expands to "the world"
    "the \

# results in a single value for jingle = jangle
let config = nccl::parse_config(&source).unwrap();
assert_eq!(1, config["jingle"].values().count());
    Ok(vec![String::from("show\nyou"), String::from("the world")]),
    config["i can"]
        .map(|value| value.parse_quoted())
        .collect::<Result<Vec<_>, _>>()


pub use config::Config;


Contains the configuration struct


Errors that may occur while parsing


Parse a nccl configuration

Parse a new nccl configuration on top of another