diff --git a/lib/builtin/editor/src/editor_view.dart b/lib/builtin/editor/src/editor_view.dart index 4010b308..eed6f98a 100644 --- a/lib/builtin/editor/src/editor_view.dart +++ b/lib/builtin/editor/src/editor_view.dart @@ -27,7 +27,7 @@ class EditorView extends StatefulWidget { class _EditorViewState extends State { EditorController? _controller; - final TreeSitterService _syntax = TreeSitterService(); + final TreeSitterService _syntax = TreeSitterService.shared; late final SyntaxTextController _text; late final FocusNode _focus; String? _lastRemoteContent; @@ -57,7 +57,6 @@ class _EditorViewState extends State { _focus.dispose(); _controller?.removeListener(_onControllerChanged); _controller?.dispose(); - _syntax.dispose(); super.dispose(); } diff --git a/lib/kernel/src/syntax/tree_sitter_service.dart b/lib/kernel/src/syntax/tree_sitter_service.dart index bffb352a..5e8b7b99 100644 --- a/lib/kernel/src/syntax/tree_sitter_service.dart +++ b/lib/kernel/src/syntax/tree_sitter_service.dart @@ -42,6 +42,9 @@ class _LoadedGrammar { } class TreeSitterService { + static final TreeSitterService shared = TreeSitterService._(); + TreeSitterService._(); + final Map _grammars = {}; final Set _unavailable = {}; diff --git a/lib/widgets/src/clide_code_block.dart b/lib/widgets/src/clide_code_block.dart index 7ca8d08d..375692fc 100644 --- a/lib/widgets/src/clide_code_block.dart +++ b/lib/widgets/src/clide_code_block.dart @@ -16,7 +16,6 @@ class ClideCodeBlock extends StatefulWidget { } class _ClideCodeBlockState extends State { - final TreeSitterService _syntax = TreeSitterService(); List? _spans; @override @@ -33,12 +32,6 @@ class _ClideCodeBlockState extends State { } } - @override - void dispose() { - _syntax.dispose(); - super.dispose(); - } - Future _highlight() async { final lang = widget.language; if (lang == null || lang.isEmpty) { @@ -46,11 +39,11 @@ class _ClideCodeBlockState extends State { return; } final path = 'code.$lang'; - if (!await _syntax.hasGrammar(path)) { + if (!await TreeSitterService.shared.hasGrammar(path)) { setState(() => _spans = null); return; } - final result = await _syntax.highlight(path, widget.source); + final result = await TreeSitterService.shared.highlight(path, widget.source); if (mounted) setState(() => _spans = result.spans); } @@ -115,14 +108,15 @@ class _ClideCodeBlockState extends State { for (final span in sorted) { final sChar = span.start < byteToChar.length ? byteToChar[span.start] : source.length; final eChar = span.end < byteToChar.length ? byteToChar[span.end] : source.length; - if (sChar > lastChar) { - children.add(TextSpan(text: source.substring(lastChar, sChar))); + final clippedStart = sChar < lastChar ? lastChar : sChar; + if (clippedStart > lastChar) { + children.add(TextSpan(text: source.substring(lastChar, clippedStart))); } - if (eChar > sChar) { + if (eChar > clippedStart) { final color = TreeSitterService.colorForRole(span.role, tokens); - children.add(TextSpan(text: source.substring(sChar, eChar), style: base.copyWith(color: color))); + children.add(TextSpan(text: source.substring(clippedStart, eChar), style: base.copyWith(color: color))); } - lastChar = eChar; + if (eChar > lastChar) lastChar = eChar; } if (lastChar < source.length) { children.add(TextSpan(text: source.substring(lastChar)));