22 个不稳定版本 (3 个破坏性更新)
0.4.3 | 2024年2月11日 |
---|---|
0.4.2 | 2024年1月6日 |
0.3.7 | 2023年11月1日 |
0.3.6 | 2023年10月17日 |
0.1.6 | 2023年9月23日 |
#43 in 模板引擎
176 每月下载量
用于 nadi_core
75KB
1.5K SLoC
string-template-plus
简介
这是一个简单的模板工具,它使用变量名和 HashMap
的 String
。可以从 [str
] 解析 Template
,然后您可以使用 HashMap
中的变量和通过 Exec
运行的任何 shell 命令来渲染它。
功能
- 从易于编写的
str
解析模板 - 支持可选变量,如果某些变量不存在,则使用
?
分隔可选项,使用它找到的第一个。如果?
在末尾,则留空而不是报错。 - 支持可选选项中的文字字符串,如果您想在末尾放置空字符串而不是空白,则可以使用包含在
"string"
中的文字字符串"
作为可选项。 - 支持使用
chrono
的日期时间格式,您可以在变量占位符{}
内使用以%
开头的任何格式,以使用 chrono 支持的日期时间格式。 - 支持任何任意命令等。您可以将任何命令放在
$(
和)
内部运行,并在模板中使用结果。您可以在其中使用其他格式元素。 - 支持使用相同模板条件迭代(使用 -N 增量)字符串
- 有限的格式化支持,如 UPCASE、downcase、float significant digits 等。有关更多信息,请参阅
transformers
。
用法
简单变量
#
let templ = Template::parse_template("hello {name}").unwrap();
let mut vars: HashMap<String, String> = HashMap::new();
vars.insert("name".into(), "world".into());
let rendered = templ
.render(&RenderOptions {
variables: vars,
..Default::default()
})
.unwrap();
assert_eq!(rendered, "hello world");
安全替换,如果不存在则留空,或者使用字面字符串
#
let templ = Template::parse_template("hello {name?} {lastname?\"User\"}").unwrap();
let vars: HashMap<String, String> = HashMap::new();
let rendered = templ
.render(&RenderOptions {
variables: vars,
..Default::default()
})
.unwrap();
assert_eq!(rendered, "hello User");
替代,找到的第一个变量将被替换
#
let templ = Template::parse_template("hello {nickname?name}").unwrap();
let mut vars: HashMap<String, String> = HashMap::new();
vars.insert("name".into(), "world".into());
let rendered = templ
.render(&RenderOptions {
variables: vars,
..Default::default()
})
.unwrap();
assert_eq!(rendered, "hello world");
计算可以写成类似于 lisp 的语言,它支持简单函数。使用 lisp 还可以使您编写更复杂的逻辑。lisp 的实现来自 https://github.com/brundonsmith/rust_lisp,有关功能请参阅那里的 README。
要访问 lisp 中的值,您可以使用以下函数
st+var
: 将值作为字符串,st+num
将值作为数字,以及st+has
如果值存在则返回 true,否则返回 false。
您需要引用符号以传递给函数(例如 (st+num 'total))。
否则,您也可以像正常一样在花括号中写入变量。
#
let templ = Template::parse_template("hello {nickname?name}. You've done =(/ (st+num 'task_done) (st+num 'task_total)) work.").unwrap();
let mut vars: HashMap<String, String> = HashMap::new();
vars.insert("name".into(), "world".into());
vars.insert("task_done".into(), "1".into());
vars.insert("task_total".into(), "4".into());
let rendered = templ
.render(&RenderOptions {
variables: vars,
..Default::default()
})
.unwrap();
assert_eq!(rendered, "hello world. You've done 0.25 work.");
自定义命令
#
let templ = Template::parse_template("L=$(printf \"%.2f\" {length})").unwrap();
let mut vars: HashMap<String, String> = HashMap::new();
vars.insert("length".into(), "12.342323".into());
let rendered = templ
.render(&RenderOptions {
wd: PathBuf::from("."),
variables: vars,
shell_commands: true,
})
.unwrap();
assert_eq!(rendered, "L=12.34");
您可以选择关闭自定义命令以确保安全
#
let templ = Template::parse_template("L=$(printf \"%.2f\" {length})").unwrap();
let mut vars: HashMap<String, String> = HashMap::new();
vars.insert("length".into(), "12.342323".into());
let rendered = templ
.render(&RenderOptions {
wd: PathBuf::from("."),
variables: vars,
shell_commands: false,
})
.unwrap();
assert_eq!(rendered, "L=$(printf %.2f 12.342323)");
日期和时间
#
let templ = Template::parse_template("hello {name} at {%Y-%m-%d}").unwrap();
let timefmt = Local::now().format("%Y-%m-%d");
let output = format!("hello world at {}", timefmt);
let mut vars: HashMap<String, String> = HashMap::new();
vars.insert("name".into(), "world".into());
let rendered = templ
.render(&RenderOptions {
wd: PathBuf::from("."),
variables: vars,
shell_commands: false,
})
.unwrap();
assert_eq!(rendered, output);
转换器
尽管没有格式字符串,但有一些转换函数可以进行格式化。我计划根据需要添加更多格式函数。
要将转换器应用于变量,请在变量模板后提供它 VAR_TRANSFORM_SEP_CHAR
(目前为 “:”)。
有几个可用的转换器
转换器 | 函数 | 参数 | 函数 | 示例 |
---|---|---|---|---|
f | 转换器::float_format |
[.]N | 仅显示 N 位小数 | {"1.12":f(.1)} ⇒ 1.1 |
case | 转换器::string_case |
up | 将字符串转换为大写 | {"na":case(up)} ⇒ NA |
case | 转换器::string_case |
down | 将字符串转换为小写 | {"nA":case(down)} ⇒ na |
case | 转换器::string_case |
proper | 将首字母转换为大写 | {"nA":case(proper)} ⇒ Na |
case | 转换器::string_case |
title | 将字符串转换为标题大小写 | {"na":case(title)} ⇒ Na |
calc | 转换器::calc |
[+-*/^]N | 算术计算 | {"1":calc(+1*2^2)} ⇒ 16 |
calc | 转换器::calc |
[+-*/^]N | 算术计算 | {"1":calc(+1,-1)} ⇒ 2,0 |
count | 转换器::count |
str | 计算字符串中 str 的出现次数 | {"nata":count(a)} ⇒ 2 |
repl | 转换器::replace |
str1,str2 | 将 str1 替换为 str2 | {"nata":rep(a,o)} ⇒ noto |
q | 转换器::quote |
[str1] | 使用 str1 引用,或 "" | {"nata":q()} ⇒ "noto" |
take | 转换器::take |
str,N | 通过 str 分隔 N 组 | {"nata":take(a,2)} ⇒ "t" |
trim | 转换器::trim |
str | 使用 str 去除字符串 | {"nata":trim(a)} ⇒ "nat" |
您可以将转换器依次链接以进行组合操作。例如,count( ):calc(+1)
将提供句子中单词的总数。
示例代码位于transformers
中的各个函数中。
#
let mut vars: HashMap<String, String> = HashMap::new();
vars.insert("length".into(), "120.1234".into());
vars.insert("name".into(), "joHN".into());
vars.insert("job".into(), "assistant manager of company".into());
let options = RenderOptions {
variables: vars,
..Default::default()
};
let cases = [
("L={length}", "L=120.1234"),
("L={length:calc(+100)}", "L=220.1234"),
("L={length:f(.2)} ({length:f(3)})", "L=120.12 (120.123)"),
("hi {name:case(up)}", "hi JOHN"),
(
"hi {name:case(proper)}, {job:case(title)}",
"hi John, Assistant Manager of Company",
),
("hi {name:case(down)}", "hi john"),
];
for (t, r) in cases {
let templ = Template::parse_template(t).unwrap();
let rendered = templ.render(&options).unwrap();
assert_eq!(rendered, r);
}
局限性
- 在这个模板系统中,您不能使用位置参数,只能使用命名参数。代码
{}
将被替换为空字符串。尽管您可以使用"0"
、"1"
等作为模板和渲染选项变量的变量名,但最好保持名称标识符友好。 - 虽然应该可以工作,但我没有测试过各种名称。
- 目前没有格式说明符,现在您可以使用带有
printf
bash命令的命令选项来按照您想要的方式格式化内容,或者使用具有有限格式化功能的transformers。例如,模板this is $(printf "%05.2f" {weight}) kg.
应该以正确的浮点格式渲染。
许可证:GPL-3.0-only
依赖关系
~4–15MB
~132K SLoC