Help us shape the future of Go! Take the 2026 Go Developer Survey

codehl

package
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 5, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package codehl classifies the spans of a fenced code block for syntax highlighting in the assistant's answers: SQL, Go, Python, JavaScript, JSON and shell.

WHY A HAND-WRITTEN LEXER and not chroma or a grammar: the answers are short, redrawn every frame while they stream, and only a handful of languages matter in a SQL client's answers. A table-driven scanner — comments, strings, numbers, a keyword list — is a few hundred lines with no dependency, and it degrades gracefully: a construct it does not know (a JS regex literal, a Go struct tag) is merely uncolored or colored as its nearest lexical cousin, never an error.

SQL is not lexed here: it delegates to sqlsplit.Lex, the scanner the editor colors with, so a statement looks the same in an answer as it will once inserted into the editor. Shell has a scanner of its own too (lexShell): its quoting, $variables, word-bound comments and heredocs fit none of the C-family switches.

The web pane draws answers in the browser, so web/static/js/hl.js mirrors this file rule for rule. Its keyword lists are checked against Keywords by web's tests; the scanning rules are kept in step by hand.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Keywords

func Keywords(tag string) []string

Keywords returns the sorted keyword list of a language (by fence tag), so the browser's copy in hl.js can be tested against the one source of truth.

func Lang

func Lang(tag string) string

Lang maps a fence's language tag to the lexer that draws it: "sql", "go", "python", "js", "json", "shell", or "" for a language not highlighted.

An untagged fence is SQL, the same call tui/chat.go isSQLLang makes for ⤓ insert: the preamble asks for ```sql and models often drop the tag, so in a SQL assistant an untagged block is overwhelmingly SQL. Coloring a plain-text block that way costs little — only SQL keywords light up. The one exception, decided by Lex from the content, is untagged JSON.

Types

type Kind

type Kind int

Kind classifies a span. Text is everything no span covers.

const (
	Text    Kind = iota
	Keyword      // a reserved word (and the literal constants: nil, None, true…)
	String       // any string, rune or template literal
	Number       // a numeric literal
	Comment      // line or block comment
	Ident        // a quoted SQL identifier ("…" or `…`)
	Param        // a SQL bind parameter ($1, ?, :name)
	// Var is a shell variable ($HOME, ${X:-1}, $?). It was once drawn as
	// Param, which both front ends color as an error (bind parameters are
	// rare enough in SQL to deserve the alarm); in a shell block $vars are
	// on most lines, and a page of error red read as a page of mistakes.
	Var
)

type Span

type Span struct {
	Start, End int
	Kind       Kind
}

Span is one classified run, as byte offsets into the source. Spans are sorted, never overlap, and start and end on rune boundaries.

func Lex

func Lex(tag, src string) []Span

Lex classifies src as the language its fence tag names. It returns nil for a language it does not highlight, which callers draw as plain text.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL