#golang #模板 #模板

gtmpl

Rust的Golang模板语言

23次发布

0.7.1 2021年8月6日
0.7.0 2021年6月7日
0.6.0 2021年1月3日
0.5.7 2019年11月21日
0.2.1 2017年11月18日

#52模板引擎 类别

Download history 3194/week @ 2024-03-14 2532/week @ 2024-03-21 1940/week @ 2024-03-28 2067/week @ 2024-04-04 2424/week @ 2024-04-11 2300/week @ 2024-04-18 3363/week @ 2024-04-25 4033/week @ 2024-05-02 3441/week @ 2024-05-09 3820/week @ 2024-05-16 3285/week @ 2024-05-23 3061/week @ 2024-05-30 3331/week @ 2024-06-06 3401/week @ 2024-06-13 2700/week @ 2024-06-20 2108/week @ 2024-06-27

12,090 每月下载量
7 个 包中使用

MIT 许可协议

175KB
5K SLoC

gtmpl-rust – Rust的Golang模板

Latest Version


gtmpl-rust 为Rust提供了 Golang text/template 引擎,这使得Rust应用程序可以无缝集成到围绕 kubernetesdocker 等devops工具的世界中。

入门

将以下依赖项添加到您的Cargo清单中...

[dependencies]
gtmpl = "0.7"

并查看文档

它还不是完美的。欢迎提出帮助和建议。

一些示例

基本模板

use gtmpl;

fn main() {
    let output = gtmpl::template("Finally! Some {{ . }} for Rust", "gtmpl");
    assert_eq!(&output.unwrap(), "Finally! Some gtmpl for Rust");
}

添加自定义函数

use gtmpl_value::Function;
use gtmpl::{FuncError, gtmpl_fn, template, Value};

fn main() {
    gtmpl_fn!(
    fn add(a: u64, b: u64) -> Result<u64, FuncError> {
        Ok(a + b)
    });
    let equal = template(r#"{{ call . 1 2 }}"#, Value::Function(Function { f: add }));
    assert_eq!(&equal.unwrap(), "3");
}

将结构体作为上下文传递

use gtmpl_derive::Gtmpl;

#[derive(Gtmpl)]
struct Foo {
    bar: u8
}

fn main() {
    let foo = Foo { bar: 42 };
    let output = gtmpl::template("The answer is: {{ .bar }}", foo);
    assert_eq!(&output.unwrap(), "The answer is: 42");
}

在上下文中调用 方法


use gtmpl_derive::Gtmpl;
use gtmpl::{Func, FuncError, Value};

fn plus_one(args: &[Value]) -> Result<Value, FuncError> {
    if let Value::Object(ref o) = &args[0] {
        if let Some(Value::Number(ref n)) = o.get("num") {
            if let Some(i) = n.as_i64() {
                return Ok((i +1).into())
            }
        }
    }
    Err(anyhow!("integer required, got: {:?}", args))
}

#[derive(Gtmpl)]
struct AddMe {
    num: u8,
    plus_one: Func
}

fn main() {
    let add_me = AddMe { num: 42, plus_one };
    let output = gtmpl::template("The answer is: {{ .plus_one }}", add_me);
    assert_eq!(&output.unwrap(), "The answer is: 43");
}

当前限制

这是一个正在进行中的项目。目前不支持以下功能:

  • 复数
  • 以下函数尚未实现:
    • htmljs
  • printf 尚未完全稳定,但应支持所有 合理 输入

增强

尽管它从未打算扩展Golang text/template的语法,但仍可能有一些方便的添加

动态模板

在您的 Cargo.toml 中启用 gtmpl_dynamic_template

[dependencies.gtmpl]
version = "0.7"
features = ["gtmpl_dynamic_template"]

现在您可以为 template 操作提供动态模板名称。

示例

use gtmpl::{Context, Template};

fn main() {
    let mut template = Template::default();
    template
        .parse(
            r#"
            {{- define "tmpl1"}} some {{ end -}}
            {{- define "tmpl2"}} some other {{ end -}}
            there is {{- template (.) -}} template
            "#,
        )
        .unwrap();

    let context = Context::from("tmpl2");

    let output = template.render(&context);
    assert_eq!(output.unwrap(), "there is some other template".to_string());
}

以下语法被使用:

{{template (pipeline)}}
	The template with the name evaluated from the pipeline (parenthesized) is
    executed with nil data.

{{template (pipeline) pipeline}}
	The template with the name evaluated from the first pipeline (parenthesized)
    is executed with dot set to the value of the second pipeline.

上下文

我们使用 gtmpl_value 的 Value 作为内部数据类型。 gtmpl_derive 提供了一个方便的 derive 宏,用于为 Value 生成 From 实现方法。

参见

为什么我们需要这个?

为什么?亲爱的上帝,为什么?我都能想象到有人会问,为什么有人会做这种事情。当第一次需要为 docker 编写一些自定义格式化字符串时,我并不是一个 Go 语言的模板的大粉丝。学习一种新的模板语言通常不是人们期待的事情。大多数人都会完全避免它。然而,如果你在寻找比完整的 DSL 更轻量级的自动化工具,它实际上是非常有用的。

这主要的原因是为了使在 Rust 中编写感觉更本地的 DevOps 工具变得更加容易。 dockerhelmkubernetes)使用 Go 语言模板,如果围绕这些模板的工具使用相同的模板,则会感觉更自然。

依赖项

~0.4–1MB
~21K SLoC