Replies: 3 comments
-
|
This is another approach I've tried using the example in the other discussion use schematic::Config;
use schematic::{ConfigLoader};
use clap::{Args, Parser};
/// CLI App
#[derive(Config, Debug)]
#[config(partial(derive(Args)))]
pub struct AppConfig {
/// The Serial port to use
#[setting(
partial(arg(short, long)))
]
pub port: String,
}
#[derive(Parser, Debug)]
struct Cli {
// Note: PartialAppConfig is a struct generated by schematic that has all types wrapped in Option
// The attributes wrapped in partial() are applied to this struct
#[command(flatten)]
app_config: PartialAppConfig,
}
impl AppConfig {
pub fn readall() -> String {
// Read from file
let file_config = ConfigLoader::<AppConfig>::new()
.file("example-app.toml").unwrap()
.load().unwrap();
let fileport = file_config.config.port;
println!("file specified port: {}", fileport);
// Read from command line
let cli = Cli::parse();
// Just panic's if the cli option isnt set
// How do we read both at the same time?
let cliport = cli.app_config.port.unwrap();
println!("cli specified port: {}", cliport);
fileport
}
} |
Beta Was this translation helpful? Give feedback.
0 replies
-
|
I've discovered that this works using figment use clap::{CommandFactory, Parser, error::ErrorKind};
use figment::{Figment, providers::{Serialized, Toml, Format}};
use serde::{Serialize, Deserialize};
// https://github.com/SergioBenitez/Figment/issues/4
#[derive(Parser, Debug, Serialize, Deserialize)]
pub struct AppConfig {
/// Port Number
#[clap(short, long)]
#[serde(skip_serializing_if = "::std::option::Option::is_none")]
pub port: Option<String>,
}
impl AppConfig {
pub fn readall() -> String {
let config: AppConfig = Figment::new()
.merge(Toml::file("example-app.toml"))
.merge(Serialized::defaults(AppConfig::parse()))
.extract().unwrap();
// Custom Validation
if config.port.is_none() {
let mut cmd = AppConfig::command();
cmd.error(
ErrorKind::MissingRequiredArgument,
"port not found",
)
.exit();
}
config.port.unwrap()
}
} |
Beta Was this translation helpful? Give feedback.
0 replies
-
|
Closing this since I've worked out a way using figment |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi,
so I've been looking for an example of how to combine clap with something like confique so that an app can read from both a configuration file and the cli at the same time.
So the question I've been having is, is there a way to parse a derived config in such a way that you can pass in a set of defaults or already specified values, so that if the cli option isn't found it falls back to the previous values (if they exist, which would ether be from a config file or defaults via a struct from confique)
I did run across this - #2763
But had a bit of trouble getting it to work, I'm not sure if all the code needed is in for the examples in that discussion for things to work fully
From what I understand it's possible to use augment_args to add derived settings on top of a Command.
But is it possible to take the output of something like confique as the struct with the defaults / file config settings in -> generate a Command from that some how using the builder API -> add to that using the augment_args call on the derive api
https://docs.rs/clap/latest/clap/_derive/index.html#mixing-builder-and-derive-apis
I'm still a bit new to rust, so please forgive if I don't fully understand the API at this stage.
Ether way I think it would make for a good example in the examples directory if there was a way to handle both file and cli options at the same time
Beta Was this translation helpful? Give feedback.
All reactions