Skip to content

Set commands apart with a line and a shade - #23

Merged
srozen merged 2 commits into
mainfrom
command-separators
Nov 11, 2026
Merged

srozen merged 2 commits into
mainfrom
command-separators

Conversation

@srozen

@srozen srozen commented Nov 11, 2026 •

Copy link
Copy Markdown
Owner

Closes #13. The terminal draws a thin line above each command's prompt and shades every other command, prompt and output together. A command that failed gets a bar beside it in the margin. Lines and shades are on by default, each with a switch in Settings › Appearance › Commands (zsh, with shell integration).

Screenshots

A line above each prompt, every other command shaded, a red bar beside the failed make lint, and the shade of the prompt you're at fading out below the cursor.

Codec with lines between commands, alternate shades and a bar beside the failed command

The four themes: the line, the shade and the bar all come from the theme's colors.

Codec, Arctic, Amber and Daylight with the separators

A running command has the bar in the accent color.

A test run part way through, with the accent bar beside it

Summary

 <PaneView>
+  <CommandSeparatorView>     # under the terminal: shades, lines, margin bars
   <CodecTerminalView>        # background already clear, so text keeps its contrast
   <FindHighlightView> …
refreshCommandSeparators          (scroll, output tick, prompt drawn, command started, layout, settings)
  off, no integration, or full-screen program  → draw nothing
  rows moved by a resize                       → draw nothing, find the commands again 0.3 s after the last step
  CommandBlocks.spans(overlapping: screen)     → each command's rows, every other one marked
  per command:
    line at its top (through the middle of a prompt's blank first line)
    shade from its line to the next; the newest fades out below its last row
    bar in the margin if it failed (alert) or is running (accent); nothing if it worked
  • The line spans the text, not the pane, so it doesn't read as a split. The shade spans the pane.
  • The bar sits where the mark over a command gone back to is drawn, a little quieter. It follows the "Line between commands" switch.
  • The prompt waiting for a command counts as the next command. Pane now remembers where zsh marked it (133;B), because between a command finishing and its prompt the cursor alone doesn't say where the output ends.
  • At each prompt, CommandBlocks.forgetBlocksGone drops the commands whose command line is no longer on screen. After clear or ⌃L they used to linger until the next command ran.
  • The refresh runs at every frame of a scroll, so it copies the screen once instead of going through TerminalGrid: about 5.6 ms per refresh in a debug build on a 297×86 terminal, down from about 32 ms. Not measured in a release build.

Evidence

  • Before:
    Before: commands run together
    After: the first screenshot above.
  • New tests, all passing with the rest of the suite (566 tests) and the universal release build:
    • CommandSeparatorTests (real zsh panes): a line above each command and a shade on every other one, each setting on its own, a pane leaving and rejoining its window, a prompt with a blank first line, bars beside a failed and a running command, clear, a full-screen program, a resize that rewraps.
    • CommandBlocksTests: spans, commands past the cursor left out, every other command staying the same one as old ones are dropped, forgetting cleared commands.

Merge Danger

Door: two-way

Two new preferences default to on. Turning both off, or reverting, restores the old look; nothing stored changes shape.

Blast Radius: terminal

  • Every zsh pane looks different on first launch after updating, which is the point of the issue but will surprise people who didn't ask for it.
  • promptWasDrawn now prunes blocks when a command line is gone from the screen. Copy Output and Select Output read blocks, so a wrong prune would disable them for that command until the next relocation. Timeline entries are untouched.
  • A per-frame screen copy during scrolling in integrated panes with either setting on.
  • Pressing Return at an empty prompt moves the line to the newest prompt; the empty ones above get none.
  • All 13 images in docs/images were retaken. The hero's git log shows this branch's name, because the tour clones the repository.

🤖 Generated with Claude Code

srozen and others added 2 commits November 11, 2026 14:31
A thin line now runs above each command's prompt in the terminal, and
every other command sits on a slightly different shade, its prompt and its
output together, so a long scrollback reads as one command after another.
The prompt waiting for a command counts as the next one. Both are on by
default, each with its switch in Settings › Appearance › Commands, and both
need zsh's shell integration, which is what tells commands apart.

They're drawn by a view under the terminal, whose own background is clear:
text over a shade keeps its contrast, and whatever the terminal fills in (a
selection, a prompt chip) covers the line. The line spans the text, not the
pane, so it doesn't read as a split; the shade spans the pane. Where a
prompt starts with a blank line, as Codec's does, the line goes through the
middle of it.

CommandBlocks works out each command's rows, and counts the commands it
dropped so that every other one stays the same one. Pane now remembers
where zsh marked the waiting prompt, since between a command finishing and
its prompt the cursor alone doesn't say where the output ends. At each
prompt it also forgets the commands whose command line is no longer on
screen: after `clear` or ⌃L they used to linger until the next command.

The refresh runs at every frame of a scroll, so it copies the screen once
rather than going through TerminalGrid. After a resize the lines are hidden
until the commands are found again, a moment after the last step, instead
of searching the whole scrollback at each one. They're hidden too while a
full-screen program has the screen.

The screenshots are retaken, since every terminal in them changed.

Closes #13

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…de out

A command that failed now has a bar beside it in the margin, in the theme's
alert color, from its prompt to the end of its output, so the failures are
what stands out when scrolling back. The command that's running has one in
the accent color, and commands that worked have nothing. The bar is where
the mark over a command gone back to is drawn, a little quieter, and comes
with the line between commands rather than a setting of its own.

The newest command isn't over, so its shade no longer ends in an edge under
the cursor: it fades out over a row below its last. That also hides the
steps the shade grew in while slow output came in.

The line is a little fainter so the bar leads, and after a resize hid them
the separators fade back in rather than pop.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@srozen
srozen merged commit e5b59c0 into main Nov 11, 2026
1 check passed
@srozen
srozen deleted the command-separators branch November 11, 2026 14:39
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.

Have a separator between the queries

1 participant