Comments (11)
But the problem is that
Config::parse()
requires to set all values. And If I usearg(..., default_value = "...")
it will override values from config.
Have you tried using join()
instead of merge()
?
I'm not really sure what you're trying to achieve exactly. That way you've written it, you're overriding everything from the TOML file with the result of Config::parse()
; if you reorder the two lines, you'll get the opposite effect. If you use join()
, you'll fill-in holes. You just have to choose what you want and what takes precedence. It's all documented, and some previously opened issues also contain examples that might help your case as well.
from figment.
Have you tried using join() instead of merge()?
Yes
That way you've written it, you're overriding everything from the TOML file with the result of Config::parse();
Yes, this is what I trying to do. But the problem is that it overrides all values from TOML with CLI. I trying to override only ones that is specified by user.
Config::parse()
sets all values for Config
. If I make any field as default - this default field will override TOML.
from figment.
Have you tried using join() instead of merge()?
Yes
Using join for the second invocation would mean you keep values specified in the TOML file even when they're present in the values resulting from Config::parse()
. Is this what you're looking for? If this doesn't work as I'm suggesting, then we have a bug to fix. But perhaps you want to override all values as long as they're not the default, even when present in the file?
That way you've written it, you're overriding everything from the TOML file with the result of Config::parse();
Yes, this is what I trying to do. But the problem is that it overrides all values from TOML with CLI. I trying to override only ones that is specified by user.
Config::parse()
sets all values forConfig
. If I make any field as default - this default field will override TOML.
The "trick" is to not serialize default values and to instead use serde's defaults or a default provider on deserialization. Concretely, this means using the skip_serializing_if
and default
serde field attributes as needed. If the values don't need to be passed in by the user, then you might be better off having two structures: one which is the true config, likely the one in your example, and one which is the CLI config structure with Option
s and skip_serializing_if = Option::is_none
for any optional fields. Then you could replace your Config::parse()
line with Cli::parse()
, and everything should work as intended.
from figment.
Using join for the second invocation would mean you keep values specified in the TOML file even when they're present in the values resulting from Config::parse(). Is this what you're looking for?
The "trick" is to not serialize default values and to instead use serde's defaults or a default provider on deserialization. Concretely, this means using the skip_serializing_if and default serde field attributes as needed.
No, I trying to do the opposite - let user override some values from TOML with some values from CLI.
Looks like the only way to achieve it is to have a special provider uses Command
from clap
under the hood. I mentioned it in the first message.
The use case is quite common. I know many apps that load configuration from file, but user can temporarily override any setting using CLI.
from figment.
Using join for the second invocation would mean you keep values specified in the TOML file even when they're present in the values resulting from Config::parse(). Is this what you're looking for?
The "trick" is to not serialize default values and to instead use serde's defaults or a default provider on deserialization. Concretely, this means using the skip_serializing_if and default serde field attributes as needed.
No, I trying to do the opposite - let user override some values from TOML with some values from CLI.
Looks like the only way to achieve it is to have a special provider uses
Command
fromclap
under the hood. I mentioned it in the first message.The use case is quite common. I know many apps that load configuration from file, but user can temporarily override any setting using CLI.
What do you mean? If I'm not mistaken, the mechanism I described above accomplishes what you're after without any special changes. You could also develop a special Provider, of course.
In any case, it looks like we're all set here, so I'm closing this out.
from figment.
Sorry, I misread you. I thought that you thinking that I talking about CLI -> TOML instead of TOML -> CLI.
Right, this solution will work. But it involves a lot of boilerplate (two structs with the same fields). Is there any chance that we could have a custom provider that accepts clap::Command
?
from figment.
Sorry, I misread you. I thought that you thinking that I talking about CLI -> TOML instead of TOML -> CLI.
Right, this solution will work. But it involves a lot of boilerplate (two structs with the same fields). Is there any chance that we could have a custom provider that accepts
clap::Command
?
I don't think it makes sense to have library-specific providers here, but you can write your own provider if you'd like! You can even release it on crates.io, and assuming it's nicely documented, we can link to it from our docs.
from figment.
I don't think it makes sense to have library-specific providers here
Makes sense, but don't you have toml
, serde_json
, etc? Clap also seems quite popular. I think CLI + one of the config formats is the most common case.
from figment.
Those are formats, not libraries. We could easily swap out the underlying dependencies for others if needed without any changes to our API. We don't expose serde_json
, we expose the JSON format. This would be akin to having a CommandLine
provider, not clap
.
In any case, I'm not sure what such an integration would look like. clap
generates a parser, so besides invoking said parser and serializing (as you're doing here and is easy to do), I'm not sure what else we could do. Maybe there's some functionality in clap I'm not aware. Should you create an implementation that is compelling and generic enough, I'm more than happy to consider it.
from figment.
This would be akin to having a CommandLine provider, not clap.
Fair point.
(as you're doing here and is easy to do), I'm not sure what else we could do
I wouldn't say that it's easy. The workaround is tricky and involves a lot of boilerplate.
Maybe there's some functionality in clap I'm not aware. Should you create an implementation that is compelling and generic enough, I'm more than happy to consider it.
I will try and let you know.
from figment.
I will try and let you know.
I was able to put together a proof of concept for this here: https://github.com/Notgnoshi/serdoc
I don't really like having to duplicate the Config
struct as NullableConfig
, but I'm not sure how else to do it (at least with clap
)
Please let us know if you find a better / more generic method!!
from figment.
Related Issues (20)
- Pattern for mixing required fields and optional fields with defaults HOT 3
- There's no way to unset an `Option` field from env variables HOT 2
- Support FromStr/Display serialization and deserialization HOT 3
- serde(flatten) breaks metadata propagation in errors HOT 4
- Pattern advice: How to use config file with required field without setting it? HOT 4
- Jail create_file in subdir HOT 2
- Write back to config file. HOT 3
- [FEATURE REQUEST]: Write a jail file with non-utf8 contents
- Preserve Toml File map Order HOT 3
- Deserializing yaml structure with enumeration fails HOT 5
- Allow Value::find to traverse arrays HOT 1
- YAML Nested Values Are Not Usable Via Environment Variables with `Env::split` HOT 2
- Option _not_ to check parent directories for configuration files HOT 1
- [Feature Request] allow to override default name for environment variables HOT 5
- FigmentBuilder
- Clippy and `rustfmt` HOT 2
- Question: Conventions to overwrite nested values with env vars HOT 3
- Question: How to load vector of struct with `Env` provider? HOT 2
- Escaping Jail Error HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from figment.