模板
mise 中的模板提供了一种强大的方式来配置环境和项目设置的不同方面。
模板是一个包含变量、表达式和控制结构的字符串。渲染时,模板引擎(tera)会用它们的值替换这些变量。
你可以在以下位置定义和使用模板:
- 大多数
mise.toml配置值mise.toml文件本身不支持模板,且必须是有效的 toml
.tool-versions文件.miserc.toml文件(上下文有限——参见 Template Support in .miserc.toml)。
示例
这是一个使用模板的 mise.toml 文件示例:
[env]
PROJECT_NAME = "{{ cwd | basename }}"
TERRAFORM_VERSION = "1.0.0"
[tools]
# 引用在此文件中定义的 env 变量
terraform = "{{ env.TERRAFORM_VERSION }}"
# 引用外部 env 变量
node = "{{ get_env(name='NODE_VERSION', default='20') }}"你可以在 食谱 中找到更多示例。
模板渲染
Mise 使用 tera 提供模板功能。 在模板中,有 3 种分隔符:
{{和}}用于表达式{%和%}用于语句{#和#}用于注释
此外,使用 raw 块来跳过 tera 分隔符的渲染:
{% raw %}
Hello {{ name }}
{% endraw %}这将变成 Hello {{name}}。
Tera 支持 字面量,包括:
- 布尔值:
true(或True)和false(或False) - 整数
- 浮点数
- 字符串:由
""、''或``包围的文本 - 数组:由
[和]包围的,以逗号分隔的字面量和/或标识符列表(允许末尾逗号)
你可以使用 {{ name }} 来渲染变量。 对于复杂属性,使用:
- 点号
.,例如{{ product.name }} - 方括号
[],例如{{ product["name"] }}
Tera 还支持强大的表达式:
- 数学表达式
+-/*%
- 比较
==!=>=<=<>
- 逻辑
andornot
- 连接
~,例如{{ "hello " ~ 'world' ~ `!` }} - in 检查,例如
{{ some_var in [1, 2, 3] }}
Tera 还支持控制结构,例如 if 和 for。
Tera v2 迁移
mise 使用 Tera v2。Tera v1 的部分语法和内置功能在 Tera v2 中发生了变化。mise 仍然可以出于兼容性考虑渲染许多旧模板。Tera v1 兼容性辅助功能将于 mise 2026.10.0 开始发出警告,并计划在 mise 2027.4.0 中移除。
在新模板中,建议优先使用以下 Tera v2 形式:
| Tera v1 模式 | Tera v2 替代形式 |
|---|---|
value | trim_start_matches(pat="v") | value | trim_start(pat="v") |
value | trim_end_matches(pat="-beta") | value | trim_end(pat="-beta") |
items | slice(start=0, end=2) | items[0:2] |
[base] | concat(with="file.txt") | [base, "file.txt"] |
[...items] | concat(with=extra_items) | [...items, ...extra_items] |
items | map(attribute="name") | [item.name for item in items] |
items | filter(attribute="active") | [item for item in items if item.active] |
value | as_str | value | str |
value | escape | value | escape_html |
value | linebreaksbr | value | newlines_to_br |
value is divisibleby(divisor=3) | value is divisible_by(divisor=3) |
value is object | value is map |
value | indent(prefix=">") | 仅处理空格时使用 value | indent(width=1) |
value | truncate | value | truncate(length=255) |
Tera v2 还增加了有用的语法,可以替代许多旧的辅助过滤器:
- 数组和字符串切片,例如
parts[0:2]、parts[-1]和name[::-1] - 数组和映射展开,例如
[first, ...rest]和{...base, key: value} - 列表推导式,例如
[tool.name for tool in tools if tool.active] - 可选链,例如
env?.NODE_ENV or "development" - 三元表达式,例如
"prod" if release else "dev"
并非所有 Tera v1 的行为都能实现兼容。Tera v2 中对未定义变量的访问更加严格, 并且 mise 模板不支持 Tera v1 宏。作为临时的退出方案,在运行 mise 前设置 MISE_TERA_V1=1,即可使用 Tera v1 渲染模板。在共享的 mise.toml 文件中, 建议使用向后兼容的环境变量形式,因为较旧版本的 mise 会将其视为普通环境变量, 而不会因未知设置而失败:
[env]
MISE_TERA_V1 = true较新的 [settings] tera_v1 = true 形式也适用于支持该设置的 mise 版本, 但与旧版本的兼容性较差。启用后,所有常规配置和任务模板都会使用实际的 Tera v1 引擎及其原始语法和内置功能。不启用时,模板将使用 Tera v2 以及下文所述的 辅助功能。该退出方案计划在 mise 2027.4.0 中移除。由于 miserc 文件会在加载设置前 进行渲染,因此加载 miserc 本身时不适用。
Tera 过滤器
你可以使用过滤器修改变量。 可以通过管道符号(|)过滤变量,并可以在括号中提供命名参数。 你还可以串联多个过滤器。 例如,{{ "Doctor Who" | lower | replace(from="doctor", to="Dr.") }} 将输出 Dr. who。
Tera 函数
函数为模板提供 额外功能。
Tera 测试
你还可以使用测试检查变量。
{% if my_number is not odd %}
偶数
{% endif %}Mise 模板功能
Mise 在 tera 功能的基础上提供了额外的变量、函数、过滤器和测试。
变量
Mise 暴露了多个变量。 这些变量提供了有关当前环境的关键信息:
env: HashMap<String, String>– 以键值映射的形式访问当前环境变量vars: HashMap<String, String>– 访问用户定义的配置变量cwd: PathBuf– 指向当前工作目录config_root: PathBuf– 定位包含mise.toml文件的目录;例如,对于~/src/myproj/.config/mise.toml这样的路径,它将指向~/src/myprojconfig_source: String– 模板本身所在的配置文件,以绝对路径表示。与config_root不同,它指向的是文件本身,而不是该文件所属的项目,并且不会解析符号链接——如果你想获取真实文件所在的位置,请通过canonicalize处理。可用于mise.toml、.tool-versions、[env]指令和[settings.age];任务文件模板和.miserc.toml仅携带config_root。通过符号链接放入
conf.d的共享配置可以使用它将自身的bin目录添加到路径中:toml[env] _.path = "{{ config_source | canonicalize | dirname }}/bin"省略
canonicalize可获取访问该文件所经过的目录,而不是文件实际所在的目录mise_bin: String- 指向当前 mise 可执行文件的路径mise_pid: String- 指向当前 mise 进程的 pidmise_env: Vec<String>- 由MISE_ENV、-E或--env指定的配置环境。如果未设置配置环境,则该变量未定义xdg_cache_home: PathBuf- 指向 XDG 缓存主目录xdg_config_home: PathBuf- 指向 XDG 配置主目录xdg_data_home: PathBuf- 指向 XDG 数据主目录xdg_state_home: PathBuf- 指向 XDG 状态主目录tools: HashMap<String, ToolInfo | ToolInfo[]>– 将已安装的工具名称映射到其信息。可用于任务模板和设置了tools = true的环境指令- 安装单个版本时:
tools.<name>.version: String– 已解析的版本(例如"22.1.0")tools.<name>.path: String– 安装路径
- 安装多个版本时,它会变成一个数组:
tools.<name>[0].version: String– 第一个版本tools.<name>[0].path: String– 第一个安装路径tools.<name>[1].version: String– 第二个版本,依此类推
- 安装单个版本时:
在 任务运行脚本 中,当任务有 usage 规范时,mise 还会暴露一个 usage 映射(参见 任务参数):
usage: HashMap<String, Value>– 已解析的任务参数和标志,以其名称为键。值不会经过 shell 转义或加引号,并且可能是:- 布尔值(用于标志和布尔参数)
- 字符串
- 布尔值/字符串数组(用于可变参数/标志)
这些键就是 usage 规范中写入的参数/标志名称。如果名称包含 -,请使用方括号访问,例如 {{ usage["dry-run"] }}。 示例:
[tasks.deploy]
usage = '''
arg "<environment>" help="目标环境"
flag "-v --verbose" help="启用详细输出"
arg "[tags]" var=#true
'''
run = '''
echo "env={{ usage.environment }}"
echo "verbose={{ usage.verbose }}"
echo "tag count={{ usage.tags | length }}"
{% for tag in usage.tags %}
echo "tag={{ tag }}"
{% endfor %}
'''函数
Tera 内置函数
Tera 提供了许多内置函数。 [] 表示可选的函数参数。 部分函数如下:
range(end, [start], [step_by])- 返回一个使用给定参数创建的整数数组end: usize:在end之前停止,必填start: usize:起始位置,默认为0step_by: usize:递增的数值,默认为1
now([timezone])- 在默认的 Tera v2 模式下,以字符串形式返回当前日期时间。 时区默认为 UTC,并接受诸如America/New_York这样的 IANA 名称- 提示:使用 date 过滤器格式化日期字符串。 例如,
{{ now() | date(format="%Y") }}可获取当前年份 - 使用
tera_v1 = true时,仍可使用原始的now([timestamp], [utc])签名
- 提示:使用 date 过滤器格式化日期字符串。 例如,
throw(message)- 抛出包含指定消息的异常get_random(start, end, [seed])- 返回指定范围内的随机整数。 提供seed后,结果将可复现
before 和 after 测试用于比较日期,并接受 other 和可选的 inclusive 参数:
{% if release_date is after(other="2026-01-01") %}...{% endif %}
Tera 还提供了更多函数。请参阅 Tera 文档。
其他 Mise 函数
除了 tera 的内置函数外,Mise 还提供了许多有用的函数。
通用函数
这些函数在所有任务中都可用,并且无论它们用于什么任务定义,其行为始终相同。换句话说,它们的返回值在不同任务定义之间是一致的。
exec(command) -> String– 执行 shell 命令并将其输出以字符串形式返回get_env(name, [default]) -> String– 根据名称返回原始进程环境变量的值。此辅助函数由 mise 提供,用于兼容较旧的 Tera 模板。在新模板中,尽可能优先使用env变量。当环境变量不存在时,将使用default值;空环境变量将按原样返回arch() -> String– 获取系统架构,例如x64或arm64os() -> String– 返回操作系统的名称,例如 linux、macos、windowsos_family() -> String– 返回操作系统系列,例如unix、windowsnum_cpus() -> usize– 获取系统上可用的 CPU 数量choice(n, alphabet)- 从alphabet中随机抽样并允许重复,生成长度为n的字符串。例如,choice(n=64, alphabet='0123456789abcdef')将生成一个随机的 64 字符小写十六进制字符串read_file(path) -> String– 读取给定路径下文件的内容,并将其以字符串形式返回
WARNING
exec() 会在模板每次渲染时运行,包括评估配置模板的 --dry-run 操作。试运行模式会抑制计划执行的 mise 操作,但不会对模板函数执行的命令进行沙箱隔离或抑制。请确保传递给 exec() 的命令不会产生副作用。
特定任务函数
这些函数是任务特定的,并且会根据所使用的任务而表现不同。换句话说,它们的返回值**可能**(但不保证)在任何给定 任务 的多次执行之间保持一致,并且应当预期在不同任务定义之间不一致。
例如,task_source_files() 返回的文件路径集合会根据调用它的任务的 sources 而有所不同。
task_source_files() -> Vec<String>– 返回任务的sources,并以解析后的文件路径数组形式呈现。此函数会处理任务源中定义的 glob 模式和 Tera 模板字符串,将它们展开为实际的文件路径。如果某个模式未匹配到任何文件,则会将其从结果中省略。如果未配置源,或没有文件匹配这些模式,则返回空数组。传递
only_changed=true可将结果限制为自 mise 上次认为该任务已是最新状态以来写入的源文件。这对于代码检查器和格式化工具很有用,因为向它们提供少量文件时速度会快得多。mise 从未将其视为最新状态的任务没有可供比较的基线,因此会返回每个源文件。运行失败不会推进基线,因此相同的文件会一直保留在列表中,直到任务成功。与 mise 自身的源文件新鲜度检查一样,这里比较的是修改时间,因此同样会受到touch和已恢复缓存相关问题的影响。过滤不会将结果缩减为空:如果没有源文件发生变化但任务仍在运行——使用了
--force、某个确实执行了操作的依赖项、或源文件保持不变时某个输出被删除——则会返回所有源文件,因为不给任务传递文件,就无法完成它被运行来执行的工作。
示例
# 使用 exec 获取命令输出
[alias.node.versions]
current = "{{ exec(command='node --version') }}"
# 使用 read_file 引入文件内容
[env]
VERSION = "{{ read_file(path='VERSION') | trim }}"
# 在任务脚本中访问已解析的源文件
[tasks.example]
sources = ["src/**/*.ts", "package.json"]
run = '''
{% for file in task_source_files() %}
echo "Processing: {{ file }}"
{% endfor %}
'''
# Only lint what changed since this task last succeeded. Each path goes through
# `quote`, so a filename containing a space or a shell metacharacter stays one
# argument (POSIX shells — see the quote filter's note).
[tasks.lint]
sources = ["src/**/*.ts"]
run = "eslint{% for file in task_source_files(only_changed=true) %} {{ file | quote }}{% endfor %}"Exec 选项
exec 函数支持以下选项:
command: String– [必需] 要运行的命令cache_key: String– 用于存储结果的缓存键。 如果提供了缓存键,结果将被缓存并在后续调用中复用cache_duration: String– 缓存结果的时长。 时长单位可以是秒、分钟、小时、天或周。 例如,cache_duration="1d"将把结果缓存 1 天
过滤器
Tera 提供了许多内置过滤器。 [] 表示可选的过滤器参数。 一些在 Tera v2 中被移除或重命名的 Tera v1 过滤器仍受支持, 以确保兼容性,直到 mise 2027.4.0。mise 将从 mise 2026.10.0 开始针对这些过滤器发出弃用警告。 tera-contrib 提供的辅助工具支持使用,且不会发出弃用警告。 部分过滤器如下:
str | lower -> String– 将字符串转换为小写str | upper -> String– 将字符串转换为大写str | capitalize -> String– 将字符串中除第一个字符外的所有字符转换为小写, 并将第一个字符转换为大写str | replace(from, to) -> String– 将字符串中所有的from替换为to。例如:{{ name | replace(from="Robert", to="Bob")}}str | title -> String– 将句子中的每个单词首字母大写。 例如,{{ "foo bar" | title }}会变为Foo Barstr | trim -> String– 移除开头和结尾的空白字符str | trim_start -> String– 移除开头的空白字符str | trim_end -> String– 移除结尾的空白字符str | truncate -> String– 将字符串截断为指定长度str | first -> String– 返回数组或字符串中的第一个元素str | last -> String– 返回数组或字符串中的最后一个元素str | join(sep) -> String– 使用分隔符连接字符串数组, 例如将{{ ["a", "b", "c"] | join(sep=", ") }}处理为a, b, cstr | length -> usize– 返回字符串或数组的长度str | reverse -> String– 反转字符串中字符的顺序, 或数组中元素的顺序str | urlencode -> String– 对字符串进行编码, 使其可以安全地用于 URL, 将特殊字符转换为百分号编码值arr | map(attribute) -> Array– 已弃用的兼容性过滤器。从数组中的每个对象提取一个属性arr | concat(with) -> Array– 已弃用的兼容性过滤器。将值追加到数组中。建议使用数组字面量和展开语法num | abs -> Number– 返回数字的绝对值num | filesize_format -> String– 将整数转换为人类可读的文件大小。filesizeformat也可作为别名使用str | date(format, [timezone]) -> String– 使用提供的格式将时间戳转换为格式化的日期字符串, 例如{{ ts | date(format="%Y-%m-%d") }}。 时间格式列表请参阅jiff文档str | b64_encode([url_safe], [padded]) -> String– 将字符串编码为 base64str | b64_decode([url_safe]) -> String– 解码 base64 字符串value | format(spec) -> String– 使用 Rust 风格的格式化方式格式化值value | json_encode([pretty]) -> String– 将值编码为 JSONarray | shuffle([seed]) -> Array– 随机打乱数组str | regex_replace(pattern, rep) -> String– 替换正则表达式匹配项str | striptags -> String– 移除 HTML 标签str | spaceless -> String– 移除 HTML 标签之间的空白字符str | slug -> String– 将字符串转换为适合 URL 的 slug。slugify也可作为别名使用str | urlencode_strict -> String– 对所有非字母数字字符进行百分号编码str | split(pat) -> Array– 根据给定模式拆分字符串, 并返回子字符串数组str | default(value) -> String– 如果变量未定义或为空, 则返回默认值
Tera 还提供了更多过滤器。请参阅 Tera 文档了解更多信息。
哈希
str | hash([algorithm], [len]) -> String– 为输入字符串生成哈希algorithm: "sha256" | "blake3":要使用的哈希算法(默认:"sha256")len: usize:将哈希字符串截断为给定长度- 示例:
{{ "foo" | hash }}– SHA256 哈希(默认){{ "foo" | hash(algorithm="blake3") }}– BLAKE3 哈希{{ "foo" | hash(len=8) }}– 将 SHA256 哈希截断为 8 个字符
path | hash_file([len]) -> String– 返回给定路径下文件的 BLAKE3 哈希值len: usize:将哈希字符串截断为给定长度
路径操作
path | absolute -> String– 将输入路径转换为绝对路径。不要求路径存在path | canonicalize -> String– 将输入路径转换为绝对输入路径版本。如果路径不存在则抛出错误path | basename -> String– 从路径中提取文件名, 例如/foo/bar/baz.txt变为baz.txtpath | file_size -> String– 返回文件的字节大小path | dirname -> String– 返回文件的目录路径, 例如/foo/bar/baz.txt变为/foo/barpath | basename -> String– 返回文件的基本名称, 例如/foo/bar/baz.txt变为baz.txtpath | extname -> String– 返回文件的扩展名, 例如/foo/bar/baz.txt变为.txtpath | file_stem -> String– 返回不含扩展名的文件名, 例如/foo/bar/baz.txt变为bazpath | file_size -> String– 返回文件的字节大小path | last_modified -> String– 返回文件的最后修改时间path[] | join_path -> String– 将路径数组连接为单一路径
例如,你可以使用数组字面量和 join_path 来构造文件路径:
[env]
PROJECT_CONFIG = "{{ [config_root, 'bar.txt'] | join_path }}"字符串操作
str | quote -> String– 为 POSIX shell 中的字符串加引号。嵌入的单引号使用 POSIX 安全的'\''形式,例如'it'\''s str'。此过滤器不会针对 PowerShell、cmd 或其他非 POSIX shell 调整其输出str | kebabcase -> String– 将字符串转换为 kebab-casestr | lowercamelcase -> String– 将字符串转换为 lowerCamelCasestr | uppercamelcase -> String– 将字符串转换为 UpperCamelCasestr | snakecase -> String– 将字符串转换为 snake_casestr | shoutysnakecase -> String– 将字符串转换为 SHOUTY_SNAKE_CASE
将模板值插入 POSIX shell 命令时,请使用 quote。带引号和不带引号的片段可以连接到同一个参数中:
[tasks.create-config]
run = "touch {{ config_root | quote }}/generated.toml"测试
Tera 提供了许多内置测试。 一些测试:
defined- 如果给定变量已定义,则返回truestring- 如果给定变量是字符串,则返回truenumber- 如果给定变量是数字,则返回truestarting_with- 如果给定变量是字符串且以所给参数开头,则返回trueending_with- 如果给定变量是字符串且以所给参数结尾,则返回truecontaining- 如果给定变量包含所给参数,则返回truematching- 如果给定变量是字符串且与参数中的正则表达式匹配,则返回true
Tera 还提供了更多测试。请参阅 Tera 文档了解更多信息。
Mise 提供了额外的测试:
if path is dir– 检查提供的路径是否是一个目录if path is file– 检查路径是否指向一个文件if path is exists– 检查路径是否存在
.miserc.toml 中的模板支持
.miserc.toml 文件支持 Tera 模板,但仅限于受限上下文。这是因为 .miserc.toml 加载得非常早——早于 mise.toml、Settings 和主配置被解析——因此只能使用操作系统级别可用的信息。
可用上下文
env: HashMap<String, String>– 操作系统环境变量(与mise.toml中相同)config_root: PathBuf– 包含.miserc.toml文件的目录cwd: PathBuf– 当前工作目录xdg_cache_home、xdg_config_home、xdg_data_home、xdg_state_home– XDG 基础目录- 所有函数:
arch()、os()、os_family()、num_cpus()、choice()等 - 所有过滤器:
absolute、dirname、basename、hash等
不可用内容
mise_env– 这是.miserc.toml定义的内容;它不能引用自身exec()– 需要 Settings,但此时它们尚未加载read_file()– 未在早期初始化上下文中注册(在此阶段尚未设置按文件目录解析)mise_bin、mise_pid– 在此阶段没有意义
miserc.toml 示例
# /workspaces/vcs/.config/miserc.toml
# 使用 $HOME 设置一个上限路径(在 home 目录处停止配置搜索)
ceiling_paths = ["{{ env.HOME }}"]
# Paths are relative to the directory containing this miserc file.
# Recursive glob patterns are supported.
ignored_config_paths = ["../vendor/**/mise.toml"]条件判断也可以——顶层的 {% if %} 块在条件为 false 时会产生空行,而 TOML 会忽略这些空行:
# ~/.config/mise/miserc.toml
{% if os() == "linux" %}
ceiling_paths = ["{{ env.HOME }}/work"]
{% endif %}TIP
如果模板渲染失败(例如由于变量未定义),mise 会记录一条警告并回退到原始内容。
WARNING
如果你的 .miserc.toml 值中包含字面量的 {{、{% 或 {# 字符 (并非用于模板),请将它们放入 {% raw %}...{% endraw %} 块中,以防止 Tera 将其解释为模板。