首页
/ Starship v0.45.0 迁移实战指南:prompt_order 与模块 prefix/suffix 的统一 format 化改造

Starship v0.45.0 迁移实战指南:prompt_order 与模块 prefix/suffix 的统一 format 化改造

2026-09-07 13:41:17作者:冯爽妲Honey

Starship 在 v0.45.0 中为迎接 v1.0.0 做了一次包含破坏性变更(breaking changes)的版本发布,其核心是把"通过模块名数组/前缀后缀拼装提示符"的旧配置模型,全面收敛为可编程的 format 字符串体系。本指南以仓库内的官方迁移文档 docs/migrating-to-0.45.0/README.md(及其译文 docs/ckb-IR/migrating-to-0.45.0/README.md)为主线,逐条拆解 prompt_order、模块级 prefix/suffix 的替代方案,并结合当前仓库的配置默认值与 formatter 源码,帮助你一次看懂"为什么改、改成什么、怎么改",在升级后平滑迁移自己的 starship.toml


1. 背景:一次面向 v1.0.0 的配置体系重构

v0.45.0 的破坏性变更并非功能删减,而是为提示符提供更大自定义自由度而重构配置方式:

  • 顶层(prompt 级):用一份完整的 format 字符串取代"按顺序罗列模块名"的 prompt_order 数组,让你能在模块之间插入任意文本、条件段与自定义片段,而不再受模块顺序清单约束。
  • 模块级:用模块自己的 format 取代零散的 prefix/suffix,模块的输出内容(如 $duration$path)与样式从此可以内联在同一段模板里精确编排。

这两处改动直接推动了一套贯穿全项目的新增字符串格式化引擎 StringFormatter(位于 src/formatter/string_formatter.rs),其语法定义见 src/formatter/spec.pest

本文所有示例与结论均以当前仓库为准。若你正在维护旧版 Starship 配置,建议对照 docs/config/README.md 的最新配置项说明逐条核对。


2. 变更一:顶层 prompt_order → 根级 format

2.1 旧写法

v0.45.0 之前,模块渲染顺序由 prompt_order 数组决定:

# 旧版配置(v0.45.0 之前)
prompt_order = [
  "username",
  "hostname",
  "directory",
  "git_branch",
  "git_commit",
  "git_state",
  "git_status",
  "cmd_duration",
  "custom",
  "line_break",
  "jobs",
  "battery",
  "time",
  "character",
]

2.2 新写法

v0.45.0 起改为根级 format 字符串,模块名以 $ 前缀的变量形式出现在模板中:

# 新版配置(v0.45.0 及之后)
format = """\
  $username\
  $hostname\
  $directory\
  $git_branch\
  $git_commit\
  $git_state\
  $git_status\
  $cmd_duration\
  $custom\
  $line_break\
  $jobs\
  $battery\
  $time\
  $character\
  """

这里采用 TOML 的多行字符串 + 反斜杠续行技巧("""...""" 中每行行尾的 \ 用于吞掉换行),既保证可读性,又不会在提示符中引入真实换行。每个 $module_name 会被替换为该模块渲染出的内容;没有内容/未启用的模块对应变量为空,会被自动丢弃(详见下文第 4 节的 formatter 语义)。

相比旧数组模型,新的根级 format 可以在任意两个模块之间插入普通文本、括号条件段甚至嵌套样式,例如自定义分割符:

format = """\
  $username\
  $hostname\
  $directory\
  $git_branch\
  ──\
  $git_status\
  $line_break\
  $character\
"""

2.3 迁移要点

  • 将旧 prompt_order 中的模块名按原顺序逐一改写成 $模块名,拼成一行模板字符串即可得到等价的新配置。
  • 迁移后 prompt_order 键不再生效,应从配置文件中删除,避免混淆。

3. 变更二:模块级 prefix/suffix → 模块 format

3.1 旧写法

旧版中部分模块通过 prefix/suffix 装饰自身输出。以命令耗时为例:

# 旧版配置
[cmd_duration]
prefix = "took "

3.2 新写法

新版以 format 取代 prefix/suffix,把原本"拼接在上下文变量之外"的前后缀文本,变成模板中与变量、样式混排的一段 format 字符串:

# 新版配置
[cmd_duration]
# $duration – 命令耗时(如 "15s")
# $style    – 模块默认样式(如 "bold yellow")
format = "took $duration "

以当前仓库源码为准,cmd_duration 模块新默认值正是这种形态(见 src/configs/cmd_duration.rs):

Self {
    min_time: 2_000,
    format: "took $duration ",
    style: "yellow bold",
    ...
}

其中 $duration文本组(textgroup)内容,将 $duration 的值按 $style 解析出的样式渲染。


4. 迁移前先读懂 format 字符串语法

