feat: add $fill layout token (Starship-style right-alignment)#189
feat: add $fill layout token (Starship-style right-alignment)#189tfenne wants to merge 3 commits into
Conversation
Add a Starship-style $fill token (configured via [cship.fill]) that expands to fill the remaining width; multiple $fill on a line split the space evenly, right-aligning trailing content. The hard part is that Claude Code gives the statusline no terminal width (no $COLUMNS, no tty, no JSON field — anthropics/claude-code#22115). We recover it best-effort on macOS/Linux by walking up the parent process chain to an ancestor with a controlling tty and reading its winsize (libproc/procfs + ctty + terminal_size). Resolution order: detected -> $COLUMNS -> [cship] width -> 80, minus [cship] width_offset (default 3). Windows and the web/desktop apps fall back to config/80. Honest limitations (documented in configuration.md + FAQ): relies on the statusline being spawned under a tty-holding ancestor; Nerd Font glyph widths may be off by a column; libproc pulls bindgen at build time on macOS. The $cship.flex stub is removed in favor of $fill. Showcased in the repo cship.toml (fills around the context bar).
…testable offset - render_fill() sizes gaps by display columns, so multi-column `symbol` values align exactly (was repeating by count → overshoot). Remainder padded with spaces. - A line whose only visible content is $fill now renders empty instead of a full-width rule, matching cship's empty-line dropping. - Extract pure apply_offset() and test it unconditionally (the old statusline_width tests were skipped whenever a tty was found). - Clarify that a disabled $fill leaves surrounding literal spaces; doc the bare-rule suppression. From the opus/sonnet/haiku review of the branch.
# Conflicts: # CHANGELOG.md # Cargo.lock # Cargo.toml # cship.toml # docs/faq.md # src/config.rs
|
Thanks for this — it's a genuinely well-built PR, and I appreciate that you flagged the dependency trade-off yourself and pre-wrote the lean alternative. That made the review easy. TL;DR: I'd love to merge the feature, but let's go with the lean What I verifiedI checked the back-compat story carefully and it's clean at runtime:
The layout math ( On simplifying — yes pleaseYou already diagnosed it, so I'll just confirm your instinct: the feature is great, but the dependency tree is disproportionate to what's a deliberately best-effort hack. The thing that tips it for me is the build-time libclang requirement that Your raw So if you're up for it:
Everything else — docs, tests, the lazy fast path — is good as-is and shouldn't need to change. One small thingLet's leave the flagship Thanks again — this is close. |
Adds a Starship-style
$filltoken (configured via[cship.fill]) that expands to fill the remaining width; multiple$fillon a line split the space evenly, so trailing content is right-aligned. Mirrors Starship'sfillmodule (symbol/style/disabled; defaults./bold black). Replaces the old inert$cship.flexstub.The hard part: terminal width
Claude Code doesn't give statusline commands the terminal width — no
$COLUMNS, no controlling tty on the child process, and no width field in the JSON (anthropics/claude-code#22115). So$fillrecovers it best-effort on macOS/Linux by walking up the parent process chain to an ancestor's controlling terminal and reading its window size. Resolution order:…then minus
[cship] width_offset(default3, ≈ the left/right margin Claude Code reserves).Honest limitations (documented in
configuration.md+ FAQ)[cship] widthor 80.unicode-width, nudging alignment by a column (a limitation shared with Starship).Dependencies — and a leaner alternative I'm happy to switch to
This PR's width walk uses
libproc(macOS) +procfs(Linux) +ctty(dev→path) +terminal_size(winsize). Two of those carry weight worth flagging:libprocpullsbindgen→clang-sysas a build dependency — it requires libclang at build time, adds ~390 lockfile lines, and slows macOS builds.ctty(2019, single release) adds a duplicatethiserror v1(the crate already uses v2) and accbuild step, and does aglob+statscan per fill-line on Linux.terminal_sizeis light (pure-Rustrustix) and worth keeping either way.If you'd prefer a minimal dependency tree, I can drop
libproc+ctty+bindgen/clang-sysentirely in favour of a rawlibc+stdimplementation (keeping onlylibc, already a dep, +terminal_size):sysctl(KERN_PROC_PID)→kinfo_proc.e_ppid/e_tdev;libc::devnamefor the device path (~30 lines, about halfunsafe)./proc/<pid>/statforppid/tty_nr;readlink /proc/<pid>/fd/0for the device path (~25 linesstd, noglob).I went with the crate-based version here for readability and to keep
unsafeout of the tree — but I'm glad to swap to the lean version if you'd rather not take onbindgen/ctty. Just say which you prefer.Tests & verification
distribute,build_filled_line(including multi-column symbols, overflow, content-less suppression, and Unicode width), andapply_offset.cargo fmt --check,cargo clippy -- -D warnings, full test suite, and release build.Showcase
cship.tomldemonstrates fills around the context bar. The README /docs/showcase.mdHero examples are intentionally left unchanged pending your call on whether to feature$fillin the flagship recommended config.