mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 04:11:10 -05:00
Add theme based syntax highlighting for code blocks
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
import { ClaudeAsk, ClaudeMessage, ClaudeSay, ClaudeSayTool } from "@shared/ExtensionMessage"
|
||||
import { VSCodeBadge, VSCodeButton, VSCodeProgressRing } from "@vscode/webview-ui-toolkit/react"
|
||||
import React, { useState } from "react"
|
||||
import { ClaudeMessage, ClaudeAsk, ClaudeSay, ClaudeSayTool } from "@shared/ExtensionMessage"
|
||||
import { VSCodeButton, VSCodeProgressRing, VSCodeBadge } from "@vscode/webview-ui-toolkit/react"
|
||||
import { COMMAND_OUTPUT_STRING } from "../utilities/combineCommandSequences"
|
||||
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"
|
||||
import { dark } from "react-syntax-highlighter/dist/esm/styles/prism"
|
||||
import CodeBlock from "./CodeBlock"
|
||||
import { SyntaxHighlighterStyle } from "../utilities/getSyntaxHighlighterStyleFromTheme"
|
||||
import CodeBlock from "./CodeBlock/CodeBlock"
|
||||
|
||||
interface ChatRowProps {
|
||||
message: ClaudeMessage
|
||||
syntaxHighlighterStyle: SyntaxHighlighterStyle
|
||||
}
|
||||
|
||||
const ChatRow: React.FC<ChatRowProps> = ({ message }) => {
|
||||
const ChatRow: React.FC<ChatRowProps> = ({ message, syntaxHighlighterStyle }) => {
|
||||
const [isExpanded, setIsExpanded] = useState(false)
|
||||
const cost = message.text != null && message.say === "api_req_started" ? JSON.parse(message.text).cost : undefined
|
||||
|
||||
@@ -126,7 +126,7 @@ const ChatRow: React.FC<ChatRowProps> = ({ message }) => {
|
||||
borderRadius: "3px",
|
||||
padding: "8px",
|
||||
whiteSpace: "pre-line",
|
||||
wordWrap: "break-word"
|
||||
wordWrap: "break-word",
|
||||
}}>
|
||||
<span>{message.text}</span>
|
||||
</div>
|
||||
@@ -188,7 +188,11 @@ const ChatRow: React.FC<ChatRowProps> = ({ message }) => {
|
||||
{toolIcon("edit")}
|
||||
<span style={{ fontWeight: "bold" }}>Claude wants to edit this file:</span>
|
||||
</div>
|
||||
<CodeBlock diff={tool.diff!} path={tool.path!} />
|
||||
<CodeBlock
|
||||
diff={tool.diff!}
|
||||
path={tool.path!}
|
||||
syntaxHighlighterStyle={syntaxHighlighterStyle}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
case "newFileCreated":
|
||||
@@ -200,7 +204,11 @@ const ChatRow: React.FC<ChatRowProps> = ({ message }) => {
|
||||
Claude wants to create a new file:
|
||||
</span>
|
||||
</div>
|
||||
<CodeBlock code={tool.content!} path={tool.path!} />
|
||||
<CodeBlock
|
||||
code={tool.content!}
|
||||
path={tool.path!}
|
||||
syntaxHighlighterStyle={syntaxHighlighterStyle}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
case "readFile":
|
||||
@@ -210,7 +218,11 @@ const ChatRow: React.FC<ChatRowProps> = ({ message }) => {
|
||||
{toolIcon("file-code")}
|
||||
<span style={{ fontWeight: "bold" }}>Claude wants to read this file:</span>
|
||||
</div>
|
||||
<CodeBlock code={tool.content!} path={tool.path!} />
|
||||
<CodeBlock
|
||||
code={tool.content!}
|
||||
path={tool.path!}
|
||||
syntaxHighlighterStyle={syntaxHighlighterStyle}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
case "listFiles":
|
||||
@@ -222,7 +234,12 @@ const ChatRow: React.FC<ChatRowProps> = ({ message }) => {
|
||||
Claude wants to view this directory:
|
||||
</span>
|
||||
</div>
|
||||
<CodeBlock code={tool.content!} path={tool.path!} language="shell-session" />
|
||||
<CodeBlock
|
||||
code={tool.content!}
|
||||
path={tool.path!}
|
||||
language="shell-session"
|
||||
syntaxHighlighterStyle={syntaxHighlighterStyle}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -260,7 +277,11 @@ const ChatRow: React.FC<ChatRowProps> = ({ message }) => {
|
||||
</div>
|
||||
<div style={contentStyle}>
|
||||
<div>
|
||||
<CodeBlock code={command} language="shell-session" />
|
||||
<CodeBlock
|
||||
code={command}
|
||||
language="shell-session"
|
||||
syntaxHighlighterStyle={syntaxHighlighterStyle}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{output && (
|
||||
@@ -268,7 +289,11 @@ const ChatRow: React.FC<ChatRowProps> = ({ message }) => {
|
||||
<p style={{ ...contentStyle, margin: "10px 0 10px 0" }}>
|
||||
{COMMAND_OUTPUT_STRING}
|
||||
</p>
|
||||
<CodeBlock code={output} language="shell-session" />
|
||||
<CodeBlock
|
||||
code={output}
|
||||
language="shell-session"
|
||||
syntaxHighlighterStyle={syntaxHighlighterStyle}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
@@ -318,7 +343,7 @@ const ChatRow: React.FC<ChatRowProps> = ({ message }) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
padding: "10px 20px 10px 20px",
|
||||
padding: "10px 15px 10px 15px",
|
||||
}}>
|
||||
{renderContent()}
|
||||
{isExpanded && message.say === "api_req_started" && (
|
||||
@@ -326,6 +351,7 @@ const ChatRow: React.FC<ChatRowProps> = ({ message }) => {
|
||||
<CodeBlock
|
||||
code={JSON.stringify(JSON.parse(message.text || "{}").request, null, 2)}
|
||||
language="json"
|
||||
syntaxHighlighterStyle={syntaxHighlighterStyle}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -9,13 +9,16 @@ import { getApiMetrics } from "../utilities/getApiMetrics"
|
||||
import { vscode } from "../utilities/vscode"
|
||||
import ChatRow from "./ChatRow"
|
||||
import TaskHeader from "./TaskHeader"
|
||||
import { getSyntaxHighlighterStyleFromTheme } from "../utilities/getSyntaxHighlighterStyleFromTheme"
|
||||
import vsDarkPlus from "react-syntax-highlighter/dist/esm/styles/prism/vsc-dark-plus"
|
||||
|
||||
interface ChatViewProps {
|
||||
messages: ClaudeMessage[]
|
||||
isHidden: boolean
|
||||
vscodeThemeName?: string
|
||||
}
|
||||
// maybe instead of storing state in App, just make chatview always show so dont conditionally load/unload? need to make sure messages are persisted (i remember seeing something about how webviews can be frozen in docs)
|
||||
const ChatView = ({ messages, isHidden }: ChatViewProps) => {
|
||||
const ChatView = ({ messages, isHidden, vscodeThemeName }: ChatViewProps) => {
|
||||
//const task = messages.length > 0 ? (messages[0].say === "task" ? messages[0] : undefined) : undefined
|
||||
const task = messages.length > 0 ? messages[0] : undefined // leaving this less safe version here since if the first message is not a task, then the extension is in a bad state and needs to be debugged (see ClaudeDev.abort)
|
||||
const modifiedMessages = useMemo(() => combineApiRequests(combineCommandSequences(messages.slice(1))), [messages])
|
||||
@@ -34,6 +37,16 @@ const ChatView = ({ messages, isHidden }: ChatViewProps) => {
|
||||
const [primaryButtonText, setPrimaryButtonText] = useState<string | undefined>(undefined)
|
||||
const [secondaryButtonText, setSecondaryButtonText] = useState<string | undefined>(undefined)
|
||||
|
||||
const [syntaxHighlighterStyle, setSyntaxHighlighterStyle] = useState(vsDarkPlus)
|
||||
|
||||
useEffect(() => {
|
||||
if (!vscodeThemeName) return
|
||||
const theme = getSyntaxHighlighterStyleFromTheme(vscodeThemeName)
|
||||
if (theme) {
|
||||
setSyntaxHighlighterStyle(theme)
|
||||
}
|
||||
}, [vscodeThemeName])
|
||||
|
||||
const scrollToBottom = (instant: boolean = false) => {
|
||||
const options = {
|
||||
containerId: "chat-view-container",
|
||||
@@ -320,7 +333,7 @@ const ChatView = ({ messages, isHidden }: ChatViewProps) => {
|
||||
overflowY: "auto",
|
||||
}}>
|
||||
{modifiedMessages.map((message, index) => (
|
||||
<ChatRow key={index} message={message} />
|
||||
<ChatRow key={index} message={message} syntaxHighlighterStyle={syntaxHighlighterStyle} />
|
||||
))}
|
||||
</div>
|
||||
<div
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import React, { useMemo, useState } from "react"
|
||||
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"
|
||||
import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism"
|
||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
||||
import { getLanguageFromPath } from "../utilities/getLanguageFromPath"
|
||||
import { useMemo, useState } from "react"
|
||||
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"
|
||||
import { getLanguageFromPath } from "../../utilities/getLanguageFromPath"
|
||||
import { SyntaxHighlighterStyle } from "../../utilities/getSyntaxHighlighterStyleFromTheme"
|
||||
|
||||
/*
|
||||
const vscodeSyntaxStyle: React.CSSProperties = {
|
||||
backgroundColor: "var(--vscode-editor-background)",
|
||||
@@ -62,13 +63,12 @@ interface CodeBlockProps {
|
||||
diff?: string
|
||||
language?: string | undefined
|
||||
path?: string
|
||||
syntaxHighlighterStyle: SyntaxHighlighterStyle
|
||||
}
|
||||
|
||||
const CodeBlock = ({ code, diff, language, path }: CodeBlockProps) => {
|
||||
const CodeBlock = ({ code, diff, language, path, syntaxHighlighterStyle }: CodeBlockProps) => {
|
||||
const [isExpanded, setIsExpanded] = useState(false)
|
||||
|
||||
const backgroundColor = oneDark['pre[class*="language-"]'].background as string
|
||||
|
||||
/*
|
||||
We need to remove leading non-alphanumeric characters from the path in order for our leading ellipses trick to work.
|
||||
|
||||
@@ -83,13 +83,11 @@ const CodeBlock = ({ code, diff, language, path }: CodeBlockProps) => {
|
||||
[path, language, code]
|
||||
)
|
||||
|
||||
console.log(inferredLanguage)
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
borderRadius: "3px",
|
||||
backgroundColor: backgroundColor,
|
||||
backgroundColor: "var(--vscode-editor-background)",
|
||||
overflow: "hidden", // This ensures the inner scrollable area doesn't overflow the rounded corners
|
||||
}}>
|
||||
{path && (
|
||||
@@ -132,7 +130,16 @@ const CodeBlock = ({ code, diff, language, path }: CodeBlockProps) => {
|
||||
<SyntaxHighlighter
|
||||
wrapLines={false}
|
||||
language={diff ? "diff" : inferredLanguage} // "diff" automatically colors changed lines in green/red
|
||||
style={oneDark}
|
||||
style={{
|
||||
...syntaxHighlighterStyle,
|
||||
// Our syntax highlighter style doesn't always match the vscode theme 1:1, so we'll apply sensible styles here that vscode exposes to us
|
||||
'code[class*="language-"]': {
|
||||
background: "var(--vscode-editor-background)",
|
||||
},
|
||||
'pre[class*="language-"]': {
|
||||
background: "var(--vscode-editor-background)",
|
||||
},
|
||||
}}
|
||||
customStyle={{
|
||||
margin: 0,
|
||||
padding: "6px 10px",
|
||||
Reference in New Issue
Block a user