Skip to content

fix(shell): stop managed rc blocks from gluing the next line / 修复托管 shell block 重写时把下一行粘成注释 - #126

Merged
chenbstack merged 1 commit into
chenbstack:mainfrom
defia:fix/zshrc-block-trailing-newline
Oct 8, 2026
Merged

chenbstack merged 1 commit into
chenbstack:mainfrom
defia:fix/zshrc-block-trailing-newline

Conversation

@defia

@defia defia commented Sep 30, 2026

Copy link
Copy Markdown
Collaborator

What & why

The managed rc blocks (inline suggestions, shell keybinds) are Swift multiline literals and end at the closing delimiter WITHOUT a trailing newline. ShellRcBlock.upsert's replace path pasted such a block verbatim over the located range — swallowing the newline that separated the block from whatever followed it. The line after the block got glued onto the end sentinel and silently became part of that comment, and every launch rewrote it the same way, so a manual fix didn't survive an app restart (#124: a user's zsh-syntax-highlighting source line was eaten this way for weeks).

How

  • Normalize the block to end in exactly one newline inside ShellRcBlock.upsert. Both installers share that path, and a file already damaged by the glue heals on the next launch (the end sentinel still matches at line start; the glued line lands back on its own line).
  • Fix the inline-suggestions snippet's "respect the user's own zsh-autosuggestions" guard: it probed ZSH_AUTOSUGGEST_VERSION, a variable the plugin never sets (grepped both the vendored copy and upstream 0.7.1 — no such assignment), so the guard could never fire. Probe the _zsh_autosuggest_start hook function the plugin defines on load instead.
  • Drop the manual bindkey of → / ^E to autosuggest-accept — the plugin's default ZSH_AUTOSUGGEST_ACCEPT_WIDGETS already binds forward-char / end-of-line, with the same accept-at-end-of-buffer semantics.
  • New tests in ShellRcBlockTests: trailing-newline regression, glue-heal, launch-to-launch idempotency.

Testing / verification

  • xcodebuild test -scheme Glint -sdk macosx -arch arm64: full GlintTests suite — 377 passed, 0 failed (incl. the new/updated ShellRcBlockTests cases).
  • New guard semantics verified in a real zsh -f: passes when the plugin isn't loaded, blocks when it already is; the old guard confirmed always-true.
  • The vendored plugin was grepped to confirm the guard/bind claims (ZSH_AUTOSUGGEST_VERSION never assigned; _zsh_autosuggest_start defined; default accept widgets cover both keys).

Fixes #124

中文

问题与原因

~/.zshrc 托管 block(命令提示、shell 快捷键)是 Swift 多行字面量,收尾不带换行符。ShellRcBlock.upsert 的原地替换路径把这样的 block 原样粘回定位区间,吞掉了 block 与后续内容之间的换行——紧跟 block 的下一行被粘到收尾哨兵上、静默变成注释的一部分;而且每次启动都照此重写,手工修复活不过一次重启(#124:报告者的 zsh-syntax-highlighting source 行因此长期失效)。

改法

  • 在 ShellRcBlock.upsert 内统一把 block 规范为恰好一个尾换行。两个安装器共用该路径;已被粘坏的文件会在下次启动自愈(收尾哨兵仍按行首匹配,被粘的行回到自己那行)。
  • 修复 inline-suggestions 脚本里「尊重用户已有 zsh-autosuggestions」的 guard:原来探测的 ZSH_AUTOSUGGEST_VERSION 变量插件从未定义(vendored 副本与上游 0.7.1 都 grep 过,无此赋值),guard 永不生效;改为探测插件加载时定义的 _zsh_autosuggest_start 钩子函数。
  • 删掉对 → / ^E 的手工 bindkey——插件默认 ZSH_AUTOSUGGEST_ACCEPT_WIDGETS 已绑定 forward-char / end-of-line,语义相同(光标在行尾才整条接受)。
  • ShellRcBlockTests 新增尾换行回归、粘行自愈、启动间幂等用例。

验证

  • 全量 GlintTests(xcodebuild test -scheme Glint -sdk macosx -arch arm64):377 通过、0 失败。
  • 新 guard 在真实 zsh -f 下验证:未加载时放行、已加载时拦截;旧 guard 确认恒真。
  • grep vendored 插件确认三条断言(ZSH_AUTOSUGGEST_VERSION 无赋值、_zsh_autosuggest_start 有定义、默认 accept widgets 覆盖两键)。

Reviewer note: #119 (brew cask postflight deprecation) lives in the tap, not this repo — chenbstack/homebrew-glint#2 already has the fix and is clean against the tap's current main.

…ack#124)

The managed blocks are Swift multiline literals, which end at the
closing delimiter without a trailing newline. ShellRcBlock.upsert's
replace path pasted such a block over the located range verbatim,
swallowing the newline that separated the block from whatever followed
it - so the line after the block got glued onto the end sentinel and
silently became part of that comment. Every launch rewrote the block
the same way, so a manual fix didn't survive an app restart (a user
lost their zsh-syntax-highlighting source line this way).

Normalize the block to end in exactly one newline inside upsert. Both
installers (inline suggestions, shell keybinds) share that path, and a
file already damaged by the glue heals on the next launch.

While in there, fix the inline-suggestions snippet:

- The "respect the user's own zsh-autosuggestions" guard probed
  ZSH_AUTOSUGGEST_VERSION, a variable the plugin never sets, so the
  guard could never fire and oh-my-zsh / prezto users got a second copy
  loaded. Probe the _zsh_autosuggest_start hook function the plugin
  defines on load instead.
- Drop the manual bindkey of Right/^E to autosuggest-accept: the
  plugin's default ZSH_AUTOSUGGEST_ACCEPT_WIDGETS already binds
  forward-char and end-of-line.

Fixes chenbstack#124
@chenbstack
chenbstack merged commit f665de6 into chenbstack:main Oct 8, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: 每次启动重写 ~/.zshrc 的 inline suggestions block 时缺换行,把紧跟其后的一行粘成注释

2 participants