Code

使用 Tree-sitter 展示语法高亮的代码。支持多种语言,提供准确、快速的高亮显示。

基本用法

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

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,
    }),
  ),
)

创建语法样式

使用 SyntaxStyle.fromStyles() 为语法标记定义颜色和属性:

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") },
})

样式属性

每个样式定义可以包含:

属性类型说明
fgRGBA前景色(文字颜色)
bgRGBA背景色
boldboolean粗体文字
italicboolean斜体文字
underlineboolean下划线文字
dimboolean暗淡文字

支持的语言

Code 使用 Tree-sitter 进行解析。Tree-sitter 支持以下语言:

  • TypeScript / JavaScript
  • Markdown
  • Zig
  • 以及任何具有 Tree-sitter 语法的语言

流式模式

当内容以增量方式到达时(例如 LLM 输出),启用流式模式:

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"

流式模式针对增量更新优化了高亮显示。

文本选择

启用文本选择以支持复制操作:

const code = new CodeRenderable(renderer, {
  id: "code",
  content: sourceCode,
  filetype: "typescript",
  syntaxStyle,
  selectable: true,
  selectionBg: "#264F78",
  selectionFg: "#FFFFFF",
})

隐藏语法元素

conceal 选项控制是否隐藏某些语法元素(如 markdown 格式化字符):

const code = new CodeRenderable(renderer, {
  id: "markdown",
  content: "# Heading\n**bold** text",
  filetype: "markdown",
  syntaxStyle,
  conceal: true, // Hide formatting characters
})

显示行号

使用 LineNumberRenderable 添加行号:

import { CodeRenderable, LineNumberRenderable, RGBA, ScrollBoxRenderable, SyntaxStyle } from "@opentui/core"

const sourceCode = "const answer = 42\nconsole.log(answer)\n"
const syntaxStyle = SyntaxStyle.fromStyles({
  default: { fg: RGBA.fromHex("#E6EDF3") },
})

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)
renderer.root.add(scrollbox)

属性

属性类型默认值说明
contentstring""要显示的源代码
filetypestring-语法高亮的语言
syntaxStyleSyntaxStyle必填语法高亮主题
streamingbooleanfalse针对增量内容更新进行优化
concealbooleantrue隐藏被隐藏的语法元素
drawUnstyledTextbooleantrue在高亮完成前显示文本
treeSitterClientTreeSitterClient-自定义 Tree-sitter 客户端实例

继承自 TextBufferRenderable

属性类型默认值说明
fgstring | RGBA-默认前景色
bgstring | RGBA-背景色
selectablebooleanfalse启用文本选择
selectionBgstring | RGBA-选区背景色
selectionFgstring | RGBA-选区前景色
wrapModestring"word"文本换行模式:"none""char""word"
tabIndicatorstring | number-Tab 显示字符或宽度

附加属性

属性类型说明
lineCountnumber内容的行数
scrollYnumber当前垂直滚动位置(可读写)
scrollXnumber当前水平滚动位置(可读写)
scrollWidthnumber总可滚动宽度(只读)
scrollHeightnumber总可滚动高度(只读)
isHighlightingboolean是否正在进行高亮处理
plainTextstring纯文本内容

Markdown 样式

对于 markdown 高亮,使用 markup 前缀的样式名称:

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") },
})