Exploring a redesign and discussing how a modern Rust configuration library should behave
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 3.2k
- Forks
- 265
- Avg merge
- 2h 42m
- Merged PRs (30d)
- 4
Description
This library has gotten quite stale over the last year and I've been loathe to come back to it mostly because I don't like it. It's complex to use, complex to develop, etc. I apologize for letting it atrophy.
I'd like to thank you everyone who has contributed or submitted a PR ( especially those who've done so in the last several months and have just sat there ). It's not that I don't want to merge in your work, it's that if I come back to this I'll want to do too much and I haven't had the time available to do that.
With that out of the way I want to explore how a configuration library could behave in Rust, optimally, using some example use cases as a jumping off point:
// load configuration only from envrionment
let settings: Settings = config::env::vars()
// filter to only keys that case-insentively start with s
.prefix("app_")
// explictly transform key names to allow traversing nested configuration
// replaces .separator("__") from config v0.9
.map(|key| key.replace("__", "."))
.load()?;
// find a single configuration file from example.* in
let settings: Settings = config::file::find("example")
// look in the following paths (by default cwd)
.paths(&[xdg_config_home, home])
// expect format in TOML only
// default allows all formats compiled in
.format(Format::Toml)
// and load into Settings
.load()?;
// find multiple configuration files and merge together
let settings: Settings = config::file::find_all(&[
"default",
mode // development, production, or test, etc.
]).load()?;
// load configuration from arguments
let settings: Settings = config::env::args(clap_matches).load();
// manually create a configuration stack
let settings: Settings = config::Stack::new()
// start with an embedded JSON file
.add(config::file::from_bytes(Format::Json, include_bytes!("default.json")))
// override from environment
.add(config::env::vars())
// load into settings
.load()?;
// create a dynamic configuration (ala config v0.9)
// any _source_ could be built into a Config struct
let settings: config::Config = config::file::find("example").build();
// a dyn configuration can listen for changes on supported sources
let _handle = settings.watch(|| do_something_fun_when_config_changes);
// use path access
let host: &str = settings.get("db.host");
Thoughts? How would you want config to work?
Are there any pain points in the current design you'd like to discuss?
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the Rust configuration use cases and API sketches in issue #111, then compare them with the current config-rs design and its existing pain points. Done means reaching agreement on the desired behavior and scope of a modern redesign; this issue does not name specific files or tests to change.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100