Code
Displays syntax-highlighted code using Tree-sitter. Supports many languages with accurate, fast highlighting.
Basic usage
Renderable API
import { CodeRenderable, createCliRenderer, SyntaxStyle, RGBA } from "@opentui/core"
const renderer = await createCliRenderer()
const syntaxStyle = SyntaxStyle.fromStyles({
keyword: { fg: RGBA.fromHex("#FF7B72"), bold: true },
string: { fg: RGBA.fromHex("#A5D6FF") },
comment: { fg: RGBA.fromHex("#8B949E"), italic: true },
number: { fg: RGBA.fromHex("#79C0FF") },
function: { fg: RGBA.fromHex("#D2A8FF") },
default: { fg: RGBA.fromHex("#E6EDF3") },
})
const code = new CodeRenderable(renderer, {
id: "code",
content: `function hello() {
// This is a comment
const message = "Hello, world!"
return message
}`,
filetype: "javascript",
syntaxStyle,
width: 50,
height: 10,
})
renderer.root.add(code)
Construct API
Note: Not available yet.
import { Code, Box, createCliRenderer, SyntaxStyle, RGBA } from "@opentui/core"
const renderer = await createCliRenderer()
const syntaxStyle = SyntaxStyle.fromStyles({
keyword: { fg: RGBA.fromHex("#FF7B72"), bold: true },
string: { fg: RGBA.fromHex("#A5D6FF") },
default: { fg: RGBA.fromHex("#E6EDF3") },
})
renderer.root.add(
Box(
{ border: true, width: 50, height: 10 },
Code({
content: 'const x = "hello"',
filetype: "javascript",
syntaxStyle,
}),
),
)
Creating syntax styles
Use SyntaxStyle.fromStyles() to define colors and attributes for syntax tokens:
import { SyntaxStyle, RGBA, parseColor } from "@opentui/core"
const syntaxStyle = SyntaxStyle.fromStyles({
// Basic tokens
keyword: { fg: RGBA.fromHex("#FF7B72"), bold: true },
"keyword.import": { fg: RGBA.fromHex("#FF7B72"), bold: true },
"keyword.operator": { fg: RGBA.fromHex("#FF7B72") },
string: { fg: RGBA.fromHex("#A5D6FF") },
comment: { fg: RGBA.fromHex("#8B949E"), italic: true },
number: { fg: RGBA.fromHex("#79C0FF") },
boolean: { fg: RGBA.fromHex("#79C0FF") },
constant: { fg: RGBA.fromHex("#79C0FF") },
// Functions and types
function: { fg: RGBA.fromHex("#D2A8FF") },
"function.call": { fg: RGBA.fromHex("#D2A8FF") },
"function.method.call": { fg: RGBA.fromHex("#D2A8FF") },
type: { fg: RGBA.fromHex("#FFA657") },
constructor: { fg: RGBA.fromHex("#FFA657") },
// Variables and properties
variable: { fg: RGBA.fromHex("#E6EDF3") },
"variable.member": { fg: RGBA.fromHex("#79C0FF") },
property: { fg: RGBA.fromHex("#79C0FF") },
// Operators and punctuation
operator: { fg: RGBA.fromHex("#FF7B72") },
punctuation: { fg: RGBA.fromHex("#F0F6FC") },
"punctuation.bracket": { fg: RGBA.fromHex("#F0F6FC") },
"punctuation.delimiter": { fg: RGBA.fromHex("#C9D1D9") },
// Default fallback
default: { fg: RGBA.fromHex("#E6EDF3") },
})
Style properties
Each style definition can include:
| Property | Type | Description |
|---|---|---|
fg | RGBA | Foreground (text) color |
bg | RGBA | Background color |
bold | boolean | Bold text |
italic | boolean | Italic text |
underline | boolean | Underlined text |
dim | boolean | Dimmed text |
Supported languages
Code uses Tree-sitter for parsing. Tree-sitter supports these languages:
- TypeScript / JavaScript
- Markdown
- Zig
- And any language with a Tree-sitter grammar
Streaming mode
Enable streaming mode when content arrives incrementally, like LLM output:
const code = new CodeRenderable(renderer, {
id: "streaming-code",
content: "",
filetype: "typescript",
syntaxStyle,
streaming: true, // Enable streaming mode
})
// Later, append content
code.content += "const x = 1\n"
code.content += "const y = 2\n"
Streaming mode optimizes highlighting for incremental updates.
Text selection
Enable text selection for copy operations:
const code = new CodeRenderable(renderer, {
id: "code",
content: sourceCode,
filetype: "typescript",
syntaxStyle,
selectable: true,
selectionBg: "#264F78",
selectionFg: "#FFFFFF",
})
Concealment
The conceal option controls whether certain syntax elements (like markdown formatting characters) are hidden:
const code = new CodeRenderable(renderer, {
id: "markdown",
content: "# Heading\n**bold** text",
filetype: "markdown",
syntaxStyle,
conceal: true, // Hide formatting characters
})
With line numbers
Use LineNumberRenderable to add line numbers:
import { CodeRenderable, LineNumberRenderable, ScrollBoxRenderable } from "@opentui/core"
const code = new CodeRenderable(renderer, {
id: "code",
content: sourceCode,
filetype: "typescript",
syntaxStyle,
width: "100%",
})
const lineNumbers = new LineNumberRenderable(renderer, {
id: "code-with-lines",
target: code,
minWidth: 3,
paddingRight: 1,
fg: "#6b7280",
bg: "#161b22",
width: "100%",
})
// Wrap in ScrollBox for scrolling
const scrollbox = new ScrollBoxRenderable(renderer, {
id: "scrollbox",
width: 60,
height: 20,
})
scrollbox.add(lineNumbers)
Properties
| Property | Type | Default | Description |
|---|---|---|---|
content | string | "" | Source code to display |
filetype | string | - | Language for syntax highlighting |
syntaxStyle | SyntaxStyle | required | Syntax highlighting theme |
streaming | boolean | false | Optimize for incremental content updates |
conceal | boolean | true | Hide concealed syntax elements |
drawUnstyledText | boolean | true | Show text before highlighting completes |
treeSitterClient | TreeSitterClient | - | Custom Tree-sitter client instance |
Inherited from TextBufferRenderable
| Property | Type | Default | Description |
|---|---|---|---|
fg | string | RGBA | - | Default foreground color |
bg | string | RGBA | - | Background color |
selectable | boolean | false | Enable text selection |
selectionBg | string | RGBA | - | Selection background color |
selectionFg | string | RGBA | - | Selection foreground color |
wrapMode | string | "word" | Text wrapping: "none", "char", "word" |
tabIndicator | string | number | - | Tab display character or width |
Additional properties
| Property | Type | Description |
|---|---|---|
lineCount | number | Number of lines in content |
scrollY | number | Current vertical scroll position (get/set) |
scrollX | number | Current horizontal scroll position (get/set) |
scrollWidth | number | Total scrollable width (read-only) |
scrollHeight | number | Total scrollable height (read-only) |
isHighlighting | boolean | Whether highlighting is in progress |
plainText | string | Raw text content |
Markdown styles
For markdown highlighting, use markup-prefixed style names:
const markdownStyle = SyntaxStyle.fromStyles({
"markup.heading": { fg: RGBA.fromHex("#58A6FF"), bold: true },
"markup.heading.1": { fg: RGBA.fromHex("#00FF88"), bold: true, underline: true },
"markup.heading.2": { fg: RGBA.fromHex("#00D7FF"), bold: true },
"markup.bold": { fg: RGBA.fromHex("#F0F6FC"), bold: true },
"markup.strong": { fg: RGBA.fromHex("#F0F6FC"), bold: true },
"markup.italic": { fg: RGBA.fromHex("#F0F6FC"), italic: true },
"markup.list": { fg: RGBA.fromHex("#FF7B72") },
"markup.quote": { fg: RGBA.fromHex("#8B949E"), italic: true },
"markup.raw": { fg: RGBA.fromHex("#A5D6FF") },
"markup.raw.block": { fg: RGBA.fromHex("#A5D6FF") },
"markup.link": { fg: RGBA.fromHex("#58A6FF"), underline: true },
"markup.link.url": { fg: RGBA.fromHex("#58A6FF"), underline: true },
default: { fg: RGBA.fromHex("#E6EDF3") },
})