#struct-fields #string #template-string #closures #templating #selector

struct-string-template

结构体字段上的简单字符串模板语言

1个不稳定版本

0.1.0 2023年5月16日

#449模板引擎

MIT/Apache

15KB
281

概述

此crate定义了一种简单的模板语言,格式为%(SELECTOR),可以在结构体上运行。给定的SELECTOR通过闭包Fn(&T) -> Option<String>访问类型为T的结构体。使用闭包允许复杂的逻辑访问结构体,例如,“如果字段x不存在,则尝试字段y,否则返回默认值或None”。

(此库绝对不是生产就绪的)

术语

  • 模板 是一个字符串 %(X),其中 X 是一个 选择器
  • 选择器 是任何不包含圆括号的字符串(包括空字符串)
  • 与给定 选择器 关联的闭包称为 访问器
  • 格式字符串 是包含零个或多个模板以及其他非模板字符的字符串,例如 %(id) - %(title)

快速入门

Cargo.toml

[dependencies]
struct_string_template = "0.1.0"

假设我们有一个 struct 定义和一个 struct 实例

struct Book {
    id: i64,
    title: String,
    author: String,
    contributors: Option<String>
}

let my_book = Book {
    id: 9784832275492,
    title: "Hidamari Sketch".to_owned(),
    author: "蒼樹うめ".to_owned(),
    contributors: None,
};

定义一个格式字符串

let format_string = "[%(id)] %(title) %(所有作者)";

通过执行以下操作构建 Templater<Book>

use struct_string_template::TemplaterBuilder;

let templater = TemplaterBuilder::<Book>::new()
    .with_selector("id", |book| Some(book.id.to_string()))
    .with_selector("title", |book| Some(book.title.clone()))
    .with_selector("所有作者", |book| {
        Some(format!("(By: {}{})",
            &book.author,
            &book.contributors.clone().map(|x| format!(", {}", x)).or(Some("".to_owned())).unwrap())
        )
    })
    .build();

使用 Templaterrender 函数进行渲染

let result = templater.render(&my_book, format_string).ok().unwrap();
println!("{}", &result);

高级用法

不使用 TemplateBuilder 构建 Templater

如果需要迭代地构建 Templater 而不是使用构建器类,则使用 Templater::new(),然后使用 insertextend 方法添加闭包。

let mut templater = Templater::<Book>::new();
templater.insert("id", |book| Some(book.id.to_string()));
templater.insert("title", |book| Some(book.title.clone()));
templater.insert("所有作者", |book| {
    Some(format!("(By: {}{})",
        &book.author,
        &book.contributors.clone().map(|x| format!(", {}", x)).or(Some("".to_owned())).unwrap())
    )
});

格式化器

如果您打算多次使用格式化字符串,可以使用类似于正则表达式的“预编译”它,以使用 Formatter 类(render 将格式化字符串内部转换为 Formatter)来提高性能,然后传递 Formatter 变量到 renderf 函数

use struct_string_template::Formatter;

let formatter = Formatter::build(format_string).ok().unwrap();
let result = templater.renderf(&my_book, &formatter);
println!("{}", &result);

错误处理

有关抛出的错误,请参阅 src/err.rs

模板规则

在本节中,X 是任何 选择器

  1. %% 被视为一个字面量 %
  2. % 后跟一个不是 ( 的字符(或字符串的结尾)是无效的
  3. %(X) 总是有效的
  4. %(X)A 其中 A 是任何有效的字符串是有效的
  5. %(X(模板未终止)是无效的
  6. 没有与 X 关联的闭包是无效的
  7. 如果结构上闭包的返回值为 None,则打印 NA。这目前无法配置,除非修改闭包本身。

限制

由于闭包类型,当前无法复制 Templater 对象,因为存在这个问题。我尚未找到解决方案。

动机

我在几个个人应用程序中使用这个库,并发现保持库更改在不同应用程序之间同步很麻烦。

依赖关系

~0.8–1.4MB
~27K SLoC