Skip to content

feat: add BashToolViewer with collapsible output and expanded syntax highlighting#169

Open
psypeal wants to merge 1 commit intomatt1398:mainfrom
psypeal:feat/bash-viewer-collapsible-output
Open

feat: add BashToolViewer with collapsible output and expanded syntax highlighting#169
psypeal wants to merge 1 commit intomatt1398:mainfrom
psypeal:feat/bash-viewer-collapsible-output

Conversation

@psypeal
Copy link
Copy Markdown
Contributor

@psypeal psypeal commented Apr 5, 2026

Summary

  • Add dedicated BashToolViewer component for rendering Bash tool calls with syntax-highlighted output
  • Add CollapsibleOutputSection for long tool outputs with expand/collapse toggle
  • Expand syntax highlighting support in syntaxHighlighter.ts (bash, C, Java, Kotlin, Swift, Scala, Haskell, Lua, Perl, Dart, Elixir, Clojure, Erlang, Zig, Nim, shell)

Test plan

  • pnpm typecheck passes
  • pnpm test — all tests pass
  • Manual: open session with Bash tool calls — verify dedicated viewer renders
  • Manual: long Bash output — verify collapsible section works

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

New Features

  • Added dedicated Bash tool viewer for clearer display of Bash commands and their execution results
  • Expanded syntax highlighting capabilities to support bash, c, java, kotlin, swift, lua, html, yaml, and cpp languages
  • Improved comment detection for multiple programming languages including zsh, fish, and yaml

…hlighting

- Add dedicated BashToolViewer component for Bash tool calls with
  syntax-highlighted command display via CodeBlockViewer
- Expand syntax highlighting with bash, C, Java, Kotlin, Swift, Scala,
  Haskell, Lua, Perl, Dart, Elixir, Clojure, Erlang, Zig, Nim, and
  shell alias keyword sets
- Add hasBashContent check in toolContentChecks
- Wire BashToolViewer into LinkedToolItem rendering pipeline

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a specialized BashToolViewer component to render Bash tool calls with syntax highlighting and collapsible output. It also significantly expands the internal syntax highlighter by adding keyword sets for Bash, C, Java, Kotlin, Swift, Lua, HTML, and YAML, along with corresponding comment style support. However, the changes to the highlighter's fallback logic introduce a regression for Markdown files and include redundant checks for Bash. Additionally, several languages mentioned in the PR's intent (such as Scala, Haskell, and Perl) are currently missing from the implementation.


