remember Syntax Highlighted Editor Value
Runs the debounce + syntax-highlight pipeline for a live code editor and returns the display TextFieldValue ready to pass directly to BasicTextField (or any other text field that accepts TextFieldValue).
This is the lower-level counterpart to SyntaxHighlightedTextEditor: it owns the engine call, the debounce window, and the span-clipping logic, but does not render anything. Callers drive their own layout, which makes it easy to:
wrap an
OutlinedTextFieldor a third-party editor with syntax highlightingtest the highlight pipeline in isolation without a
Surface/BasicTextFieldin the tree
The returned TextFieldValue is recomputed each time a new highlight result arrives. Between updates the previous spans are transferred using a prefix/suffix analysis: spans on unchanged text before the edit are kept as-is, spans on unchanged text after the edit (lines below) are shifted by the length delta, and spans in the edited region are dropped. This means syntax colors on all lines above and below a mid-text edit remain correct during the debounce window, and only the characters being typed are temporarily unstyled.
Usage - standalone (with BasicTextField)
var editorValue by remember { mutableStateOf(TextFieldValue("fun hello() = println(\"Hello!\")")) }
HighlightThemeProvider(
lightHighlightTheme = HighlightTheme.tomorrow(),
darkHighlightTheme = HighlightTheme.tomorrowNight(),
) {
val displayValue = rememberSyntaxHighlightedEditorValue(
value = editorValue,
language = "kotlin",
)
BasicTextField(
value = displayValue,
onValueChange = { editorValue = it },
)
}Usage - with SyntaxHighlightedTextEditor (preferred for most cases)
For the common case of a themed, bordered editor use SyntaxHighlightedTextEditor directly. It calls this function internally and adds the Surface + padding + test-tag wrapper.
Return
The TextFieldValue with syntax-highlight spans applied, preserving the original cursor position and selection. Falls back to plain text while a highlight result is in flight, on error, or when the language/theme has just changed. Because this function is a non-restartable composable (returns a non-Unit type), all internal State reads (including the highlight snapshot) automatically subscribe the caller's recompose scope - callers should use it like any other composable helper (val x = rememberXxx()).
Parameters
The current TextFieldValue, including text, cursor position, and selection.
Highlight.js language identifier (e.g. "kotlin", "python", "sql").
The highlight theme to apply. Defaults to LocalHighlightTheme.
Milliseconds to wait after the last keystroke before triggering a new highlight call. Defaults to 150 ms. If debounceMs changes, the new value is used on the next keystroke. The currently running debounce window is unaffected (the original delay completes with its captured-at-suspension value).
Optional callback invoked each time a highlight cycle completes successfully. Receives the resulting AnnotatedString with syntax spans applied. Useful for testing (wait until the first result arrives) and for observing the highlight output without owning the editor's text state.
Optional callback invoked with the HighlightException when a highlight cycle fails. The editor falls back to plain text on failure regardless of whether this callback is set - it is purely observational. Use it to log failures, show a snackbar, or record analytics. Possible failure types: HighlightException.Timeout, HighlightException.JsExecutionFailed, HighlightException.WebViewInitFailed, HighlightException.HtmlParseFailed.