فهرست منبع

Merge pull request #160 from itzhoujun/feature/word_separator

Feature/word separator
xuty 3 سال پیش
والد
کامیت
cd6b6751a6
5فایلهای تغییر یافته به همراه80 افزوده شده و 6 حذف شده
  1. 7 0
      CHANGELOG.md
  2. 9 3
      lib/src/core/buffer/buffer.dart
  3. 18 3
      lib/src/terminal.dart
  4. 18 0
      test/src/core/buffer/buffer_test.dart
  5. 28 0
      test/src/terminal_test.dart

+ 7 - 0
CHANGELOG.md

@@ -1,3 +1,6 @@
+# [upcoming]
+* Support customizing word separators for selection [#160]. Thanks [@itzhoujun].
+
 ## [3.4.1] - 2023-01-27
 * Fix Flutter 3.7 incompatibilities [#151], thanks [@jpnurmi].
 
@@ -204,6 +207,8 @@
 [@jpnurmi]: https://github.com/jpnurmi
 [@LucasAschenbach]: https://github.com/LucasAschenbach
 [@tauu]: https://github.com/tauu
+[@itzhoujun]: https://github.com/itzhoujun
+
 
 [#40]: https://github.com/TerminalStudio/xterm.dart/pull/40
 [#43]: https://github.com/TerminalStudio/xterm.dart/pull/43
@@ -247,3 +252,5 @@
 
 [#151]: https://github.com/TerminalStudio/xterm.dart/pull/151
 
+[#160]: https://github.com/TerminalStudio/xterm.dart/pull/160
+

+ 9 - 3
lib/src/core/buffer/buffer.dart

@@ -18,10 +18,15 @@ class Buffer {
 
   final bool isAltBuffer;
 
+  /// Characters that break selection when calling [getWordBoundary]. If null,
+  /// defaults to [defaultWordSeparators].
+  final Set<int>? wordSeparators;
+
   Buffer(
     this.terminal, {
     required this.maxLines,
     required this.isAltBuffer,
+    this.wordSeparators,
   }) {
     for (int i = 0; i < terminal.viewHeight; i++) {
       lines.push(_newEmptyLine());
@@ -464,7 +469,7 @@ class Buffer {
     return line;
   }
 
-  static final _kWordSeparators = <int>{
+  static final defaultWordSeparators = <int>{
     0,
     r' '.codeUnitAt(0),
     r'.'.codeUnitAt(0),
@@ -479,6 +484,7 @@ class Buffer {
   };
 
   BufferRangeLine? getWordBoundary(CellOffset position) {
+    var separators = wordSeparators ?? defaultWordSeparators;
     if (position.y >= lines.length) {
       return null;
     }
@@ -492,7 +498,7 @@ class Buffer {
         break;
       }
       final char = line.getCodePoint(start - 1);
-      if (_kWordSeparators.contains(char)) {
+      if (separators.contains(char)) {
         break;
       }
       start--;
@@ -503,7 +509,7 @@ class Buffer {
         break;
       }
       final char = line.getCodePoint(end);
-      if (_kWordSeparators.contains(char)) {
+      if (separators.contains(char)) {
         break;
       }
       end++;

+ 18 - 3
lib/src/terminal.dart

@@ -62,6 +62,10 @@ class Terminal with Observable implements TerminalState, EscapeHandler {
   /// Flag to toggle os specific behaviors.
   final TerminalTargetPlatform platform;
 
+  /// Characters that break selection when double clicking. If not set, the
+  /// [Buffer.defaultWordSeparators] will be used.
+  final Set<int>? wordSeparators;
+
   Terminal({
     this.maxLines = 1000,
     this.onBell,
@@ -73,6 +77,7 @@ class Terminal with Observable implements TerminalState, EscapeHandler {
     this.inputHandler = defaultInputHandler,
     this.mouseHandler = defaultMouseHandler,
     this.reflowEnabled = true,
+    this.wordSeparators,
   });
 
   late final _parser = EscapeParser(this);
@@ -81,9 +86,19 @@ class Terminal with Observable implements TerminalState, EscapeHandler {
 
   late var _buffer = _mainBuffer;
 
-  late final _mainBuffer = Buffer(this, maxLines: maxLines, isAltBuffer: false);
-
-  late final _altBuffer = Buffer(this, maxLines: maxLines, isAltBuffer: true);
+  late final _mainBuffer = Buffer(
+    this,
+    maxLines: maxLines,
+    isAltBuffer: false,
+    wordSeparators: wordSeparators,
+  );
+
+  late final _altBuffer = Buffer(
+    this,
+    maxLines: maxLines,
+    isAltBuffer: true,
+    wordSeparators: wordSeparators,
+  );
 
   final _tabStops = TabStops();
 

+ 18 - 0
test/src/core/buffer/buffer_test.dart

@@ -138,6 +138,24 @@ void main() {
     });
   });
 
+  group('Buffer.getWordBoundary supports custom word separators', () {
+    test('can set word separators', () {
+      final terminal = Terminal(wordSeparators: {'o'.codeUnitAt(0)});
+
+      terminal.write('Hello World');
+
+      expect(
+        terminal.mainBuffer.getWordBoundary(CellOffset(0, 0)),
+        BufferRangeLine(CellOffset(0, 0), CellOffset(4, 0)),
+      );
+
+      expect(
+        terminal.mainBuffer.getWordBoundary(CellOffset(5, 0)),
+        BufferRangeLine(CellOffset(5, 0), CellOffset(7, 0)),
+      );
+    });
+  });
+
   test('does not delete lines beyond the scroll region', () {
     final terminal = Terminal();
     terminal.resize(10, 10);

+ 28 - 0
test/src/terminal_test.dart

@@ -85,6 +85,34 @@ void main() {
       expect(terminal.buffer.lines[2].toString(), 'd');
     });
   });
+
+  group('Terminal.mouseInput', () {
+    test('applys to the main buffer', () {
+      final terminal = Terminal(
+        wordSeparators: {
+          'z'.codeUnitAt(0),
+        },
+      );
+
+      expect(
+        terminal.mainBuffer.wordSeparators,
+        contains('z'.codeUnitAt(0)),
+      );
+    });
+
+    test('applys to the alternate buffer', () {
+      final terminal = Terminal(
+        wordSeparators: {
+          'z'.codeUnitAt(0),
+        },
+      );
+
+      expect(
+        terminal.altBuffer.wordSeparators,
+        contains('z'.codeUnitAt(0)),
+      );
+    });
+  });
 }
 
 class _TestInputHandler implements TerminalInputHandler {