首页
/ 入门 / 万物皆可生成
万物皆可生成
CUE 在配置管理方面非常出色,而且解决了大量目前我们其他选择的根本问题。
虽然这是大多数人使用 CUE 的主要使用场景,但是实际上可以用 CUE 生成任何东西。
怎么可能?可以用 text/template 包来渲染任何我们想要的文件。
用 CUE 生成
first.cue
package gen
import "text/template"
data: {
// meta info
name: *"tasks" | string @tag(name)
msg: "Hello \(name), welcome to Cuetorials"
// task list
tasks: [
{name: "t1", effort: 1, complete: true},
{name: "t2", effort: 4, complete: true},
{name: "t3", effort: 3, complete: false},
{name: "t4", effort: 2, complete: true},
{name: "t5", effort: 3, complete: false},
]
// grouped tasks
complete: [ for t in tasks if t.complete == true {t}]
incomplete: [ for t in tasks if t.complete == false {t}]
}
// Templates which use Go's template engine
templates: [
{
filename: "\(data.name)-todo.txt"
contents: """
{{ .msg }}
--- TODO ---
{{ range $T := .incomplete -}}
{{ printf "%-4s%v" $T.name $T.effort }}
{{ end }}
"""
}, {
filename: "\(data.name)-done.txt"
contents: """
Here's what you have finished \(data.name). Good job!
--- DONE ---
{{ range $T := .complete -}}
{{ $T.name }}
{{ end }}
"""
},
]
// The rendered output from data+templates
rendered: [ for T in templates {
filename: T.filename
contents: template.Execute(T.contents, data)
}]
first_tool.cue
package gen
import (
"tool/file"
)
command: "gen": {
for i, R in rendered {
// make a unique name when comprehending
"write-\(i)": file.Create & {
filename: R.filename
contents: R.contents
}
}
}
cue cmd -t "name=bob" gen
CUE 的模板系统使用的 Go 的模板系统,所以所有的兼容性和规则都是一样的。
我们使用了 list 和 field 推导分别渲染和写入我们的模板,使用复杂的 CUE 定义、值以及模板你可以生成任何输出。
使用 Hof 生成
在 Hofstadter,我们使用 hof 用于复杂的代码生成,
我们希望可以通过唯一的来源来生成数据库、后端以及前端的代码。
我们认为对于开发这来说是,这是 high code (low code)的解决方案,CUE 被选为 UX/DX 来写输入(设计)和生成器。
之前系统的两个问题是:
你总会在生成的代码中编写自定义的代码
设计发展了,但是你已经生成了样板代码
解决方案实际上非常简单,保留最初生成代码代码的副本,然后使用 3-way diff 工具来合并设计更新和自定义的代码。
将下面两个文件放到同一个文件夹,然后运行 hof mod vendor cue 和 hof gen
cue.mods
module cuetorials.com/gen-with-hof
cue 0.4.0
require (
github.com/hofstadter-io/hof v0.5.17
)
hof.cue
package gen
import (
// import hof's generator schema
"github.com/hofstadter-io/hof/schema/gen"
)
// A schema for our generator's input
#Input: {
name: string
todos: [...{
name: string
effort: int
complete: bool
}]
}
// create a generator
#Gen: gen.#HofGenerator & {
// We often have some input values for the user to provide.
// Use a Cue definition to enforce a schema
Input: #Input
// Required filed for generator definitions, details can be found in the hof docs
PackageName: "dummy"
// Required field for a generator to work, the list of files to generate
Out: [...gen.#HofGeneratorFile] & [
todo,
done,
debug,
]
// In is supplied as the root data object to every template
// pass user inputs to the tempaltes here, possibly modified, enhanced, or transformed
In: {
INPUT: Input
Completed: _C
Incomplete: _I
}
// calculate some internal data from the input
_C: [ for t in Input.todos if t.complete == true {t}]
_I: [ for t in Input.todos if t.complete == false {t}]
// the template files
todo: {
Template: """
Hello {{ .INPUT.name }}.
The items still on your todo list:
{{ range $T := .Incomplete -}}
{{ printf "%-4s%v" $T.name $T.effort }}
{{ end }}
"""
// The output filename, using string interpolation
Filepath: "\(Input.name)-todo.txt"
}
done: {
Template: """
Here's what you have finished {{ .INPUT.name }}. Good job!
{{ range $T := .Completed -}}
{{ $T.name }}
{{ end }}
"""
Filepath: "\(Input.name)-done.txt"
}
// useful helper
debug: {
Template: """
{{ yaml . }}
"""
Filepath: "debug.yaml"
}
}
// Add the @gen(
Gen: _ @gen(todos)
// Construct the generator
Gen: #Gen & {
Input: {
name: "tasks"
todos: [
{name: "t1", effort: 1, complete: true},
{name: "t2", effort: 4, complete: true},
{name: "t3", effort: 3, complete: false},
{name: "t4", effort: 2, complete: true},
{name: "t5", effort: 3, complete: false},
]
}
}
你可以通过下面的链接了解更多 hof 相关的内容:
https://github.com/hofstadter-io/hof
https://docs.hofstadter.io
也有许多 hofmod 的仓库用于生成 CLI、API 以及更多其他内容,
hofmod 和 hof 工具的分离意味着你可以创建你自己的而不需要修改我们的代码。
因为它们也是 CUE 的模块,所以你可以使用 CUE 的所有功能,也可以引用它们来重用并扩展你自己的生成器和项目。
CUE 脚本
模版
Hofstadter CUE 支持和培训
发布时间: 2025-04-25
编辑本页
创建页面 issue
创建项目 issue
我们绝不会将你的邮箱分享给任何人。