Skip to content

feat(tui): color the bash tool's command as shell code - #54704

Closed
Nowaker wants to merge 1 commit into
anomalyco:v1from
Nowaker:bash-syntax
Closed

Nowaker wants to merge 1 commit into
anomalyco:v1from
Nowaker:bash-syntax

Conversation

@Nowaker

@Nowaker Nowaker commented Oct 12, 2026 •

Copy link
Copy Markdown

Note: I'm aware v1 is now the maintenance branch and new features go to v2 only. This PR is here for others to use, and I'll submit the v2 version once I've migrated my whole plugin system to it.

Issue for this PR

Closes #54700

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

The bash tool's command is colored like write and edit already are. It is the same <text>$ command</text> as before with each token a colored span, so it wraps, indents and fits the block exactly as the plain command does; only the colors differ. It draws plain at once and takes its colors when the parser worker answers.

  • util/highlight-cache.ts: a command asks for its colors every time its block is created, so a remounted transcript or reopened session would reparse every command. Results are cached by language and content (LRU, 1000 entries / 4M chars); identical concurrent requests share one round trip; a failure is retried.
  • theme/tool-code.ts: red means a failed or rejected tool call in the transcript, so code inside a tool call never uses red. Every syntax slot that is red, or the theme's error color (builtins use it in every theme), takes a non-red alternative, e.g. variables and builtins take the function color.
  • util/bash-highlight.ts: nvim-treesitter's bash query narrows its number, constant and shebang captures with #lua-match?, which web-tree-sitter does not evaluate, so every word came back as a number. Those patterns are applied after the worker answers. It also drops @spell, which the theme colors as plain text and which turned comments back to the text color.
  • syntax.bash: false in tui.json restores the plain command. On by default. Documented in tui.mdx.

How did you verify your code works?

  • bun typecheck in packages/tui; bun test test/util test/config.test.tsx test/cli/tui test/tool-code-theme.test.ts: 114 pass. shell-command.test.tsx renders a long command with long path tokens as spans and as plain text at 40, 80 and 160 columns and requires identical frames; tool-code-theme.test.ts checks every built-in theme, dark and light, for red or error-colored slots.
  • A real TUI at 80 and 160 columns: the screen text with syntax.bash on and off is byte-identical.
  • Real parser worker on real commands: for/in keywords, $HOME constant, numbers only on numbers.
  • A real TUI on a copied 6,000-part session, through a PTY client on a throwaway tmux server, A/B/B/A against the same tree without the change: scroll p50 13.8 → 17.3 ms, keystroke p50 26.7 → 24.6 ms, idle CPU unchanged (run-to-run spread is larger than either difference).

Screenshots / recordings

Text capture (colors: cd/grep function, "$HOME" string, 10 number):

$ cd /tmp && ls -la | grep -v total; echo "$HOME" $((1 + 2)) && FOO=bar ./run.sh --flag 10

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

This PR is AI generated, but under direct supervision and on request of @Nowaker.

@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Nowaker added a commit to Nowaker/opencode that referenced this pull request Oct 12, 2026
Feature and session records for the bash, heredoc, file language and
tool input coloring (dfbf7f6..8a360b4), upstream PRs anomalyco#54704-anomalyco#54707
and the vt-238 install on desktop and m4max.

AI-Model: anthropic/claude-opus-5-5
AI-Variant: high
AI-Tool: opencode 1.19.0-vt-227-dfb56f76c7
AI-Platform: linux
AI-Harness: Vibeterm e8a9833
AI-Session-ID: ses_ed1e2b932ffe6tTqhsOiGuYXRE
The bash tool's command was the one block of code in a session drawn as
plain text, while write, edit and apply_patch already go through
tree-sitter. It is now the same `<text>$ command</text>` as before, with
each token a colored span, so it wraps, indents and fits the block
exactly as the plain command does; only the colors differ.

The text appears plain at once and takes its colors when the parser
worker answers. Highlighting goes through a cache keyed by language and
content (packages/tui/src/util/highlight-cache.ts), so a remounted
transcript or a reopened session does not reparse every command.
Identical concurrent requests share one round trip, a failed one is
retried, and the cache holds at most 1000 entries or 4M characters.

In the transcript red means a failed or rejected tool call, so the
command is colored with a syntax style that never uses red
(packages/tui/src/theme/tool-code.ts): every syntax slot that comes out
red, or in the theme's error color, takes a non-red alternative, such as
the function color for variables, commands and builtins. A test checks
every built-in theme in dark and light.

nvim-treesitter's bash query narrows its number, constant and shebang
captures with `#lua-match?`, which web-tree-sitter does not evaluate, so
every word came back as a number and every variable as a constant.
packages/tui/src/util/bash-highlight.ts applies those patterns after the
worker answers. It also drops the query's `@spell` captures: the theme
colors spell as plain text, which turned every comment back to the text
color.

`syntax.bash: false` in tui.json restores the plain-text command.
Nowaker added a commit to Nowaker/opencode that referenced this pull request Oct 12, 2026
The colored bash command now lays out byte-identically to the plain one,
and tool-call code never draws in red (b236851, 91e33c5); upstream
branches amended, PRs anomalyco#54704, anomalyco#54705 and anomalyco#54707 updated, vt-241 on
desktop and m4max.

AI-Model: anthropic/claude-opus-5-5
AI-Variant: high
AI-Tool: opencode 1.19.0-vt-227-dfb56f76c7
AI-Platform: linux
AI-Harness: Vibeterm e6434eb
AI-Session-ID: ses_ed1e2b932ffe6tTqhsOiGuYXRE
@opencodejr opencodejr Bot mentioned this pull request Oct 29, 2026
3 of 6 tasks
@Nowaker

Nowaker commented Nov 2, 2026

Copy link
Copy Markdown
Author

Closing: this targets the v1 TUI, which upstream now maintains for critical fixes only, so it is not going to be merged. The branch stays on Nowaker/opencode if anyone wants to pick it up.

@Nowaker Nowaker closed this Nov 2, 2026
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.

1 participant