Repository: akvelon/flutter-code-editor
Pull request #38 (2022-07-28 11:27:56)

Language-specific comments when parsing EOL comment tokens
#34 


Patch:
diff --git a/lib/src/code/code.dart b/lib/src/code/code.dart
index c18ad5e..75f22d6 100644
--- a/lib/src/code/code.dart
+++ b/lib/src/code/code.dart
@@ -1,18 +1,36 @@
 import 'package:collection/collection.dart';
 import 'package:flutter/material.dart';
+import 'package:highlight/highlight.dart';
+import 'package:highlight/languages/dart.dart';
+import 'package:highlight/languages/go.dart';
+import 'package:highlight/languages/java.dart';
+import 'package:highlight/languages/python.dart';
+import 'package:highlight/languages/scala.dart';
 
 import 'code_line.dart';
 import 'text_range.dart';
 import 'tokens.dart';
 
+const _slashes = '//';
+const _hash = '#';
+
+final _singleLineLanguageComments = <Mode, List<String>>{
+  java: [_slashes],
+  dart: [_slashes],
+  go: [_slashes],
+  scala: [_slashes],
+  python: [_hash],
+};
+
 class Code {
   final String text;
   final List<CodeLine> lines;
 
   factory Code({
     required String text,
-    required List<String> singleLineComments,
+    Mode? language,
   }) {
+    final singleLineComments = _singleLineLanguageComments[language] ?? [];
     final lines = _textToCodeLines(text, singleLineComments);
     return Code._(text: text, lines: lines);
   }
diff --git a/lib/src/code_field/code_controller.dart b/lib/src/code_field/code_controller.dart
index fbc9863..caf1e47 100644
--- a/lib/src/code_field/code_controller.dart
+++ b/lib/src/code_field/code_controller.dart
@@ -20,9 +20,6 @@ import 'editor_params.dart';
 
 const _middleDot = '·';
 
-// TODO(alexeyinkin): Derive comments from language https://github.com/akvelon/flutter-code-editor/issues/34
-const _singleLineComments = ['//', '#'];
-
 class CodeController extends TextEditingController {
   Mode? _language;
 
@@ -114,7 +111,7 @@ class CodeController extends TextEditingController {
       : _theme = theme,
         _lastCode = Code(
           text: text ?? '',
-          singleLineComments: _singleLineComments,
+          language: language,
         ),
         super(text: text) {
     this.language = language;
@@ -319,7 +316,7 @@ class CodeController extends TextEditingController {
 
       _lastCode = Code(
         text: newValue.text,
-        singleLineComments: _singleLineComments,
+        language: language,
       );
     }
 


Test patch:
diff --git a/test/src/code/code_test.dart b/test/src/code/code_test.dart
index 336afb5..e2314a2 100644
--- a/test/src/code/code_test.dart
+++ b/test/src/code/code_test.dart
@@ -4,10 +4,11 @@ import 'package:code_text_field/src/code/code.dart';
 import 'package:code_text_field/src/code/code_line.dart';
 import 'package:collection/collection.dart';
 import 'package:flutter_test/flutter_test.dart';
+import 'package:highlight/languages/angelscript.dart';
+import 'package:highlight/languages/java.dart';
 
-const singleLineComments = ['//', '#'];
-
-const text = '''
+final _language = java;
+const _text = '''
 1 Lorem ipsum dolor sit amet,
 2 consectetur adipiscing elit,
 3 sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
@@ -30,7 +31,7 @@ void main() {
       const texts = ['', 'no-newline'];
 
       for (final text in texts) {
-        final code = Code(text: text, singleLineComments: singleLineComments);
+        final code = Code(text: text, language: _language);
 
         expect(
           const ListEquality().equals(
@@ -49,7 +50,7 @@ void main() {
     });
 
     test('parses lines', () {
-      final code = Code(text: text, singleLineComments: singleLineComments);
+      final code = Code(text: _text, language: _language);
 
       expect(
         const ListEquality().equals(
@@ -80,10 +81,10 @@ void main() {
     test('characterIndexToLineIndex', () {
       const tails = ['', '\n'];
       for (final tail in tails) {
-        final textWithTail = text + tail;
+        final textWithTail = _text + tail;
         final code = Code(
           text: textWithTail,
-          singleLineComments: singleLineComments,
+          language: _language,
         );
 
         final map = {
@@ -141,7 +142,7 @@ void main() {
     test('characterIndexToLineIndex on a single line', () {
       const texts = ['', 'no-newline'];
       for (final text in texts) {
-        final code = Code(text: text, singleLineComments: singleLineComments);
+        final code = Code(text: text, language: _language);
 
         for (int i = 0; i <= texts.length; i++) {
           expect(code.characterIndexToLineIndex(i), 0, reason: '"$text" at $i');
@@ -181,7 +182,7 @@ void main() {
       for (final data in dataSets) {
         final code = Code(
           text: data['text']! as String,
-          singleLineComments: singleLineComments,
+          language: _language,
         );
 
         final readonly = data['readonly']! as List<bool>;
@@ -190,5 +191,14 @@ void main() {
         }
       }
     });
+    
+    test(
+      'does not parse an unsupported language',
+      () {
+        String textWithReadonly = 'end of line // readonly';
+        final code = Code(text: textWithReadonly, language: angelscript);
+        expect(code.lines.first.isReadOnly, false);
+      },
+    );
   });
 }
diff --git a/test/src/code_field/code_controller_test.dart b/test/src/code_field/code_controller_test.dart
index 12a7af3..4e5157c 100644
--- a/test/src/code_field/code_controller_test.dart
+++ b/test/src/code_field/code_controller_test.dart
@@ -2,6 +2,7 @@ import 'package:code_text_field/code_text_field.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_test/flutter_test.dart';
+import 'package:highlight/languages/java.dart';
 
 const _editableBeginningEnd = '''
 abc
@@ -16,12 +17,17 @@ abc
 ro//readonly
 ''';
 
+final _language = java;
+
 void main() {
   group('CodeController Read-only', () {
     testWidgets(
       'Can edit at editable beginning of the document',
       (WidgetTester wt) async {
-        final controller = CodeController(text: _editableBeginningEnd);
+        final controller = CodeController(
+          text: _editableBeginningEnd,
+          language: _language,
+        );
         final focusNode = FocusNode();
 
         await wt.pumpWidget(_createApp(controller, focusNode));
@@ -74,7 +80,10 @@ void main() {
     testWidgets(
       'Can edit at editable end of the document',
       (WidgetTester wt) async {
-        final controller = CodeController(text: _editableBeginningEnd);
+        final controller = CodeController(
+          text: _editableBeginningEnd,
+          language: _language,
+        );
         final focusNode = FocusNode();
 
         await wt.pumpWidget(_createApp(controller, focusNode));
@@ -130,7 +139,10 @@ void main() {
     testWidgets(
       'Junction of editable and read-only',
       (WidgetTester wt) async {
-        final controller = CodeController(text: _editableBeginningEnd);
+        final controller = CodeController(
+          text: _editableBeginningEnd,
+          language: _language,
+        );
         final focusNode = FocusNode();
 
         await wt.pumpWidget(_createApp(controller, focusNode));
@@ -205,7 +217,10 @@ void main() {
     testWidgets(
       'Junction of and read-only and editable',
       (WidgetTester wt) async {
-        final controller = CodeController(text: _editableBeginningEnd);
+        final controller = CodeController(
+          text: _editableBeginningEnd,
+          language: _language,
+        );
         final focusNode = FocusNode();
 
         await wt.pumpWidget(_createApp(controller, focusNode));
@@ -263,7 +278,10 @@ void main() {
     testWidgets(
       'Read-only beginning of the document',
       (WidgetTester wt) async {
-        final controller = CodeController(text: _editableBetween);
+        final controller = CodeController(
+          text: _editableBetween,
+          language: _language,
+        );
         final focusNode = FocusNode();
 
         await wt.pumpWidget(_createApp(controller, focusNode));
@@ -294,8 +312,11 @@ void main() {
 
     testWidgets(
       'Read-only end of the document',
-        (WidgetTester wt) async {
-        final controller = CodeController(text: _editableBetween);
+      (WidgetTester wt) async {
+        final controller = CodeController(
+          text: _editableBetween,
+          language: _language,
+        );
         final focusNode = FocusNode();
 
         await wt.pumpWidget(_createApp(controller, focusNode));