Repository navigation
Conversation
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.
Generic tool output was drawn as plain text, and nothing knows its type: a plugin tool returns a string and an MCP text result carries no content type, so a JSON result from `browser` read as a grey wall. `syntax.tool_output` in tui.json maps a tool name or glob (`browser`, `github_*`, `*`) to a language id, `auto` or `none`; an exact name wins over globs and the most specific glob over the rest (packages/tui/src/util/tool-output.ts). `auto` colors output that is a JSON object or array: a bounded sniff (bracket pair, at most 100,000 characters, one parse) whose answer is cached by content. Only output that is shown is sniffed or colored. Unset by default, so output stays plain as upstream draws it. The output is one text renderable whose content becomes the same text as colored chunks when the parser worker answers, so it wraps exactly as the plain text does (test/cli/tui/tool-output.test.tsx compares the frames at 40, 80 and 160 columns), and it uses the non-red tool-code palette, since red means a failed tool call. The whole output is highlighted, once and cached, even while the block is collapsed: a preview cut through the middle of a JSON value does not parse, so the preview takes the whole output's highlights that fall inside the part it shares with the output, and its ellipsis stays plain.
Reads and searches print code from files, and it is drawn plain: a `cat x.ts | sed -n 1,60p`, `grep -n`, an `rg` with headings, a GitHub code search snippet. syntax.file_output (default off) colors it: - Bash output is colored when the command reads files of one language (cat, head, tail, sed, nl, awk, bat, git show <ref>:<path>, chained or piped through filters), when it is a whole JSON document or a diff, and line by line where each line names its file: `path:12:`, `path-12-`, `path:`, rg headings, or a `12:` gutter on files of one language. A `--type` or `--glob` of one language counts too. - The read and grep tools' rows can be clicked to show what they found, colored, and folded back. - Plugin and MCP output that syntax.tool_output leaves alone: GitHub code search snippets by their Path, docs with fenced code as markdown, and the line shapes above. 'none' for a tool keeps it plain. Prefixes (paths, line numbers, headers) are muted. Each file's lines are highlighted together once, cached, and the colors land on whatever part of them the shown text holds, so a collapsed preview is colored like the expanded output. The language is worked out once per finished call; output over 100,000 characters, past 64 files, or of no clear language stays plain.
Contributor
|
The following comment was made by an LLM, it may be inaccurate: |
1 task done
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 #56006
Builds on #54968 (plugin and MCP tool output coloring), which builds on #54704 (bash command coloring). Their commits come first; review only the last commit.
Type of change
What does this PR do?
Reads and searches print code from files, and it is drawn plain.
syntax.file_output(default off) colors it in each file's language:cat,head,tail,sed -n,nl,awk,bat,git show <ref>:<path>, chained or piped through filters likeheadorgrep), its output is colored whole. Lines that name their file (path:12:code,path-12-code,path:code, rg headings) are colored per file. A12:gutter takes the command's language, and so does anrg -t pyor--glob '*.rs'. Output that is a whole JSON document or starts like a diff is colored as such.syntax.tool_outputleaves alone: GitHub code search snippets (grep_app) in the language of eachPath:, docs with fenced code (context7) as markdown, and the line shapes above. A tool set tononestays plain.Path, line-number and header prefixes are muted; red is never used. Output stays plain when the language is unclear: files of different languages read by one command, a command that also runs something else (
ls && cat a.ts), or a pipe through a transform (cat a.json | jq).Performance: the language is worked out once per finished call, never while it streams or per frame. Each file's lines are highlighted together once in the parser worker and cached by content, and the colors land on whatever part of them the shown text holds, so a collapsed preview is colored like the expanded output. Output over 100,000 characters stays plain, and only the first 64 files of a search are highlighted.
The design comes from ten days of my own tool history: 36,910 of 57,040 bash calls had a read or search stage, 19,673 of them naming files of a single language; there were 12,816 read calls and 873 grep calls.
How did you verify your code works?
bun typecheckin packages/tui;bun testin packages/tui: 252 pass. Unit tests cover command parsing (pipes, chains, quoting,--type/--glob,git show), every output shape, the read and grep tool formats, code search snippets, and mapping a collapsed preview back onto the output. Frame tests show colored output wraps byte-identically to the plain text at 40, 80 and 160 columns.grep -nover a.tsfile, anrg --headingacross.tsand.md, ased -nof a.pyfile, a read of a.gofile (clicked open) and a grep_app result: the code is in its language's colors, prefixes are muted, and the layout is unchanged.Go string literals stay plain: nvim-treesitter's Go query captures them again as
@spell, which has no style. That affects every Go view, file tools included, and is not changed here.Screenshots / recordings
rg -n --heading output src, the path and12:muted, the code colored as TypeScript and markdown:Checklist
This PR is AI generated, but under direct supervision and on request of @Nowaker.