From 7c468ebd7d0402be0d282f26baa011317aa1df21 Mon Sep 17 00:00:00 2001 From: Cyril Dutrieux Date: Fri, 31 Jul 2020 10:11:37 +0200 Subject: [PATCH 1/8] Make visible a editingcontroller & textspan getter --- flutter_highlight/lib/flutter_highlight.dart | 130 ++++++++++++++----- 1 file changed, 97 insertions(+), 33 deletions(-) diff --git a/flutter_highlight/lib/flutter_highlight.dart b/flutter_highlight/lib/flutter_highlight.dart index 43b7fa1..518dec3 100644 --- a/flutter_highlight/lib/flutter_highlight.dart +++ b/flutter_highlight/lib/flutter_highlight.dart @@ -36,38 +36,6 @@ class HighlightView extends StatelessWidget { int tabSize = 8, // TODO: https://github.com/flutter/flutter/issues/50087 }) : source = input.replaceAll('\t', ' ' * tabSize); - List _convert(List nodes) { - List spans = []; - var currentSpans = spans; - List> stack = []; - - _traverse(Node node) { - if (node.value != null) { - currentSpans.add(node.className == null - ? TextSpan(text: node.value) - : TextSpan(text: node.value, style: theme[node.className])); - } else if (node.children != null) { - List tmp = []; - currentSpans.add(TextSpan(children: tmp, style: theme[node.className])); - stack.add(currentSpans); - currentSpans = tmp; - - node.children.forEach((n) { - _traverse(n); - if (n == node.children.last) { - currentSpans = stack.isEmpty ? spans : stack.removeLast(); - } - }); - } - } - - for (var node in nodes) { - _traverse(node); - } - - return spans; - } - static const _rootKey = 'root'; static const _defaultFontColor = Color(0xff000000); static const _defaultBackgroundColor = Color(0xffffffff); @@ -93,9 +61,105 @@ class HighlightView extends StatelessWidget { child: RichText( text: TextSpan( style: _textStyle, - children: _convert(highlight.parse(source, language: language).nodes), + children: getHighlightTextSpan(source, language, theme), ), ), ); } } + +List getHighlightTextSpan( source, language, theme) { + return _convert(highlight.parse(source, language: language).nodes, theme); +} + +class HighlightEditingController extends TextEditingController { + String language; + Map theme; + + HighlightEditingController(this.language, this.theme); + + @override + TextSpan buildTextSpan({TextStyle style, bool withComposing}) { + final result = highlight.parse(value.text, language: language); + final spans = + TextSpan(style: style, children: _convert(result.nodes, theme)); + if (value.composing.isValid && withComposing) { + underlineComposing(spans); + } + return spans; + } + + underlineComposing(TextSpan nodes) { + var pos = 0; + final TextStyle composingStyle = + TextStyle(decoration: TextDecoration.underline); + + TextSpan _traverse(TextSpan node) { + if (node.text != null && pos <= value.composing.start && + value.composing.end <= pos + node.text.length) { + var relativeComposing = TextRange( + start: value.composing.start - pos, + end: value.composing.end - pos, + ); + return TextSpan( + children: [ + TextSpan(text: relativeComposing.textBefore(node.text)), + TextSpan( + style: composingStyle, + text: relativeComposing.textInside(node.text), + ), + TextSpan(text: relativeComposing.textAfter(node.text)), + ], + ); + } + + pos += node.text?.length ?? 0; + if (node.children != null) { + for (var i = 0; + i < node.children.length && pos <= value.composing.start; + i++) { + var update = _traverse(node.children[i]); + if (update != null) { + node.children[i] = update; + return null; + } + } + } + return null; + } + + _traverse(nodes); + } +} + +List _convert(List nodes, theme) { + List spans = []; + var currentSpans = spans; + List> stack = []; + + _traverse(Node node) { + if (node.value != null) { + currentSpans.add(node.className == null + ? TextSpan(text: node.value) + : TextSpan(text: node.value, style: theme[node.className])); + } else if (node.children != null) { + List tmp = []; + currentSpans.add(TextSpan(children: tmp, style: theme[node.className])); + stack.add(currentSpans); + currentSpans = tmp; + + node.children.forEach((n) { + _traverse(n); + if (n == node.children.last) { + currentSpans = stack.isEmpty ? spans : stack.removeLast(); + } + }); + } + } + + for (var node in nodes) { + _traverse(node); + } + + return spans; +} From c80e92f13e1ec48618f2cd42e815b35216aca66b Mon Sep 17 00:00:00 2001 From: Tushar Sadhwani <18bit160@ietdavv.edu.in> Date: Sun, 2 Aug 2020 02:23:00 -0700 Subject: [PATCH 2/8] Add controller input, and editable boolean --- flutter_highlight/lib/flutter_highlight.dart | 88 ++++++++++++++------ 1 file changed, 64 insertions(+), 24 deletions(-) diff --git a/flutter_highlight/lib/flutter_highlight.dart b/flutter_highlight/lib/flutter_highlight.dart index 518dec3..b4a5638 100644 --- a/flutter_highlight/lib/flutter_highlight.dart +++ b/flutter_highlight/lib/flutter_highlight.dart @@ -3,9 +3,12 @@ import 'package:flutter/widgets.dart'; import 'package:highlight/highlight.dart' show highlight, Node; /// Highlight Flutter Widget -class HighlightView extends StatelessWidget { +class HighlightView extends StatefulWidget { /// The original code to be highlighted - final String source; + String source; + + /// The controller for the highlighted text + HighlightEditingController controller; /// Highlight language /// @@ -19,6 +22,12 @@ class HighlightView extends StatelessWidget { /// [All available themes](https://github.com/pd4d10/highlight/blob/master/flutter_highlight/lib/themes) final Map theme; + /// Editable + /// + /// If set to true, this will render a TextField instead. + /// Defaults to false. + final bool editable; + /// Padding final EdgeInsetsGeometry padding; @@ -27,14 +36,24 @@ class HighlightView extends StatelessWidget { /// Specify text styles such as font family and font size final TextStyle textStyle; - HighlightView( - String input, { + HighlightView({ + String text, + this.controller, this.language, this.theme = const {}, + this.editable = false, this.padding, this.textStyle, int tabSize = 8, // TODO: https://github.com/flutter/flutter/issues/50087 - }) : source = input.replaceAll('\t', ' ' * tabSize); + }) { + if (controller == null) { + source = text.replaceAll('\t', ' ' * tabSize); + controller = HighlightEditingController(language, theme); + controller.text = source; + } else { + source = controller.text.replaceAll('\t', ' ' * tabSize); + } + } static const _rootKey = 'root'; static const _defaultFontColor = Color(0xff000000); @@ -45,30 +64,48 @@ class HighlightView extends StatelessWidget { // So we just use monospace here for now static const _defaultFontFamily = 'monospace'; + @override + _HighlightViewState createState() => _HighlightViewState(); +} + +class _HighlightViewState extends State { @override Widget build(BuildContext context) { var _textStyle = TextStyle( - fontFamily: _defaultFontFamily, - color: theme[_rootKey]?.color ?? _defaultFontColor, + fontFamily: HighlightView._defaultFontFamily, + color: widget.theme[HighlightView._rootKey]?.color ?? + HighlightView._defaultFontColor, ); - if (textStyle != null) { - _textStyle = _textStyle.merge(textStyle); + if (widget.textStyle != null) { + _textStyle = _textStyle.merge(widget.textStyle); } return Container( - color: theme[_rootKey]?.backgroundColor ?? _defaultBackgroundColor, - padding: padding, - child: RichText( - text: TextSpan( - style: _textStyle, - children: getHighlightTextSpan(source, language, theme), - ), - ), + color: widget.theme[HighlightView._rootKey]?.backgroundColor ?? + HighlightView._defaultBackgroundColor, + padding: widget.padding, + child: widget.editable + ? TextField( + controller: widget.controller, + decoration: InputDecoration(border: InputBorder.none), + maxLines: null, + style: widget.theme[HighlightView._rootKey], + ) + : RichText( + text: TextSpan( + style: _textStyle, + children: getHighlightTextSpan( + widget.source, + widget.language, + widget.theme, + ), + ), + ), ); } } -List getHighlightTextSpan( source, language, theme) { +List getHighlightTextSpan(source, language, theme) { return _convert(highlight.parse(source, language: language).nodes, theme); } @@ -81,8 +118,10 @@ class HighlightEditingController extends TextEditingController { @override TextSpan buildTextSpan({TextStyle style, bool withComposing}) { final result = highlight.parse(value.text, language: language); - final spans = - TextSpan(style: style, children: _convert(result.nodes, theme)); + final spans = TextSpan( + style: style, + children: _convert(result.nodes, theme), + ); if (value.composing.isValid && withComposing) { underlineComposing(spans); } @@ -92,10 +131,11 @@ class HighlightEditingController extends TextEditingController { underlineComposing(TextSpan nodes) { var pos = 0; final TextStyle composingStyle = - TextStyle(decoration: TextDecoration.underline); + TextStyle(decoration: TextDecoration.underline); TextSpan _traverse(TextSpan node) { - if (node.text != null && pos <= value.composing.start && + if (node.text != null && + pos <= value.composing.start && value.composing.end <= pos + node.text.length) { var relativeComposing = TextRange( start: value.composing.start - pos, @@ -116,8 +156,8 @@ class HighlightEditingController extends TextEditingController { pos += node.text?.length ?? 0; if (node.children != null) { for (var i = 0; - i < node.children.length && pos <= value.composing.start; - i++) { + i < node.children.length && pos <= value.composing.start; + i++) { var update = _traverse(node.children[i]); if (update != null) { node.children[i] = update; From d90a68fc2ea1bf04733e87d09be2347860a18647 Mon Sep 17 00:00:00 2001 From: Tushar Sadhwani <18bit160@ietdavv.edu.in> Date: Sun, 2 Aug 2020 02:23:40 -0700 Subject: [PATCH 3/8] Make example editable --- flutter_highlight/example/android/gradle.properties | 1 + flutter_highlight/example/lib/main.dart | 13 ++++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/flutter_highlight/example/android/gradle.properties b/flutter_highlight/example/android/gradle.properties index 2bd6f4f..1441b1d 100644 --- a/flutter_highlight/example/android/gradle.properties +++ b/flutter_highlight/example/android/gradle.properties @@ -1,2 +1,3 @@ org.gradle.jvmargs=-Xmx1536M +android.enableR8=true diff --git a/flutter_highlight/example/lib/main.dart b/flutter_highlight/example/lib/main.dart index 74ada48..989bc5b 100644 --- a/flutter_highlight/example/lib/main.dart +++ b/flutter_highlight/example/lib/main.dart @@ -92,17 +92,20 @@ class _MyHomePageState extends State { ], ), body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, + child: ListView( + primary: false, + shrinkWrap: true, children: [ HighlightView( - exampleMap[language], + text: exampleMap[language], + editable: true, language: language, theme: themeMap[theme], padding: EdgeInsets.all(12), textStyle: TextStyle( - fontFamily: - 'SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace'), + fontFamily: + 'SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace', + ), ) ], ), From f0ad89025df75f545f520b75a70af8a460ae917a Mon Sep 17 00:00:00 2001 From: Tushar Sadhwani <18bit160@ietdavv.edu.in> Date: Sun, 2 Aug 2020 09:31:20 -0700 Subject: [PATCH 4/8] Fix immutable warning --- flutter_highlight/lib/flutter_highlight.dart | 35 ++++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/flutter_highlight/lib/flutter_highlight.dart b/flutter_highlight/lib/flutter_highlight.dart index b4a5638..f75004a 100644 --- a/flutter_highlight/lib/flutter_highlight.dart +++ b/flutter_highlight/lib/flutter_highlight.dart @@ -5,10 +5,10 @@ import 'package:highlight/highlight.dart' show highlight, Node; /// Highlight Flutter Widget class HighlightView extends StatefulWidget { /// The original code to be highlighted - String source; + final String text; /// The controller for the highlighted text - HighlightEditingController controller; + final HighlightEditingController controller; /// Highlight language /// @@ -37,7 +37,7 @@ class HighlightView extends StatefulWidget { final TextStyle textStyle; HighlightView({ - String text, + this.text, this.controller, this.language, this.theme = const {}, @@ -45,15 +45,7 @@ class HighlightView extends StatefulWidget { this.padding, this.textStyle, int tabSize = 8, // TODO: https://github.com/flutter/flutter/issues/50087 - }) { - if (controller == null) { - source = text.replaceAll('\t', ' ' * tabSize); - controller = HighlightEditingController(language, theme); - controller.text = source; - } else { - source = controller.text.replaceAll('\t', ' ' * tabSize); - } - } + }); static const _rootKey = 'root'; static const _defaultFontColor = Color(0xff000000); @@ -69,6 +61,21 @@ class HighlightView extends StatefulWidget { } class _HighlightViewState extends State { + String source; + HighlightEditingController controller; + + @override + void initState() { + super.initState(); + if (widget.controller == null) { + controller = HighlightEditingController(widget.language, widget.theme); + controller.text = widget.text; + } else { + controller = widget.controller; + source = controller.text; + } + } + @override Widget build(BuildContext context) { var _textStyle = TextStyle( @@ -86,7 +93,7 @@ class _HighlightViewState extends State { padding: widget.padding, child: widget.editable ? TextField( - controller: widget.controller, + controller: controller, decoration: InputDecoration(border: InputBorder.none), maxLines: null, style: widget.theme[HighlightView._rootKey], @@ -95,7 +102,7 @@ class _HighlightViewState extends State { text: TextSpan( style: _textStyle, children: getHighlightTextSpan( - widget.source, + source, widget.language, widget.theme, ), From db57e4ca1f7bb70beec4e1cc7dc31380c746eeed Mon Sep 17 00:00:00 2001 From: Tushar Sadhwani <18bit160@ietdavv.edu.in> Date: Sun, 2 Aug 2020 10:13:52 -0700 Subject: [PATCH 5/8] bugfix --- flutter_highlight/lib/flutter_highlight.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter_highlight/lib/flutter_highlight.dart b/flutter_highlight/lib/flutter_highlight.dart index f75004a..184a804 100644 --- a/flutter_highlight/lib/flutter_highlight.dart +++ b/flutter_highlight/lib/flutter_highlight.dart @@ -72,8 +72,8 @@ class _HighlightViewState extends State { controller.text = widget.text; } else { controller = widget.controller; - source = controller.text; } + source = controller.text; } @override From 4dafa63a42be96895dbcb62f53e76928b0407220 Mon Sep 17 00:00:00 2001 From: Tushar Sadhwani Date: Fri, 1 Jan 2021 17:40:49 +0530 Subject: [PATCH 6/8] Minor fix --- flutter_highlight/example/pubspec.yaml | 2 ++ flutter_highlight/lib/flutter_highlight.dart | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/flutter_highlight/example/pubspec.yaml b/flutter_highlight/example/pubspec.yaml index 417fdba..7f96469 100644 --- a/flutter_highlight/example/pubspec.yaml +++ b/flutter_highlight/example/pubspec.yaml @@ -1,6 +1,8 @@ name: flutter_highlight_gallery description: A new Flutter project. +publish_to: none + # The following defines the version and build number for your application. # A version number is three numbers separated by dots, like 1.2.43 # followed by an optional build number separated by a +. diff --git a/flutter_highlight/lib/flutter_highlight.dart b/flutter_highlight/lib/flutter_highlight.dart index 184a804..19c0b13 100644 --- a/flutter_highlight/lib/flutter_highlight.dart +++ b/flutter_highlight/lib/flutter_highlight.dart @@ -45,7 +45,8 @@ class HighlightView extends StatefulWidget { this.padding, this.textStyle, int tabSize = 8, // TODO: https://github.com/flutter/flutter/issues/50087 - }); + }) : assert(text != null || controller != null, + 'One of text or controller properties must be provided'); static const _rootKey = 'root'; static const _defaultFontColor = Color(0xff000000); From 7df6e1ec935c39bbb3489e12e3c179aba5d969da Mon Sep 17 00:00:00 2001 From: Tushar Sadhwani Date: Fri, 1 Jan 2021 17:54:28 +0530 Subject: [PATCH 7/8] Change highlight path --- flutter_highlight/pubspec.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/flutter_highlight/pubspec.yaml b/flutter_highlight/pubspec.yaml index ea30628..151a685 100644 --- a/flutter_highlight/pubspec.yaml +++ b/flutter_highlight/pubspec.yaml @@ -4,13 +4,16 @@ version: 0.6.0+1 author: Rongjian Zhang homepage: https://github.com/git-touch/highlight +publish_to: none + environment: sdk: ">=2.3.0 <3.0.0" dependencies: flutter: sdk: flutter - highlight: ^0.6.0 + highlight: + path: ../highlight dev_dependencies: flutter_test: From 0ed985962bdaf5ef51faa4df3edb15bf3d955d4f Mon Sep 17 00:00:00 2001 From: Tushar Sadhwani Date: Tue, 9 Feb 2021 01:01:51 +0530 Subject: [PATCH 8/8] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b7906c6..218dd13 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +> NOTE: this fork has been archived in favour of hosting my own [flutter_highlight](https://github.com/tusharsadhwani/flutter_highlight) repo for ease of use. + # highlight Syntax highlighting for Dart and Flutter, which supports lots of languages and themes.