Nested params

This commit is contained in:
bluepython508
2023-12-09 22:27:53 +00:00
parent 342a364aed
commit 8482b7fea0
3 changed files with 50 additions and 11 deletions

View File

@@ -1 +1 @@
abc 123 {{ name }} abc 123 {{ name }} {{ nested.param }}

View File

@@ -61,8 +61,7 @@ fn run(
"Expected {} to be empty or not exist", "Expected {} to be empty or not exist",
destination.display() destination.display()
); );
// let destination = destination.canonicalize()?; let params = Params::from_kv(params)?;
let params = Params(params.into_iter().collect());
context::Context::load(template, params)?.generate(destination)?; context::Context::load(template, params)?.generate(destination)?;

View File

@@ -1,7 +1,7 @@
use eyre::Result; use eyre::{bail, Result};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tracing::instrument;
use std::{collections::HashMap, convert::Infallible, path::PathBuf, str::FromStr}; use std::{collections::HashMap, convert::Infallible, path::PathBuf, str::FromStr};
use tracing::instrument;
#[derive(Debug, Clone, PartialEq, Deserialize)] #[derive(Debug, Clone, PartialEq, Deserialize)]
pub struct Manifest { pub struct Manifest {
@@ -34,7 +34,7 @@ impl Source {
Self::Path(relative) if relative.is_relative() => match self { Self::Path(relative) if relative.is_relative() => match self {
Self::Path(root) => Self::Path(root.join(relative)), Self::Path(root) => Self::Path(root.join(relative)),
}, },
other => other.clone() other => other.clone(),
} }
} }
@@ -48,7 +48,7 @@ impl Source {
#[instrument] #[instrument]
pub fn load(&self) -> Result<Vec<u8>> { pub fn load(&self) -> Result<Vec<u8>> {
match self { match self {
Self::Path(path) => Ok(std::fs::read(path)?) Self::Path(path) => Ok(std::fs::read(path)?),
} }
} }
} }
@@ -89,7 +89,8 @@ impl Transform {
} }
#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq)] #[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq)]
pub struct Params(pub HashMap<String, String>); #[serde(transparent)]
pub struct Params(toml::Table);
impl Params { impl Params {
pub fn load_user() -> Result<Self> { pub fn load_user() -> Result<Self> {
@@ -98,8 +99,47 @@ impl Params {
)?)) )?))
} }
pub fn merge(mut self, other: Self) -> Self { pub fn from_kv(it: impl IntoIterator<Item = (String, String)>) -> Result<Self> {
self.0.extend(other.0); it.into_iter()
self .map(|(k, v)| {
let toml::Value::Table(val) = k
.split('.')
.rev()
.fold(toml::Value::String(v), |v, k| {
toml::Value::Table(toml::Table::from_iter([(k.to_owned(), v)]))
})
else {
bail!("Key must not be empty")
};
Ok(Self(val))
})
.try_fold(Self::default(), |acc, param| Ok(acc.merge(param?)))
}
pub fn merge(self, other: Self) -> Self {
fn merge(v1: &mut toml::Value, v2: toml::Value) {
use toml::Value::*;
match (v1, v2) {
(Table(t1), Table(t2)) => {
for (k, v) in t2 {
match t1.entry(k) {
toml::map::Entry::Vacant(e) => {
e.insert(v);
}
toml::map::Entry::Occupied(e) => {
merge(e.into_mut(), v);
}
}
}
}
(v1, v2) => {
*v1 = v2;
}
}
}
let mut lhs = toml::Value::Table(self.0);
merge(&mut lhs, toml::Value::Table(other.0));
let toml::Value::Table(table) = lhs else { unreachable!() };
Self(table)
} }
} }