cli: externalize ConfigArg value from enum, group arguments of the same type

This will simplify handling of multiple ConfigArg items of the same type.
Consecutive --config NAME=VALUE arguments will be inserted to the same
ConfigLayer.
This commit is contained in:
Yuya Nishihara 2024-12-14 17:55:06 +09:00
parent 3f115cbea5
commit 17ad708e44
2 changed files with 28 additions and 17 deletions

View file

@ -157,7 +157,7 @@ use crate::complete;
use crate::config::config_from_environment;
use crate::config::parse_config_args;
use crate::config::CommandNameAndArgs;
use crate::config::ConfigArg;
use crate::config::ConfigArgKind;
use crate::config::ConfigEnv;
use crate::diff_util;
use crate::diff_util::DiffFormat;
@ -3113,7 +3113,7 @@ pub struct EarlyArgs {
}
impl EarlyArgs {
fn merged_config_args(&self, matches: &ArgMatches) -> Vec<ConfigArg> {
fn merged_config_args(&self, matches: &ArgMatches) -> Vec<(ConfigArgKind, &str)> {
merge_args_with(
matches,
&[
@ -3121,8 +3121,8 @@ impl EarlyArgs {
("config_file", &self.config_file),
],
|id, value| match id {
"config_toml" => ConfigArg::Toml(value.clone()),
"config_file" => ConfigArg::File(value.clone()),
"config_toml" => (ConfigArgKind::Toml, value.as_ref()),
"config_file" => (ConfigArgKind::File, value.as_ref()),
_ => unreachable!("unexpected id {id:?}"),
},
)

View file

@ -458,29 +458,40 @@ fn env_overrides_layer() -> ConfigLayer {
layer
}
/// Configuration source/data provided as command-line argument.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ConfigArg {
/// Configuration source/data type provided as command-line argument.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ConfigArgKind {
/// `--config-toml=TOML`
Toml(String),
Toml,
/// `--config-file=PATH`
File(String),
File,
}
/// Parses `--config-toml` arguments.
pub fn parse_config_args(toml_strs: &[ConfigArg]) -> Result<Vec<ConfigLayer>, ConfigLoadError> {
pub fn parse_config_args(
toml_strs: &[(ConfigArgKind, &str)],
) -> Result<Vec<ConfigLayer>, ConfigLoadError> {
// It might look silly that a layer is constructed per argument, but
// --config-toml argument can contain a full TOML document, and it makes
// sense to preserve line numbers within the doc. If we add
// --config=KEY=VALUE, multiple values might be loaded into one layer.
let source = ConfigSource::CommandArg;
toml_strs
.iter()
.map(|arg| match arg {
ConfigArg::Toml(text) => ConfigLayer::parse(source, text),
ConfigArg::File(path) => ConfigLayer::load_from_file(source, path.into()),
})
.try_collect()
let mut layers = Vec::new();
for (kind, chunk) in &toml_strs.iter().chunk_by(|&(kind, _)| kind) {
match kind {
ConfigArgKind::Toml => {
for (_, text) in chunk {
layers.push(ConfigLayer::parse(source, text)?);
}
}
ConfigArgKind::File => {
for (_, path) in chunk {
layers.push(ConfigLayer::load_from_file(source, path.into())?);
}
}
}
}
Ok(layers)
}
/// Command name and arguments specified by config.