启动选择世代记录的别名和排版问题

问题

  • 别名:启动菜单里每条世代记录的名字长这样 —— {序号} {日期 时间} {描述}。描述有三个来源(见下),而 systemd-boot-builder 每次都会按闭包里的只读 label 重写所有条目,所以靠 boot-menu-names 模块在 builder 之后再重放一遍命名。
  • 排版:菜单里各行参差不齐(实测 gen1 = 41 字符、gen42 = 67 字符、gen44 = 48 字符),而且整个菜单框在屏幕上居中,看着乱。

结论一:菜单“居中”改不了

systemd-boot 的界面是编译进 EFI 二进制的固定渲染。逐项看过 loader.conf 手册,选项只有 default / timeout / console-mode / editor / auto-entries / auto-firmware / beep / random-seed-mode 这一类,搜 align|theme|margin|position|column 零匹配 —— 没有对齐、没有主题、没有边距。所以“居中”不是配置问题;换 GRUB 也一样(GRUB 的菜单同样是居中的框)。

结论二:参差不齐可以修 —— 标题等长化

关键设计:宽度不是存下来的状态,而是每次 rebuild 现算。钩子每次运行时收集“本次实际存在的全部世代”(已被 prune 的自动跳过),现算两个宽度 —— NW = 最长世代号宽度(世代号右对齐)、W = 最长标签宽度(标签右补空格),然后一次性重写所有条目。所以追加一条更长的描述,整列会自动变宽;删掉最长的那条,整列会自动收窄,无残留。

情形NW / W每条 title 长度
改之前(真实 /boot 条目:41 / 67 / 48 字符)—参差不齐
改之后(当前 15 条真实数据)2 / 58全部 61 字符
假设追加一条更长描述(标签 69 字符)2 / 69全部 72 字符
假设删掉最长的 gen42(标签降到 39 字符)2 / 39全部 42 字符
  • 宽度不入库:映射表 boot-menu-titles.tsv 仍是未补空格的原标签 → rebuild list 的输出一个字不变;version 行也不动。
  • 无额外开销:这个钩子本来每次 rebuild 就会重写全部条目,改动只是在写之前先定宽(多一趟数组遍历)。
  • 改动位置:/etc/nixos/modules/boot-menu-names.nix(收集代替逐条写、末尾统一定宽写盘、title 里世代号右对齐),备份 boot-menu-names.nix.bak-align-20261009-111955。
  • 注意:脚本在 Nix 缩进字符串里,bash 的 ${...} 必须写成 ''${...}(这次改动新增的几处已逐个核定)。

代价与边界(先声明判据)

  • 对齐的内在代价:只要出现更长的描述,整列就变宽(所有行一起变)—— 这是“对齐”的固有性质,不是缺陷。
  • 若要“宽度恒定、不随内容变”:唯一办法是限长描述(信息损失)。按本项目规矩,超长应报错拒绝而不是静默截断;需要的话再加一个 maxWidth 选项(值另定)。
  • “居中”永远改不了(见结论一)。

别名从哪来(简述)

  • 三方来源:explicit 人工表(如 gen42 = rebuild-script-auto-append-to-explicit)→ rebuild <描述> 新建的世代自动登记回表 → 其余表外世代自动起名(按包级 diff 关键字映射,兜底 config-change)。
  • 必须纯 ASCII:systemd-boot 用内置 8x16 点阵字体,二进制里没有字体加载路径,中文只会画成方块(要在菜单里显示中文得换 GRUB + 自制 pf2)。
  • label 字符集受系统限制 [a-zA-Z0-9:_.-]:rebuild 会把空格转成 -,非 ASCII 或非法字符直接报错拒绝(不静默改写)。
  • 标题里的日期时间取自世代链接的 mtime(不是 rebuild 那一刻的墙钟),所以与 label 里那份时间戳可能差几秒。

验证(均已实测)

  • nix-instantiate --parse 通过。
  • 把渲染后的脚本还原出来跑 bash -n → 语法 OK。
  • 用真实世代数据演算三种情形(见上表)。
  • 改前的真实 /boot 条目标题长度:41 / 67 / 48 字符(ESP 是 fmask=0077,读它要走 root)。

待实测

下一次 rebuild 后:菜单各行应等长;日志里会出现 boot-menu-names: 标题定宽 NW=2 W=58(数值随当时的世代集变化)。

相关

  • 命名机制与 rebuild 命令本体:见「世代管理命令rebuild」
  • 模块:/etc/nixos/modules/boot-menu-names.nix