新旧两种 format(根级与模块级)底层是同一套语法。根据 src/formatter/spec.pest 的定义,模板由四种基本元素组成:

元素 语法 含义
变量 Variable $name${scope:name} 占位符,如 $username$duration${env:PWD}
文本 Text 普通字符 原样输出;[ ] ( ) \ $ 等功能字符需用 \ 转义(如 \\(
文本组 TextGroup [内容 内容 应用 样式;样式位置也允许放变量(如 ($style)
条件段 Conditional (内容) 仅当括号内所有变量都非空时才渲染整段

源码级语义可以从 src/formatter/string_formatter.rs 及其测试得到印证:

  • 变量无值即丢弃map() 返回 None 的变量在 parse() 时被整体移除(对应注释 "If it is None when self.parse() is called, it will be dropped",测试 test_conditional($none) shouldn't 的结果是不渲染 $none);
  • 变量可嵌套:文本组可以嵌套(测试 test_nested_textgroupouter middle [inner](red bold) 依次产出三层样式);
  • meta 变量:一个变量可以被映射到另一段 format 字符串再展开(测试 test_meta_variable$all → $a$b),这正是 git_status 模块内部组合 $all_status$ahead_behind 的机制;
  • shell 转义:渲染时会针对 Bash(转义 \$`)与 Zsh(转义 %)等做提示符安全转义(见 shell_prompt_escape 及测试 test_bash_escape)。

理解这四点后,下面逐模块的迁移看起来会非常直观:模块 format 就是该模块完整输出的一份小模板,内容变量与样式变量都在模板内就地引用。


5. 受影响模块逐一迁移对照

5.1 Character(字符提示符)

character 模块的旧属性全部收敛到带样式的符号变量:

已移除属性 替代方案
symbol success_symbol
use_symbol_for_status error_symbol
style_success success_symbol
style_failure error_symbol

默认配置变化(diff)

[character]
-- symbol = "❯"
-- error_symbol = "✖"
-- use_symbol_for_status = true
-- vicmd_symbol = "❮"
++ success_symbol = "❯"
++ error_symbol = "❯"
++ vicmd_symbol = "❮"

新语义解释:

  • use_symbol_for_status = true 控制"最后一条命令返回非零状态码时是否切换为 error_symbol";
  • v0.45.0 起无条件启用该行为:退出码非零时一律使用 error_symbol,从而把 use_symbol_for_statuserror_symbol 两个概念合并为一个。这与当前实现一致——在 src/modules/character.rs 中,模块根据 exit_code == "0" 直接选择 success_symbolerror_symbol;同文件测试 failure_status 覆盖了退出码 154321-5000 均渲染红色箭头 的情形。

若想恢复旧 use_symbol_for_status = true 的视觉效果(失败时显示 ✖ 而非红色 ❯),把 error_symbol 显式指回 ✖ 即可:

[character]
error_symbol = "✖"

注意character 元素会自动在其后补一个空格,所以与其它模块的 format 不同,上述示例中的符号样式字符串特意不写尾部空格。对应地,当前仓库的默认 format"$symbol "(见 src/configs/character.rs),即空格由 format 统一管理,success_symbol/error_symbol 本身不带空格。

5.2 Command Duration(命令耗时)

已移除属性 替代方案
prefix format
[cmd_duration]
-- prefix = "took "
++ format = "took $duration "

5.3 Directory(目录)

已移除属性 替代方案
prefix format
[directory]
-- prefix = "in "
++ format = "$path$read_only "

这里把 $read_only(默认锁图标 🔒)及其专属样式 $read_only_style(默认 red)一并并入模板;当前仓库 src/configs/directory.rs 的默认值 format: "$path$read_only " 与迁移后形态完全一致。

5.4 Environment Variable(环境变量)

已移除属性 替代方案
prefix format
suffix format
[env_var]
-- prefix = ""
-- suffix = ""
++ format = "with $env_value "

5.5 Git Commit(Git 提交)

已移除属性 替代方案
prefix format
suffix format
[git_commit]
-- prefix = "("
-- suffix = ")"
++ format = '\($hash\) '

注意这里使用单引号包裹 TOML 字符串,并配合 \(\) 转义——因为括号是 format 语法中的条件段定界符,普通文本中的括号必须转义才能作为字面量输出(对应第 4 节语法表)。

5.6 Git Status(Git 状态)

这是本次受影响最深、改动最多的模块:

已移除属性 替代方案
prefix format
suffix format
show_sync_count format(配合 ahead/behind/diverged
[git_status]
-- prefix = "["
-- suffix = "]"
-- show_sync_count = false
++ format = '([\[$all_status$ahead_behind\]]($style) )'

format 的结构解读:

  • $all_status 是一个 meta 变量,由模块内部展开为工作区各状态符号的拼接;
  • $ahead_behind 是另一个 meta 变量,表示与远端的分叉情况;
  • 整段被包在 [\[...\]](...) 方括号文本组与条件段 (...) 内,保证无状态时整段不输出。

show_sync_count 的三分替代:旧 show_sync_count 只负责"是否显示领先/落后远端提交数"这一个布尔开关;v0.45.0 拆成了三个独立可配置的符号属性 aheadbehinddiverged,它们可以各自使用 ${count}(或 ${ahead_count}/${behind_count})取到提交数。要恢复旧 show_sync_count = true 的行为,请显式配置:

[git_status]
ahead = "⇡${count}"
diverged = "⇕⇡${ahead_count}⇣${behind_count}"
behind = "⇣${count}"

作为对照,当前仓库 src/configs/git_status.rs 中的默认 ahead: "⇡"behind: "⇣"diverged: "⇕" 均不含 ${count} 变量——这正是"默认不显示同步计数"的新行为,且旧字段 prefix/suffix/show_sync_count 已完全从配置结构中移除。

5.7 Hostname(主机名)

已移除属性 替代方案
prefix format
suffix format
[hostname]
-- prefix = ""
-- suffix = ""
++ format = "$hostname in "

注意这个例子把连接词 in 移到了模块尾部,说明 format 化之后,前后置文本不再有固定位置,可以按需放到任何一侧。

5.8 Singularity(容器环境)

已移除属性 替代方案
label format
prefix format
suffix format
[singularity]
-- prefix = ""
-- suffix = ""
++ format = '[$symbol\[$env\]]($style) '

label 语义被并入模板:\[\] 为转义方括号(字面输出 []),中间是 $env 容器名变量,最外层 ... 套用模块默认样式。

5.9 Time(时间)

time 模块的特殊之处在于:它旧的 format既要承担时间格式又要承担展示排版,因此被拆成两个键:

已移除属性 替代方案
format(旧含义) time_format
[time]
-- format = "🕙[ %T ]"
++ time_format = "%T"
++ format = "at 🕙$time "
  • 时间本身用 C 风格 strftime 指令(%T 表示 HH:MM:SS)放到新的 time_format 中;
  • 模块 format 则只负责排版:$time 变量引用渲染好的时间,$style 是模块样式变量。

当前仓库 src/configs/time.rsformat: "at $time " 即该模型的直接延续(time_format 默认缺省,由 use_12hrutc_time_offsettime_range 等联合决定实际取值)。

5.10 Custom Commands(自定义命令)

已移除属性 替代方案
prefix format
suffix format
[custom.example]
-- prefix = ""
-- suffix = ""
++ format = "$symbol$output "

$symbol(自定义符号)与 $output(命令输出)可以自由混排,且整体能套模块默认样式。当前仓库 src/configs/custom.rs 的默认 format: "$symbol($output )" 进一步示范了用条件段 ($output ) 让命令输出为空时连尾巴空格都不输出的写法。


6. 升级后的配置健康检查

迁移完成后,可对照以下几点做自检:

  1. 搜索残留旧键:在 starship.toml 中全局搜索 prompt_orderprefixsuffixuse_symbol_for_statusshow_sync_count,以及各模块旧意义的 format/symbol 用法,确认已全部改写或删除;
  2. 留意转义:模板中出现字面量方括号/圆括号时记得用 \ 转义;包含反斜杠的 TOML 字符串建议使用单引号字面量,避免双重转义;
  3. 模块间插入内容的自由度:既然已升级到根级 format,可以顺手把原先依赖多个模块前后缀实现的装饰逻辑(如目录前的 in 、主机名后的 in )统一收编进模板,减少配置散落;
  4. 回归验证退出码行为:执行一条会失败的命令(如 falseexit 1),确认 character 已按预期切换为 error_symbol 样式(可用 success_symbol/error_symbol 分别设置不同形状的箭头来直观区分)。

7. 小结

v0.45.0 的迁移本质上是一堂"配置模板化"课:

  • 顶层从"模块名有序数组"变为根级 format,获得在模块间自由插入文本与条件段的能力;
  • 模块级从"前缀/后缀"收敛为模块内 format,让每个模块的输出内容、样式与前后置文本在同一个模板里自洽表达;
  • 配置项的形态全面向当前仓库的默认实现看齐(如 charactercmd_durationdirectorygit_statuscustom 的 config 结构均已只保留 format 家族字段)。

只要把握住"$变量 引用内容、... 应用样式、(...) 做条件渲染、字面量符号需转义"四条规则,你就能在新体系下写出比旧配置更紧凑也更灵活的提示符定义。完整的迁移对照请以仓库内官方文档 docs/migrating-to-0.45.0/README.md 为准,配置项全量说明见 docs/config/README.md

登录后查看全文
热门项目推荐
相关项目推荐