Colour code with a scanner of our own instead of the library
dev.snipme:highlights 1.1.0 found comments before it knew the language and paired /* with */ by ordinal, so `//` in any URL commented out the rest of its line, every Rust `#[derive(...)]` greyed out as a comment, a `#` inside a Kotlin string swallowed the line, and `x '*/a/*'` in shell produced a span whose end preceded its start -- the one that crashed a card holding `-path '*/.git/*'`. None of that could be post-processed away, because comments won over strings before the language was known. Highlighter.kt is one left-to-right scanner: at each position it is in a line comment, a block comment, a string, or ordinary code, and every span is emitted by advancing an index, so spans cannot overlap, arrive out of order or run backwards. Languages.kt is a `Rules` row per language -- comment tokens, block comment and whether it nests, the string forms, what opens an attribute, and the keyword set -- so a new language is a table entry. The keyword lists came from the library's SyntaxTokens.kt (Apache-2.0, noted at the table) so nothing that is coloured today turns plain, and RON, TOML, fish and JSON are coloured for the first time. HighlighterTest.kt is a new JVM unit test source set -- 24 cases, the library's mistakes kept as regressions, plus a sweep asserting no span escapes the code for any language on unterminated and empty input. AGENTS.md's app line now runs :androidApp:testDebugUnitTest. Measured on the ai-app emulator, debug build, a ~200-line Kotlin fence sent into a sandbox session: before code highlighted: 1, 101.9ms total, 101.9ms mean, 101.9ms worst after code highlighted: 1, 15.0ms total, 15.0ms mean, 15.0ms worst and a second fence in the same run took 13.9ms, so that is the steady cost rather than class loading. stream-bench.sh after the change: code highlighted: 1, 12.1ms total, 12.1ms mean, 12.1ms worst markdown reparsed while streaming: 1329, 2130.7ms total, 1.6ms mean, 8.7ms worst record: one block: 131, 11.4ms total, 0.1ms mean, 0.4ms worst draw phase 1.21ms per frame, the transcript 0.23ms of it transcript-bench.sh after: draw phase 1.10ms per frame, the transcript 0.49ms (place 0.48), worst place 4.3ms -- unchanged within run-to-run noise, as expected, since the scan happens in `warm` and not while drawing. Looked at on the emulator: a URL inside a Kotlin string, a Rust attribute with a lifetime and a raw string, a shell line with globs and `$#`, a RON fence and a TOML fence all colour correctly; a Bash tool card still colours its command; a plain Python fence -- which this change had no reason to touch -- looks as it did; an unknown language stays plain; and a fence is plain while it streams and colours when it freezes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3d90e0947c
commit
a2b11d516f
13 files changed
+1136
-495
No files matched your search
@@ -6,8 +6,6 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import dev.snipme.highlights.model.SyntaxTheme
|
||||
|
||||
/**
|
||||
* Catppuccin Mocha, as published in `catppuccin/palette`.
|
||||
@@ -198,24 +196,24 @@ val rawSurface: Color
|
||||
@Composable get() = Mocha.Crust
|
||||
|
||||
/**
|
||||
* Catppuccin Mocha as a syntax theme, for the highlighter used on a tool call's input.
|
||||
* Catppuccin Mocha as the highlighter's palette; see [SyntaxPalette].
|
||||
*
|
||||
* Here with the rest of the palette rather than beside the code that highlights: a library's own
|
||||
* theme would otherwise be the one surface in the app whose colours came from somewhere else, and
|
||||
* the accents below are the same ones every other coloured thing already uses.
|
||||
* Here with the rest of the palette rather than beside the code that highlights: the colours a
|
||||
* fence is drawn in are the same accents every other coloured thing in the app already uses, and
|
||||
* splitting them out would make code the one surface whose palette came from somewhere else.
|
||||
*
|
||||
* Not a composable, because [highlight] runs off the drawing thread; these colours never vary with
|
||||
* the theme.
|
||||
*/
|
||||
fun catppuccinSyntax(): SyntaxTheme =
|
||||
SyntaxTheme(
|
||||
key = "catppuccin-mocha",
|
||||
code = Mocha.Text.toArgb(),
|
||||
keyword = Mocha.Mauve.toArgb(),
|
||||
string = Mocha.Green.toArgb(),
|
||||
literal = Mocha.Peach.toArgb(),
|
||||
comment = Mocha.Overlay0.toArgb(),
|
||||
metadata = Mocha.Yellow.toArgb(),
|
||||
multilineComment = Mocha.Overlay0.toArgb(),
|
||||
punctuation = Mocha.Subtext0.toArgb(),
|
||||
mark = Mocha.Sky.toArgb(),
|
||||
fun catppuccinSyntax(): SyntaxPalette =
|
||||
SyntaxPalette(
|
||||
keyword = Mocha.Mauve,
|
||||
string = Mocha.Green,
|
||||
literal = Mocha.Peach,
|
||||
comment = Mocha.Overlay0,
|
||||
metadata = Mocha.Yellow,
|
||||
punctuation = Mocha.Subtext0,
|
||||
mark = Mocha.Sky,
|
||||
)
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user