4 releases

0.2.2 Sep 6, 2024
0.2.1 May 1, 2024
0.2.0 May 1, 2024
0.1.0 Jan 19, 2024

#109 in Configuration

Download history 6281/week @ 2024-07-27 5189/week @ 2024-08-03 5034/week @ 2024-08-10 6777/week @ 2024-08-17 5889/week @ 2024-08-24 7305/week @ 2024-08-31 5776/week @ 2024-09-07 3832/week @ 2024-09-14 6971/week @ 2024-09-21 6172/week @ 2024-09-28 7275/week @ 2024-10-05 8275/week @ 2024-10-12 9051/week @ 2024-10-19 7236/week @ 2024-10-26 7599/week @ 2024-11-02 3911/week @ 2024-11-09

29,393 downloads per month

MIT/Apache

29KB
298 lines

clap-adapters

Adapter types for declaratively loading configurations with clap

Did you know that any type that implements FromStr can be used in a clap derive struct? That means that any logic you can fit into a fn(&str) -> Result<T, Error> can be run at parsing-time. This can be expecially useful for declaratively selecting config files or doing other cool stuff. Check this out:

use clap::Parser;
use clap_adapters::prelude::*;

#[derive(Debug, Parser)]
struct Cli {
    /// Path to a config file of arbitrary Json
    #[clap(long)]
    config: PathTo<JsonOf<serde_json::Value>>,
}

fn main() {
    // Create a config file in a temporary directory
    let config_dir = tempfile::tempdir()?;
    let config_path = config_dir.path().join("config.json");
    let config_path_string = config_path.display().to_string();

    // Write a test config of {"hello":"world"} to the config file
    let config = serde_json::json!({"hello": "world"});
    let config_string = serde_json::to_string(&config)?;
    std::fs::write(&config_path, &config_string)?;

    // Parse our CLI, passing our config file path to --config
    let cli = Cli::parse_from(["app", "--config", &config_path_string]);
    let data = cli.config.data();

    // We should expect the value we get to match what we wrote to the config
    assert_eq!(data, &serde_json::json!({"hello":"world"}));
}

Extending clap-adapters

You can implement additional composable adapters by defining new types that implement traits in this crate. For example, by implementing FromReader, you could define an adapter that can construct itself from a file path, nesting your adapter into PathTo<T>, like PathTo<YourAdapter>.

Dependencies

~4–13MB
~164K SLoC