Sfoglia il codice sorgente

Adds SearchString to BufferLine

Moved line data to sub component that gets copied between Isolates to avoid copying the cached search string
devmil 4 anni fa
parent
commit
a349f1d4f6

+ 161 - 7
lib/buffer/line/line.dart

@@ -1,17 +1,169 @@
 import 'dart:math';
 
-import 'package:xterm/buffer/line/line_bytedata.dart';
-import 'package:xterm/buffer/line/line_list.dart';
+import 'package:meta/meta.dart';
+import 'package:xterm/buffer/line/line_bytedata_data.dart';
+import 'package:xterm/buffer/line/line_list_data.dart';
 import 'package:xterm/terminal/cursor.dart';
 import 'package:xterm/util/constants.dart';
 
-abstract class BufferLine {
-  factory BufferLine({int length = 64, bool isWrapped = false}) {
+@sealed
+class BufferLine {
+  BufferLine({int length = 64, bool isWrapped = false}) {
+    _data = BufferLineData(length: length, isWrapped: isWrapped);
+  }
+
+  BufferLine.withDataFrom(BufferLine other) {
+    _data = other.data;
+  }
+
+  late BufferLineData _data;
+
+  BufferLineData get data => _data;
+
+  bool get isWrapped => _data.isWrapped;
+
+  set isWrapped(bool value) => _data.isWrapped = value;
+
+  void ensure(int length) => _data.ensure(length);
+
+  void insert(int index) {
+    _invalidateCaches();
+    _data.insert(index);
+  }
+
+  void insertN(int index, int count) {
+    _invalidateCaches();
+    _data.insertN(index, count);
+  }
+
+  void removeN(int index, int count) {
+    _invalidateCaches();
+    _data.removeN(index, count);
+  }
+
+  void clear() {
+    _invalidateCaches();
+    _data.clear();
+  }
+
+  void erase(Cursor cursor, int start, int end, [bool resetIsWrapped = false]) {
+    _invalidateCaches();
+    _data.erase(cursor, start, end);
+  }
+
+  void cellClear(int index) {
+    _invalidateCaches();
+    _data.cellClear(index);
+  }
+
+  void cellInitialize(
+    int index, {
+    required int content,
+    required int width,
+    required Cursor cursor,
+  }) {
+    _invalidateCaches();
+    _data.cellInitialize(
+      index,
+      content: content,
+      width: width,
+      cursor: cursor,
+    );
+  }
+
+  bool cellHasContent(int index) => _data.cellHasContent(index);
+
+  int cellGetContent(int index) => _data.cellGetContent(index);
+
+  void cellSetContent(int index, int content) {
+    _invalidateCaches();
+    _data.cellSetContent(index, content);
+  }
+
+  int cellGetFgColor(int index) => _data.cellGetFgColor(index);
+
+  void cellSetFgColor(int index, int color) =>
+      _data.cellSetFgColor(index, color);
+
+  int cellGetBgColor(int index) => _data.cellGetBgColor(index);
+
+  void cellSetBgColor(int index, int color) =>
+      _data.cellSetBgColor(index, color);
+
+  int cellGetFlags(int index) => _data.cellGetFlags(index);
+
+  void cellSetFlags(int index, int flags) => _data.cellSetFlags(index, flags);
+
+  int cellGetWidth(int index) => _data.cellGetWidth(index);
+
+  void cellSetWidth(int index, int width) {
+    _invalidateCaches();
+    _data.cellSetWidth(index, width);
+  }
+
+  void cellClearFlags(int index) => _data.cellClearFlags(index);
+
+  bool cellHasFlag(int index, int flag) => _data.cellHasFlag(index, flag);
+
+  void cellSetFlag(int index, int flag) => _data.cellSetFlag(index, flag);
+
+  void cellErase(int index, Cursor cursor) {
+    _invalidateCaches();
+    _data.cellErase(index, cursor);
+  }
+
+  int getTrimmedLength([int? cols]) => _data.getTrimmedLength(cols);
+
+  void copyCellsFrom(
+      covariant BufferLine src, int srcCol, int dstCol, int len) {
+    _invalidateCaches();
+    _data.copyCellsFrom(src.data, srcCol, dstCol, len);
+  }
+
+  void removeRange(int start, int end) {
+    _invalidateCaches();
+    _data.removeRange(start, end);
+  }
+
+  void clearRange(int start, int end) {
+    _invalidateCaches();
+    _data.clearRange(start, end);
+  }
+
+  String toDebugString(int cols) => _data.toDebugString(cols);
+
+  void _invalidateCaches() {
+    _searchStringCache = null;
+  }
+
+  String? _searchStringCache;
+
+  String toSearchString(int cols) {
+    if (_searchStringCache != null) {
+      return _searchStringCache!;
+    }
+    final searchString = StringBuffer();
+    final length = getTrimmedLength();
+    for (int i = 0; i < max(cols, length); i++) {
+      var code = cellGetContent(i);
+      if (code == 0) {
+        searchString.writeAll(List<String>.filled(cellGetWidth(i), ' '));
+      } else {
+        searchString.writeCharCode(code);
+      }
+    }
+    _searchStringCache = searchString.toString();
+    return _searchStringCache!;
+  }
+}
+
+abstract class BufferLineData {
+  factory BufferLineData({int length = 64, bool isWrapped = false}) {
     if (kIsWeb) {
-      return ListBufferLine(length, isWrapped);
+      return ListBufferLineData(length, isWrapped);
     }
 
-    return ByteDataBufferLine(length, isWrapped);
+    return ByteDataBufferLineData(length, isWrapped);
   }
 
   bool get isWrapped;
@@ -71,7 +223,8 @@ abstract class BufferLine {
 
   int getTrimmedLength([int? cols]);
 
-  void copyCellsFrom(covariant BufferLine src, int srcCol, int dstCol, int len);
+  void copyCellsFrom(
+      covariant BufferLineData src, int srcCol, int dstCol, int len);
 
   // int cellGetHash(int index);
 
@@ -79,6 +232,7 @@ abstract class BufferLine {
 
   void clearRange(int start, int end);
 
+  @nonVirtual
   String toDebugString(int cols) {
     final result = StringBuffer();
     final length = getTrimmedLength();

+ 5 - 4
lib/buffer/line/line_bytedata.dart → lib/buffer/line/line_bytedata_data.dart

@@ -35,10 +35,10 @@ int _nextLength(int lengthRequirement) {
   return nextLength;
 }
 
-/// [ByteData] based [BufferLine], used in non-web platforms to minimize memory
+/// [ByteData] based [BufferLineData], used in non-web platforms to minimize memory
 /// footprint,
-class ByteDataBufferLine with BufferLine {
-  ByteDataBufferLine(int length, this.isWrapped) {
+class ByteDataBufferLineData with BufferLineData {
+  ByteDataBufferLineData(int length, this.isWrapped) {
     _maxCols = _nextLength(length);
     _cells = ByteData(_maxCols * _cellSize);
   }
@@ -244,7 +244,8 @@ class ByteDataBufferLine with BufferLine {
     return 0;
   }
 
-  void copyCellsFrom(ByteDataBufferLine src, int srcCol, int dstCol, int len) {
+  void copyCellsFrom(
+      ByteDataBufferLineData src, int srcCol, int dstCol, int len) {
     ensure(dstCol + len);
 
     final intsToCopy = len * _cellSize64Bit;

+ 4 - 4
lib/buffer/line/line_list.dart → lib/buffer/line/line_list_data.dart

@@ -33,9 +33,9 @@ int _nextLength(int lengthRequirement) {
   return nextLength;
 }
 
-/// [List] based [BufferLine], used in browser where ByteData is not avaliable.
-class ListBufferLine with BufferLine {
-  ListBufferLine(int length, this.isWrapped) {
+/// [List] based [BufferLineData], used in browser where ByteData is not avaliable.
+class ListBufferLineData with BufferLineData {
+  ListBufferLineData(int length, this.isWrapped) {
     _maxCols = _nextLength(length);
     _cells = List.filled(_maxCols * _cellSize, 0);
   }
@@ -226,7 +226,7 @@ class ListBufferLine with BufferLine {
     return 0;
   }
 
-  void copyCellsFrom(ListBufferLine src, int srcCol, int dstCol, int len) {
+  void copyCellsFrom(ListBufferLineData src, int srcCol, int dstCol, int len) {
     ensure(dstCol + len);
 
     final intsToCopy = len * _cellSize;

+ 4 - 1
lib/terminal/terminal_isolate.dart

@@ -141,7 +141,10 @@ void terminalMain(SendPort port) async {
             _terminal.cursorY,
             _terminal.showCursor,
             _terminal.theme.cursor,
-            _terminal.getVisibleLines(),
+            _terminal
+                .getVisibleLines()
+                .map((bl) => BufferLine.withDataFrom(bl))
+                .toList(growable: false),
             _terminal.composingString,
           );
           port.send([_IsolateEvent.newState, newState]);