Starship Bracketed Segments 预设详解:一行命令把 “via/on” 替换为统一括号分段
本文基于 Starship 仓库中的 Bracketed Segments 预设文档(docs/ar-SA/presets/bracketed-segments.md,阿拉伯语版;对应英文版为 docs/presets/bracketed-segments.md)展开,完整介绍该预设的作用、启用命令与全部配置内容,并结合 starship preset 子命令的源码实现(src/main.rs、src/print.rs、build.rs)解析预设文件是如何被内嵌、生成和写入配置目录的。读完后,你可以一键应用该预设、读懂预设文件中每一类 format 字符串的语法,并知道如何按需微调。
一、Bracketed Segments 预设是什么
Starship 的默认提示词在展示各类信息时,会带上自然语言连接词,例如运行时模块默认以 “via ⎈ v1.2.3” 的形式呈现,git 相关模块会以 “on” 等字样衔接分支信息。Bracketed Segments 预设做的事情很简单但很彻底:
它把所有内置模块的 format 改为用方括号包裹当前分段内容,取代 Starship 默认的措辞("via"、"on" 等)。
也就是说,同样的信息源,默认样式是散落的 “via/ on” 文字连接,套用该预设后每个模块都变成 [内容] 形式的独立方块,视觉上更接近 powerline/终端标签风格,各分段之间的边界也更清晰。
两个关键事实值得先明确:
- 该预设只覆盖各模块的
format字符串。预设 TOML 中没有任何disabled、display_mode等其他配置项(可对照 docs/public/presets/toml/bracketed-segments.toml 全文确认),因此模块的启用条件、检测逻辑、样式(style)全部维持 Starship 默认行为不变——在普通目录下看不到的模块,套用预设后依然不会出现。 - 它是一次性“整包替换”型预设:
starship preset bracketed-segments -o <文件>生成的 TOML 会作为完整配置文件使用,适合直接作为starship.toml的全部内容,而不是和已有配置逐段合并。
二、一行命令启用预设
文档给出的配置命令是:
starship preset bracketed-segments -o ~/.config/starship.toml
这条命令会把 bracketed-segments 预设的完整 TOML 直接写入 ~/.config/starship.toml。命令各部分的含义如下:
preset:Starship 的预设子命令,用于打印/落盘内置预设配置;bracketed-segments:预设名称,必须是 Starship 编译时内嵌的预设之一;-o ~/.config/starship.toml:将预设内容输出到指定文件(等价长参数为--output),而不是打印到 stdout。
从 src/main.rs 中该子命令的参数定义还可以确认另外三个可用能力:
/// Prints a preset config
Preset {
/// The name of preset to be printed
#[clap(required_unless_present("list"), value_enum)]
name: Option<print::Preset>,
/// Output the preset to a file instead of stdout
#[clap(short, long, conflicts_with = "list")]
output: Option<PathBuf>,
/// Forcibly overwrite the output file if it already exists
#[clap(short, long, requires = "output")]
force: bool,
/// List out all preset names
#[clap(short, long)]
list: bool,
},
对应的实用用法:
# 不带 -o:把预设 TOML 打印到终端,可配合重定向或 cat 查看
starship preset bracketed-segments
# 列出当前二进制内置的全部预设名
starship preset -l
# 目标文件已存在时,需要显式 --force 强制覆盖
starship preset bracketed-segments -o ~/.config/starship.toml --force
force 参数带有 requires = "output" 约束,即只有配合 -o 使用才有意义;list 与 -o 互斥。
三、预设加载机制:从源码看 preset 子命令做了什么
预设并不是运行时去某个目录读取文件,而是在编译期就被内嵌进了二进制。整条链路如下:
- 构建阶段:build.rs 扫描
docs/public/presets/toml/目录下的所有.toml文件(本仓库即 docs/public/presets/toml/ 下的 12 个预设),为每个文件生成include_str!条目,拼出get_preset_list()与get_preset_content(name)两个函数(由shadow模块暴露)。文件名去掉.toml后缀即为预设名,所以bracketed-segments.toml对应预设名bracketed-segments。 - 运行阶段:src/print.rs 中
Preset类型实现 clap 的ValueEnum,其候选值直接来自shadow::get_preset_list();preset_command拿到预设内容后,若指定了-o则调用utils::write_file_atomic原子写入目标文件,否则写 stdout。
pub fn preset_command(name: Option<Preset>, output: Option<PathBuf>, force: bool, list: bool) {
if list {
println!("{}", preset_list());
return;
}
let variant = name.expect("name argument must be specified");
let content = shadow::get_preset_content(variant.0);
if let Some(output) = output {
if let Err(e) = crate::utils::write_file_atomic(&output, content, force) {
eprintln!("Error writing preset to {output:?}: {e}");
std::process::exit(1);
}
} else if let Err(err) = std::io::stdout().write_all(content.as_bytes()) {
// ...
}
}
这意味着两点实操结论:
- 预设内容的唯一事实来源是仓库中的
docs/public/presets/toml/*.toml,文档页面展示的 TOML 与命令输出完全一致,可直接对照; - 仓库测试(src/print.rs)覆盖了
preset -l、各预设可正常打印、写入文件与--force覆盖等路径,行为稳定可依赖。
四、预设完整配置(可整段复制)
以下就是 starship preset bracketed-segments -o ... 落盘的全部内容(与 docs/public/presets/toml/bracketed-segments.toml 一致,共 12 个预设文件之一):
"$schema" = 'https://starship.rs/config-schema.json'
[aws]
format = '\[[$symbol($profile)(\($region\))(\[$duration\])]($style)\]'
[azure]
format = '\[$symbol($subscription)\]'
[battery]
format = '\[$symbol$percentage\]'
[buf]
format = '\[$symbol($version)\]'
[bun]
format = '\[$symbol($version)\]'
[c]
format = '\[$symbol($version(-$name))\]'
[cmake]
format = '\[$symbol($version)\]'
[cmd_duration]
format = '\[⏱ $duration\]'
[cobol]
format = '\[$symbol($version)\]'
[conda]
format = '\[$symbol$environment\]'
[container]
format = '\[[$symbol \[$name\]]($style)\]'
[cpp]
format = '\[$symbol($version(-$name))\]'
[crystal]
format = '\[$symbol($version)\]'
[daml]
format = '\[$symbol($version)\]'
[dart]
format = '\[$symbol($version)\]'
[deno]
format = '\[$symbol($version)\]'
[direnv]
format = '\[$symbol$loaded/$allowed\]'
[docker_context]
format = '\[$symbol$context\]'
[dotnet]
format = '\[$symbol($version)(🎯 $tfm)\]'
[elixir]
format = '\[$symbol($version \(OTP $otp_version\))\]'
[elm]
format = '\[$symbol($version)\]'
[erlang]
format = '\[$symbol($version)\]'
[fennel]
format = '\[$symbol($version)\]'
[fortran]
format = '\[$symbol($version)\]'
[fossil_branch]
format = '\[$symbol$branch\]'
[fossil_metrics]
format = '\[+$added\]\[-$deleted\]'
[gcloud]
format = '\[$symbol$account(@$domain)(\($region\))\]'
[git_branch]
format = '\[$symbol$branch\]'
[git_commit]
format = '\[\($hash$tag\)\]'
[git_metrics]
format = '\[+$added\]\[-$deleted\]'
[git_state]
format = '\[$state ($progress_current/$progress_total)\]'
[git_status]
format = '([\[$all_status$ahead_behind\]]($style))'
[gleam]
format = '\[$symbol($version)\]'
[golang]
format = '\[$symbol($version)\]'
[gradle]
format = '\[$symbol($version)\]'
[guix_shell]
format = '\[$symbol\]'
[haskell]
format = '\[$symbol($version)\]'
[haxe]
format = '\[$symbol($version)\]'
[helm]
format = '\[$symbol($version)\]'
[hg_branch]
format = '\[$symbol$branch\]'
[hostname]
format = '\[$ssh_symbol($hostname)\] '
[java]
format = '\[$symbol($version)\]'
[jj_bookmark]
format = '\[$symbol$bookmark(@$remote)$diverged( \(+$overflow_count others\))\]'
[jobs]
format = '\[$symbol$number\]'
[julia]
format = '\[$symbol($version)\]'
[kotlin]
format = '\[$symbol($version)\]'
[kubernetes]
format = '\[$symbol$context( \($namespace\))\]'
[localip]
format = '\[$localipv4\]'
[lua]
format = '\[$symbol($version)\]'
[maven]
format = '\[$symbol($version)\]'
[memory_usage]
format = '\$symbol[$ram( | $swap)\]'
[meson]
format = '\[$symbol$project\]'
[mise]
format = '\[$symbol$health\]'
[mojo]
format = '\[$symbol($version)\]'
[nats]
format = '\[$symbol$name\]'
[netns]
format = '\[[$symbol \[$name\]]($style)\]'
[nim]
format = '\[$symbol($version)\]'
[nix_shell]
format = '\[$symbol$state( \($name\))\]'
[nodejs]
format = '\[$symbol($version)\]'
[ocaml]
format = '\[$symbol($version)(\($switch_indicator$switch_name\))\]'
[odin]
format = '\[$symbol($version )\]'
[opa]
format = '\[$symbol($version)\]'
[openstack]
format = '\[$symbol$cloud(\($project\))\]'
[os]
format = '\[$symbol\]'
[package]
format = '\[$symbol$version\]'
[perl]
format = '\[$symbol($version)\]'
[php]
format = '\[$symbol($version)\]'
[pijul_channel]
format = '\[$symbol$channel\]'
[pixi]
format = '\[$symbol$version( $environment)\]'
[pulumi]
format = '\[$symbol$stack\]'
[purescript]
format = '\[$symbol($version)\]'
[python]
format = '\[${symbol}${pyenv_prefix}(${version})(\($virtualenv\))\]'
[quarto]
format = '\[$symbol($version)\]'
[raku]
format = '\[$symbol($version-$vm_version)\]'
[red]
format = '\[$symbol($version)\]'
[rlang]
format = '\[$symbol($version)\]'
[ruby]
format = '\[$symbol($version)\]'
[rust]
format = '\[$symbol($version)\]'
[scala]
format = '\[$symbol($version)\]'
[shell]
format = '\[$indicator\]'
[singularity]
format = '\[[$symbol\[$env\]]($style)\]'
[solidity]
format = '\[$symbol($version)\]'
[spack]
format = '\[$symbol$environment\]'
[status]
format = '\[$symbol$status\]'
[sudo]
format = '\[as $symbol\]'
[swift]
format = '\[$symbol($version)\]'
[terraform]
format = '\[$symbol$workspace\]'
[time]
format = '\[$time\]'
[typst]
format = '\[$symbol($version)\]'
[username]
format = '\[$user\]'
[vagrant]
format = '\[$symbol($version)\]'
[vcsh]
format = '\vcsh [$symbol$repo\]'
[vlang]
format = '\[$symbol($version)\]'
[xmake]
format = '\[$symbol($version)\]'
[zig]
format = '\[$symbol($version)\]'
第一行 "$schema" 指向 Starship 的配置 JSON Schema(对应仓库内的 docs/public/config-schema.json),用于编辑器在 starship.toml 中获得自动补全与校验,对运行时行为没有影响。
五、format 字符串语法拆解:读懂预设里的每个符号
预设本质上是一套 Starship format 语法模板的批量应用。结合 src/formatter/string_formatter.rs 的解析实现,预设文件中反复出现五类语法:
| 语法 | 含义 | 预设中的典型例子 |
|---|---|---|
\[ / \] |
转义字符,原样输出方括号;若不转义,[ ] 会被解析器当作分组语法 |
几乎所有行的首尾 \[\[ ... \]\] |
$var / ${var} |
变量占位符,渲染时替换为对应模块计算出的值 | $symbol、$version、${pyenv_prefix} |
(group) |
可选分组:组内变量全部为空时整组不渲染,非空则整组显示 | ($version)、(\($region\)) |
($style) |
特殊分组:把该模块配置中定义的 style 应用到括号包裹的文本上 |
每行末尾的 ]($style) |
| 普通文本 | 原样输出,可用 \- 等方式转义 |
[c] 中的 -$name 连接符 |
以几个有代表性的模块格式为例逐句解读:
1. 运行时类模块(如 [nodejs])
format = '\[$symbol($version)\]'
渲染结果是 [⬢ v20.11.0] 这类结构:$symbol 是语言图标,($version) 是可选分组(版本查不到时整个 (...) 消失,方括号里只剩图标),最外层 \[ \] 是转义后的字面方括号,($style) 把整个内容染成该模块的默认颜色。对比默认格式,这里没有任何 "via" 字样——这正是预设标题 "Bracketed Segments" 的含义。
2. 带多级可选信息的模块(如 [aws])
format = '\[[$symbol($profile)(\($region\))(\[$duration\])]($style)\]'
嵌套了三个可选分组:profile 存在才显示 profile,region 存在才显示 (region),duration 存在才显示 [duration]。注意 region 外层的 \( \) 是转义圆括号(字面字符),而包裹它的 (...) 才是可选分组语法——两类圆括号通过反斜杠区分,这是阅读该预设时最容易混淆的地方。
3. 双括号结构(如 [git_status])
format = '([\[$all_status$ahead_behind\]]($style))'
最外层 (...) 是可选分组(没有 git 状态变化时整段不显示),内部 \[\[ ... \]\] 是转义后的字面方括号。渲染效果类似 ([+2 ~1 ⭢ | ↑2↓1]),即“可选分组 + 字面括号”双层结构。
4. 带特殊变量的模块(如 [python])
format = '\[${symbol}${pyenv_prefix}(${version})(\($virtualenv\))\]'
pyenv_prefix 与 virtualenv 由 src/configs/python.rs 提供的模块逻辑填充:pyenv 环境会额外显示 pyenv 版本信息,虚拟环境存在时追加 (venv名)。${symbol} 写法与 $symbol 等价,这里用花括号形式避免与相邻变量粘连产生歧义。
5. 无图标模块(如 [hostname]、[sudo])
[hostname]
format = '\[$ssh_symbol($hostname)\] '
[sudo]
format = '\[as $symbol\]'
hostname 在 SSH 会话下 $ssh_symbol 非空时整段才出现;sudo 则固定渲染成 [as 前缀](保留 "as" 一词作为语义提示),行尾空格用于与下一个模块分隔。
6. 固定文案模块(如 [vcsh]、[cmd_duration])
[vcsh]
format = '\vcsh [$symbol$repo\]'
[cmd_duration]
format = '\[⏱ $duration\]'
[vcsh] 中的 vcsh 是纯文本前缀,不属于任何可选分组,模块显示时必然出现;[cmd_duration] 则完全依赖 cmd_duration 模块的 min_time 判断(低于阈值的命令不显示),预设本身不改写这个判断逻辑。
7. 双段式模块(如 [git_metrics]、[fossil_metrics])
format = '\[+$added\]\[-$deleted\]'
一个 format 里放了两个独立括号段:新增行计数用 added_style 着色、删除行计数用 deleted_style 着色,各自可选渲染。
六、使用建议与恢复默认
结合本文源码与配置事实,给出几条实操建议:
- 先备份再覆盖:
-o会直接写目标文件,若~/.config/starship.toml已有自定义内容,建议先手动备份,或先用--force语义确认可以覆盖后再执行;也可以先不带-o执行starship preset bracketed-segments把内容打印出来审阅。 - 恢复默认:删除(或还原备份的)
starship.toml中的相关format覆盖即可,模块随即回到默认措辞;预设本身不改动 Starship 二进制。 - 微调方式:该预设是“全量 format 覆盖”思路,若只想改个别模块,不必整包套用,可以单独借鉴对应模块的
format行(如把[python]、[git_status]的写法挪进自己的starship.toml)。 - 验证生效:修改配置后新开终端会话即可看到效果;排查单个模块输出时可配合
starship module python之类的子命令(见 src/main.rs 中Module子命令)单独查看该模块的渲染结果。 - 与其他预设的关系:Starship 内置 12 个预设(见 docs/public/presets/toml/,含 nerd-font、no-nerd-font、jetpack、tokyo-night、catppuccin-powerline、gruvbox-rainbow、pastel-powerline、pure-preset、no-runtimes、plain-text、bracketed-segments 等),每个预设都是独立完整配置。从源码结构看,
preset子命令一次只输出一个预设的全部内容,多个预设之间没有自动合并机制,混合风格需要自行挑选各自的format行拼接。
七、小结
Bracketed Segments 是 Starship 官方预设中偏“结构重塑”的一类:它不增减信息,只把所有内置模块的输出统一收进 [...] 字面括号,并借助 $symbol、$version 与 ($style) 保留原有的图标、可选分组和配色。启用只需一条 starship preset bracketed-segments -o ~/.config/starship.toml;其背后是构建期由 build.rs 内嵌 TOML、运行期由 src/print.rs 原子写入的实现链路;而预设全文的每一行都可以按本文第五节的 format 语法表逐符号解读,方便你把它改造成自己的分段风格。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
