diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-06-29 03:54:54 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-06-29 03:54:54 +0800 |
| commit | ca7527681b609fedc368ea973022b004469035e6 (patch) | |
| tree | 47109782fa5a4435889d93a823db3a4e1f5e7bd6 /just_template | |
| parent | ba15b7c06468cb6c52c8d2a53419fd83f9ebcb8b (diff) | |
feat(just_template): add proc-macro `tmpl!` and restructure crate
Move the old `tmpl!` and `tmpl_param!` macros into a dedicated
`just_template_macros` proc-macro crate. The new `tmpl!` macro supports
both simple parameter assignment and multi-arm implementation blocks
with per-arm overrides. Remove the deprecated `deprecated` module and
update tests accordingly.
Diffstat (limited to 'just_template')
| -rw-r--r-- | just_template/Cargo.toml | 1 | ||||
| -rw-r--r-- | just_template/src/deprecated.rs | 45 | ||||
| -rw-r--r-- | just_template/src/lib.rs | 60 | ||||
| -rw-r--r-- | just_template/src/template.rs | 9 | ||||
| -rw-r--r-- | just_template/src/test_expand.rs (renamed from just_template/src/test.rs) | 2 | ||||
| -rw-r--r-- | just_template/src/test_macros.rs | 186 |
6 files changed, 205 insertions, 98 deletions
diff --git a/just_template/Cargo.toml b/just_template/Cargo.toml index 66217b4..1536e0b 100644 --- a/just_template/Cargo.toml +++ b/just_template/Cargo.toml @@ -10,4 +10,5 @@ license = "MIT OR Apache-2.0" repository = "https://github.com/catilgrass/just_template" [dependencies] +just_template_macros.workspace = true just_fmt = "0.1.2" diff --git a/just_template/src/deprecated.rs b/just_template/src/deprecated.rs deleted file mode 100644 index b218969..0000000 --- a/just_template/src/deprecated.rs +++ /dev/null @@ -1,45 +0,0 @@ -#[macro_export] -macro_rules! tmpl_param { - ($template:ident, $($key:ident = $value:expr),* $(,)?) => {{ - $( - $template.insert_param(stringify!($key).to_string(), $value.to_string()); - )* - }}; -} - -#[macro_export] -macro_rules! tmpl { - ($template:ident, $($name:ident { - $($key:ident = $value:expr),* $(,)? - }),* $(,)?) => {{ - $( - let $name = $template.add_impl(stringify!($name).to_string()); - $( - $name.push({ - let mut params = std::collections::HashMap::new(); - params.insert(stringify!($key).to_string(), $value.to_string()); - params - }); - )* - )* - }}; - - // Old syntax - ($template:ident += { - $($name:ident { - $(($($key:ident = $value:expr),* $(,)?)),* - $(,)? - }),* - }) => {{ - $( - let $name = $template.add_impl(stringify!($name).to_string()); - $( - $name.push({ - let mut params = std::collections::HashMap::new(); - $(params.insert(stringify!($key).to_string(), $value.to_string());)* - params - }); - )* - )* - }}; -} diff --git a/just_template/src/lib.rs b/just_template/src/lib.rs index 7ff77f5..2b4f986 100644 --- a/just_template/src/lib.rs +++ b/just_template/src/lib.rs @@ -1,58 +1,14 @@ //! Template struct for storing template strings and their parameters. -//! -//! The template supports two types of parameters: -//! - Simple parameters: key-value pairs used to replace simple placeholders (`<<<key>>>` format) in the template. -//! - Implementation parameters: for implementation blocks (`>>>>>>>>> block_name` and `@@@ >>> block_name` format), -//! can contain multiple parameter sets, each corresponding to an implementation instance. -//! -//! # Examples -//! ``` -//! use just_template::Template; -//! -//! let mut tmpl = Template::from("Hello, <<<name>>>!".to_string()); -//! tmpl.insert_param("name".to_string(), "World".to_string()); -//! assert_eq!(tmpl.to_string(), "Hello, World!"); -//! ``` -//! -//! Using the `tmpl_param!` macro makes it easier to add simple parameters: -//! ``` -//! use just_template::{Template, tmpl_param}; -//! -//! let mut tmpl = Template::from("<<<a>>> + <<<b>>> = <<<c>>>".to_string()); -//! tmpl_param!(tmpl, a = 1, b = 2, c = 3); -//! assert_eq!(tmpl.to_string(), "1 + 2 = 3"); -//! ``` -//! -//! Using the `tmpl!` macro adds implementation block parameters: -//! ``` -//! use just_template::{Template, tmpl}; -//! -//! let mut tmpl = Template::from(" -//! >>>>>>>>>> arms -//! @@@ >>> arms -//! <<<crate_name>>> => Some(<<<crate_name>>>::exec(data, params).await), -//! @@@ <<< -//! ".trim().to_string()); -//! tmpl!(tmpl, -//! arms { -//! crate_name = "my", -//! crate_name = "you", -//! } -//! ); -//! // Output the expanded template -//! let expanded = tmpl.to_string(); -//! assert_eq!(expanded, " -//! my => Some(my::exec(data, params).await), -//! you => Some(you::exec(data, params).await), -//! ".trim().to_string()); -//! ``` + +mod expand; + mod template; -pub use template::*; // Re-export template to just_template +pub use template::*; // Re-export template -pub mod expand; +pub use just_template_macros::*; // Re-export macros #[cfg(test)] -pub mod test; +pub mod test_expand; -#[deprecated] -pub mod deprecated; +#[cfg(test)] +pub mod test_macros; diff --git a/just_template/src/template.rs b/just_template/src/template.rs index e368917..953d7a5 100644 --- a/just_template/src/template.rs +++ b/just_template/src/template.rs @@ -1,9 +1,18 @@ use std::collections::HashMap; +/// Template struct, used to represent a template composed of a template string and parameters. +/// +/// # Fields +/// - `template_str` - Template string containing placeholders. +/// - `params` - Normal parameters, key-value mappings. +/// - `impl_params` - Implementation block parameters, where each implementation block name corresponds to a list of parameter maps (each parameter map is a key-value mapping). #[derive(Default, Clone)] pub struct Template { + /// Template string containing placeholders such as `{{param_name}}`. pub(crate) template_str: String, + /// Normal parameters, keyed by parameter name with values as parameter values. pub(crate) params: HashMap<String, String>, + /// Implementation block parameters, keyed by implementation block name with values as a list of parameter maps. pub(crate) impl_params: HashMap<String, Vec<HashMap<String, String>>>, } diff --git a/just_template/src/test.rs b/just_template/src/test_expand.rs index ca7b357..9132f6e 100644 --- a/just_template/src/test.rs +++ b/just_template/src/test_expand.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use crate::template::Template; +use crate::Template; #[test] fn basic_param() { diff --git a/just_template/src/test_macros.rs b/just_template/src/test_macros.rs new file mode 100644 index 0000000..5be58f5 --- /dev/null +++ b/just_template/src/test_macros.rs @@ -0,0 +1,186 @@ +use crate::Template; +use crate::tmpl; + +#[test] +fn basic_param() { + let mut tmpl = Template::from("Hello, <<<name>>>!".to_string()); + + tmpl!(tmpl, name = "World"); + // tmpl.insert_param("name".to_string(), "World".to_string()); + + assert_eq!(tmpl.expand().unwrap(), "Hello, World!"); +} + +#[test] +fn multi_param() { + let mut tmpl = Template::from("<<<a>>> + <<<b>>> = <<<c>>>".to_string()); + + tmpl! { + // tmpl, // Template named tmpl can be omitted + a = "1", + b = "2", + c = "3", + }; + + assert_eq!(tmpl.expand().unwrap(), "1 + 2 = 3"); +} + +#[test] +fn impl_blocks() { + let mut tmpl = Template::from( + r#" +>>>>>>>>>> arms +@@@ >>> arms + "<<<crate_name>>>" => Some(<<<crate_name>>>::exec(data, params).await), +@@@ <<< +"# + .trim() + .to_string(), + ); + + tmpl! { + arms { + crate_name = "my", + crate_name = "you", + } + } + + let expanded = tmpl.expand().unwrap(); + assert!(expanded.contains(r#""my" => Some(my::exec(data, params).await)"#)); + assert!(expanded.contains(r#""you" => Some(you::exec(data, params).await)"#)); +} + +#[test] +fn display_block_global_hidden_by_default() { + let tmpl = Template::from( + r#" +visible line +??? >>> debug + hidden line +??? <<< +visible end +"# + .trim() + .to_string(), + ); + + let expanded = tmpl.expand().unwrap(); + assert!(expanded.contains("visible line")); + assert!(expanded.contains("visible end")); + assert!(!expanded.contains("hidden line")); +} + +#[test] +fn display_block_global_shown_via_param() { + let mut tmpl = Template::from( + r#" +visible line +??? >>> debug + shown line +??? <<< +visible end +"# + .trim() + .to_string(), + ); + + tmpl! { + debug = true, + } + + let expanded = tmpl.expand().unwrap(); + assert!(expanded.contains("visible line")); + assert!(expanded.contains("visible end")); + assert!(expanded.contains("shown line")); +} + +#[test] +fn display_block_inside_impl_area_hidden_by_default() { + let mut tmpl = Template::from( + r#" +>>>>>>>>>> arms +@@@ >>> arms + <<<crate_name>>> => exec, +??? >>> extra + <<<crate_name>>> => metrics, +??? <<< +@@@ <<< +"# + .trim() + .to_string(), + ); + + tmpl! { + arms { + crate_name = "my" + } + } + + let expanded = tmpl.expand().unwrap(); + assert!(expanded.contains(r#"my => exec"#)); + assert!(!expanded.contains(r#"my => metrics"#)); +} + +#[test] +fn display_block_inside_impl_area_shown_by_global_param() { + let mut tmpl = Template::from( + r#" +>>>>>>>>>> arms +@@@ >>> arms + <<<crate_name>>> => exec, +??? >>> extra + <<<crate_name>>> => metrics, +??? <<< +@@@ <<< +"# + .trim() + .to_string(), + ); + + tmpl! { + extra = true, + arms { + crate_name = "my", + crate_name = "you" + } + } + + let expanded = tmpl.expand().unwrap(); + assert!(expanded.contains(r#"my => exec"#)); + assert!(expanded.contains(r#"my => metrics"#)); + assert!(expanded.contains(r#"you => exec"#)); + assert!(expanded.contains(r#"you => metrics"#)); +} + +#[test] +fn display_block_inside_impl_area_shown_by_arm_param() { + let mut tmpl = Template::from( + r#" +>>>>>>>>>> arms +@@@ >>> arms + <<<crate_name>>> => exec, +??? >>> extra + <<<crate_name>>> => metrics, +??? <<< +@@@ <<< +"# + .trim() + .to_string(), + ); + + tmpl! { + arms { + crate_name = "my", + { + crate_name = "you", + extra = true + } + } + } + + let expanded = tmpl.expand().unwrap(); + assert!(expanded.contains(r#"my => exec"#)); + assert!(!expanded.contains(r#"my => metrics"#)); + assert!(expanded.contains(r#"you => exec"#)); + assert!(expanded.contains(r#"you => metrics"#)); +} |
