Plusfinity logo

val_highlight_flutter

Syntax-highlighted code for Flutter.

Show code with CodeView and edit it with CodeField.
55 languages, eight themes, and large files that stay smooth.

Pub Version Pub Points BSD-3-Clause license

βš™οΈ Engine Β· πŸ’» GitHub Β· πŸ“¦ pub.flutter-io.cn


✨ Why val_highlight_flutter?

  • Two widgets, one line each β€” CodeView(source, language: dartLanguage) to show code, CodeField(controller: …) to edit it.
  • Smooth on large files β€” a 20,000-line file scrolls with no dropped frames, and typing in a 2,000-line editor takes about 14 ms per keystroke.
  • Real editing β€” Tab and Shift+Tab indent and outdent, Enter keeps the indentation, and every edit re-highlights only what it can affect.
  • Native rendering β€” plain Flutter text, no WebView and no platform code. Works on Android, iOS, macOS, Windows, Linux and the web.
  • Follows your app β€” light and dark themes switch with the app, and CodeTheme sets defaults once for every code block.
  • Interactive β€” tap handlers and custom spans per token, for jump-to-definition, links and tooltips.

πŸ› οΈ Quick start

flutter pub add val_highlight_flutter
import 'package:val_highlight_flutter/val_highlight_flutter.dart';
import 'package:val_highlight/languages/dart.dart';

CodeView(source, language: dartLanguage)

This package re-exports the core API of val_highlight. Languages and themes are separate imports under package:val_highlight/languages/ and package:val_highlight/themes/, so an app ships only what it uses.

πŸ“„ CodeView

CodeView(
  source,
  language: kotlinLanguage,
  lineNumbers: true,
  highlightedLines: {3, 4},
  wrap: true,
  header: const Text('MainActivity.kt'),
  onTokenTap: (token) => print('${token.scope}: ${token.text}'),
)
  • Line numbers β€” lineNumbers, firstLineNumber; a custom gutterBuilder.
  • Highlighted lines β€” highlightedLines, highlightColor.
  • Wrapping β€” wrap: true, or scroll long lines horizontally.
  • Selection and copying β€” on by default (selectable); line numbers are never copied.
  • Custom rendering β€” lineBuilder wraps each row, header adds a title bar or copy button, spanBuilder replaces any token's span.
  • Tappable tokens β€” onTokenTap receives each token's text, offsets, line and scopes.
  • Unknown languages β€” with no language, pass detectLanguages: allLanguages to detect it; otherwise the generic grammar highlights what most languages share (fallbackLanguage changes this).
  • Large files β€” code with more than virtualizeAbove lines (1,000 by default), placed where its height is bounded, renders lazily. Inputs above 50,000 characters are highlighted in a background isolate while plain text shows.

⌨️ CodeField

final controller = HighlightTextController(language: dartLanguage);

CodeField(controller: controller, expands: true)

CodeField is a TextField for code:

  • monospace, no autocorrect or smart quotes;
  • Tab and Shift+Tab indent and outdent (indent sets the unit);
  • Enter keeps the current indentation, adding a level after {, [, ( or :;
  • each edit re-scans only the lines it can affect.

Flutter lays out a text field's whole text on every change, and styled runs make that slower. So for documents over 300 lines, CodeField colours only the visible lines plus a margin, and the coloured window follows scrolling.

HighlightTextController also works in a plain TextField for short documents. For long ones, use CodeField, or set controller.window yourself.

🎨 Themes

The theme follows the app's brightness: lightTheme or darkTheme by default. Choose any of the eight built-in themes, a VS Code theme, or your own:

CodeView(source, language: dartLanguage, theme: midnightTheme)

Set app-wide defaults once:

MaterialApp(
  theme: ThemeData(
    extensions: [
      CodeTheme(
        light: sepiaTheme,
        dark: dimTheme,
        textStyle: const TextStyle(fontFamily: 'JetBrains Mono'),
        lineNumbers: true,
      ),
    ],
  ),
)

βš™οΈ CodeHighlighter

CodeHighlighter.shared highlights for every widget, with a result cache. Create your own to change the isolate threshold or cache size, or to resolve languages named inside code, such as Markdown fences:

final highlighter = CodeHighlighter(registry: allLanguagesRegistry());

CodeView(markdown, language: markdownLanguage, highlighter: highlighter)

Call CodeHighlighter.shared.preload([dartLanguage, …]) at startup to compile languages during idle frames, so the first code shown in each has no compile delay (1–3 ms per language otherwise).

🧱 Lower level

  • CodeStyles converts a ValTheme into cached TextStyles.
  • lineSpans, documentSpans and exactSpans turn a HighlightResult into TextSpans for your own widgets.

πŸ“Έ Screenshots

Dart in CodeView with line numbers and highlighted lines
CodeView
Line numbers, highlighted lines, selection.
Python being edited in CodeField
CodeField
An editor that highlights as you type.
Markdown with bash, Python and JSON code fences
Languages inside languages
Markdown fences, HTML with CSS and JavaScript.

⚑ Performance

Frame timings on a MacBook, in profile mode:

Scenario Build time avg / p90 Missed frames
Scroll a 20,000-line CodeView 1.3 / 2.6 ms 0 of 926
Same, wrapped 1.3 / 2.6 ms 0 of 927
Scroll 800 lines as one text block 0.3 / 0.4 ms 0 of 915
Type in a 2,000-line CodeField 14.3 / 15.7 ms 4 of 120
Type in a plain TextField, same text, no highlighting 17.4 / 17.6 ms 120 of 120
Scroll a 2,000-line CodeField 3.7 / 7.1 ms 15 of 926

The missed frames while scrolling a CodeField happen when its coloured window moves, which makes Flutter lay out the whole field again.

πŸ§ͺ Example

The example app has a gallery of every language and theme, a live editor, and a large file rendered lazily.

Built by Val

val_highlight_flutter is part of Val, the live visual layer for AI agents.

πŸ’¬ Community

Issues and pull requests are welcome on GitHub; see the contributing guide. If the package helps your project, consider giving it a like on pub.flutter-io.cn or a star on GitHub.

πŸ“„ License

BSD 3-Clause β€” see LICENSE.

Libraries

val_highlight_flutter
Flutter widgets for val_highlight.