// If no highlighting support, return plain text as single-element array
if (keywords.size === 0 && !['json', 'css', 'html', 'bash', 'markdown'].includes(language)) {
if (keywords.size === 0 && !['json', 'css', 'bash'].includes(language)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The removal of markdown from this list causes a regression: markdown files (which have no defined keywords in this highlighter) will now be returned as plain text without basic highlighting for backticks (treated as strings), numbers, or operators. Additionally, bash is now redundant in this check because it has been added to the KEYWORDS object, so keywords.size will be non-zero for bash.

Suggested change
if (keywords.size === 0 && !['json', 'css', 'bash'].includes(language)) {
if (keywords.size === 0 && !['json', 'css', 'markdown'].includes(language)) {

Comment on lines +405 to 797
bash: new Set([
'if',
'then',
'else',
'elif',
'fi',
'for',
'while',
'do',
'done',
'case',
'esac',
'in',
'function',
'return',
'local',
'export',
'readonly',
'declare',
'typeset',
'unset',
'shift',
'source',
'eval',
'exec',
'exit',
'trap',
'break',
'continue',
'echo',
'printf',
'read',
'test',
'true',
'false',
'cd',
'pwd',
'mkdir',
'rm',
'cp',
'mv',
'ls',
'cat',
'grep',
'sed',
'awk',
'find',
'sort',
'uniq',
'wc',
'head',
'tail',
'chmod',
'chown',
'sudo',
'apt',
'pip',
'npm',
'pnpm',
'yarn',
'git',
'docker',
'curl',
'wget',
]),
c: new Set([
'auto',
'break',
'case',
'char',
'const',
'continue',
'default',
'do',
'double',
'else',
'enum',
'extern',
'float',
'for',
'goto',
'if',
'inline',
'int',
'long',
'register',
'return',
'short',
'signed',
'sizeof',
'static',
'struct',
'switch',
'typedef',
'union',
'unsigned',
'void',
'volatile',
'while',
'NULL',
'true',
'false',
'include',
'define',
'ifdef',
'ifndef',
'endif',
'pragma',
]),
java: new Set([
'abstract',
'assert',
'boolean',
'break',
'byte',
'case',
'catch',
'char',
'class',
'const',
'continue',
'default',
'do',
'double',
'else',
'enum',
'extends',
'final',
'finally',
'float',
'for',
'if',
'implements',
'import',
'instanceof',
'int',
'interface',
'long',
'native',
'new',
'package',
'private',
'protected',
'public',
'return',
'short',
'static',
'strictfp',
'super',
'switch',
'synchronized',
'this',
'throw',
'throws',
'transient',
'try',
'void',
'volatile',
'while',
'true',
'false',
'null',
'var',
'yield',
'record',
'sealed',
'permits',
]),
kotlin: new Set([
'abstract',
'annotation',
'as',
'break',
'by',
'catch',
'class',
'companion',
'const',
'constructor',
'continue',
'crossinline',
'data',
'do',
'else',
'enum',
'external',
'false',
'final',
'finally',
'for',
'fun',
'if',
'import',
'in',
'infix',
'init',
'inline',
'inner',
'interface',
'internal',
'is',
'lateinit',
'noinline',
'null',
'object',
'open',
'operator',
'out',
'override',
'package',
'private',
'protected',
'public',
'reified',
'return',
'sealed',
'super',
'suspend',
'this',
'throw',
'true',
'try',
'typealias',
'val',
'var',
'vararg',
'when',
'where',
'while',
]),
swift: new Set([
'associatedtype',
'break',
'case',
'catch',
'class',
'continue',
'default',
'defer',
'deinit',
'do',
'else',
'enum',
'extension',
'fallthrough',
'false',
'fileprivate',
'for',
'func',
'guard',
'if',
'import',
'in',
'init',
'inout',
'internal',
'is',
'let',
'nil',
'open',
'operator',
'override',
'private',
'protocol',
'public',
'repeat',
'rethrows',
'return',
'self',
'static',
'struct',
'subscript',
'super',
'switch',
'throw',
'throws',
'true',
'try',
'typealias',
'var',
'where',
'while',
'async',
'await',
]),
lua: new Set([
'and',
'break',
'do',
'else',
'elseif',
'end',
'false',
'for',
'function',
'goto',
'if',
'in',
'local',
'nil',
'not',
'or',
'repeat',
'return',
'then',
'true',
'until',
'while',
'self',
'require',
'print',
'type',
'tostring',
'tonumber',
'pairs',
'ipairs',
'error',
'pcall',
'xpcall',
'setmetatable',
'getmetatable',
]),
html: new Set([
'div',
'span',
'html',
'head',
'body',
'title',
'meta',
'link',
'script',
'style',
'section',
'article',
'header',
'footer',
'nav',
'main',
'aside',
'form',
'input',
'button',
'select',
'option',
'textarea',
'label',
'table',
'thead',
'tbody',
'tr',
'th',
'td',
'ul',
'ol',
'li',
'a',
'p',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'img',
'video',
'audio',
'canvas',
'svg',
'class',
'id',
'src',
'href',
'type',
'name',
'value',
'placeholder',
'alt',
'width',
'height',
'true',
'false',
]),
yaml: new Set([
'true',
'false',
'null',
'yes',
'no',
'on',
'off',
]),
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The PR description mentions adding syntax highlighting support for several languages that are missing from the implementation, including Scala, Haskell, Perl, Dart, Elixir, Clojure, Erlang, Zig, and Nim. These should be added to the KEYWORDS object to match the stated intent of the PR.

@coderabbitai coderabbitai bot added the feature request New feature or request label Apr 5, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 5, 2026

📝 Walkthrough

Walkthrough

The pull request adds Bash tool rendering support by introducing a new BashToolViewer component that displays bash commands and their results. It updates the linked tool item component to conditionally render Bash tools, adds a utility to detect Bash tool content, and expands syntax highlighting capabilities for multiple programming languages.

Changes

Cohort / File(s) Summary
Bash Viewer Component
src/renderer/components/chat/items/linkedTool/BashToolViewer.tsx, src/renderer/components/chat/items/linkedTool/index.ts, src/renderer/components/chat/items/LinkedToolItem.tsx
Introduces new BashToolViewer React component that renders bash commands via CodeBlockViewer and conditionally displays results in a collapsible section. Updates LinkedToolItem to route Bash tools to this viewer and export the component from the linkedTool module.
Bash Content Detection
src/renderer/utils/toolRendering/toolContentChecks.ts, src/renderer/utils/toolRendering/index.ts
Adds hasBashContent helper function that checks if a linked tool has a bash command to display, and exports it from the toolRendering utilities module.
Syntax Highlighting Expansion
src/renderer/components/chat/viewers/syntaxHighlighter.ts
Expands KEYWORDS dictionary with bash, c, java, kotlin, swift, lua, html, and yaml keyword sets. Adds language aliasing for zsh/fish to use bash keywords and cpp/hpp to use C/C++ keywords. Updates comment detection rules to support additional languages and adjusts fallback highlighting logic.

Possibly related PRs

Suggested labels

feature request


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/renderer/components/chat/viewers/syntaxHighlighter.ts (1)

803-805: Missing shell alias mentioned in PR objectives.

The PR description mentions adding shell (alias) keyword set, but only zsh and fish are aliased to bash. Consider adding shell as well for consistency with common language identifiers:

 // Extend zsh/fish to use bash keywords
 KEYWORDS.zsh = KEYWORDS.bash;
 KEYWORDS.fish = KEYWORDS.bash;
+KEYWORDS.shell = KEYWORDS.bash;
+KEYWORDS.sh = KEYWORDS.bash;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/components/chat/viewers/syntaxHighlighter.ts` around lines 803 -
805, The PR added aliases for zsh and fish but forgot the requested "shell"
alias; update the keyword aliasing in the syntaxHighlighter by adding
KEYWORDS.shell = KEYWORDS.bash alongside KEYWORDS.zsh and KEYWORDS.fish so the
"shell" language identifier uses the same bash keyword set (refer to the
KEYWORDS.zsh, KEYWORDS.fish, and KEYWORDS.bash symbols).
src/renderer/components/chat/items/linkedTool/BashToolViewer.tsx (1)

24-26: Type assertion is safe but could be more defensive.

The as string assertion on line 25 relies on hasBashContent being called before this component renders. While this contract is currently enforced by LinkedToolItem.tsx, a more defensive approach would be:

-  const command = linkedTool.input.command as string;
+  const command = String(linkedTool.input.command ?? '');

This is a minor concern since the precondition is checked, but it adds resilience against future refactoring.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/components/chat/items/linkedTool/BashToolViewer.tsx` around
lines 24 - 26, The BashToolViewer component currently uses unsafe type
assertions (command = linkedTool.input.command as string) that rely on an
external precondition; make it defensive by validating and narrowing the types
inside BashToolViewer: check hasBashContent(linkedTool) or verify
linkedTool.input?.command is a string before using it, fall back to a safe
default or render null/placeholder when invalid, and update uses of
linkedTool.input.description similarly; reference the BashToolViewer component,
linkedTool.input.command/description, and the existing hasBashContent helper
(and LinkedToolItem.tsx contract) when implementing the checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/renderer/components/chat/items/linkedTool/BashToolViewer.tsx`:
- Around line 24-26: The BashToolViewer component currently uses unsafe type
assertions (command = linkedTool.input.command as string) that rely on an
external precondition; make it defensive by validating and narrowing the types
inside BashToolViewer: check hasBashContent(linkedTool) or verify
linkedTool.input?.command is a string before using it, fall back to a safe
default or render null/placeholder when invalid, and update uses of
linkedTool.input.description similarly; reference the BashToolViewer component,
linkedTool.input.command/description, and the existing hasBashContent helper
(and LinkedToolItem.tsx contract) when implementing the checks.

In `@src/renderer/components/chat/viewers/syntaxHighlighter.ts`:
- Around line 803-805: The PR added aliases for zsh and fish but forgot the
requested "shell" alias; update the keyword aliasing in the syntaxHighlighter by
adding KEYWORDS.shell = KEYWORDS.bash alongside KEYWORDS.zsh and KEYWORDS.fish
so the "shell" language identifier uses the same bash keyword set (refer to the
KEYWORDS.zsh, KEYWORDS.fish, and KEYWORDS.bash symbols).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9c0ae152-3f3e-40dc-b3cc-884f4c9f4db6

📥 Commits

Reviewing files that changed from the base of the PR and between c0708bb and fa03149.

📒 Files selected for processing (6)
  • src/renderer/components/chat/items/LinkedToolItem.tsx
  • src/renderer/components/chat/items/linkedTool/BashToolViewer.tsx
  • src/renderer/components/chat/items/linkedTool/index.ts
  • src/renderer/components/chat/viewers/syntaxHighlighter.ts
  • src/renderer/utils/toolRendering/index.ts
  • src/renderer/utils/toolRendering/toolContentChecks.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature request New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant