search method

List<TerminalSearchMatch> search(
  1. String query, {
  2. bool caseSensitive = false,
  3. bool wholeWord = false,
  4. bool useRegex = false,
  5. int maxResults = _defaultSearchResultLimit,
})

Finds query in the active buffer.

Soft-wrapped physical rows are searched as one logical line. Search results are capped by maxResults so repeated output cannot cause unbounded result allocation.

Implementation

List<TerminalSearchMatch> search(
  String query, {
  bool caseSensitive = false,
  bool wholeWord = false,
  bool useRegex = false,
  int maxResults = _defaultSearchResultLimit,
}) {
  if (query.isEmpty || maxResults <= 0) {
    return const [];
  }

  final pattern = switch (useRegex) {
    true => query,
    false => RegExp.escape(query),
  };
  final expression = RegExp(
    pattern,
    caseSensitive: caseSensitive,
    unicode: true,
  );
  final results = <TerminalSearchMatch>[];
  final buffer = this.buffer;
  final textBuffer = StringBuffer();
  final searchCells = _SearchCells();
  var lineIndex = 0;

  while (lineIndex < buffer.lines.length && results.length < maxResults) {
    final logicalLine = _buildLogicalLine(
      buffer,
      lineIndex,
      textBuffer,
      searchCells,
    );
    lineIndex = logicalLine.nextLineIndex;
    if (logicalLine.text.isEmpty || logicalLine.cells.isEmpty) continue;

    for (final match in expression.allMatches(logicalLine.text)) {
      if (match.start == match.end) continue;
      if (wholeWord && !_isWholeWord(logicalLine.text, match)) continue;

      final startCell = logicalLine.cells.cellAt(buffer, match.start);
      final endCell = logicalLine.cells.cellAt(buffer, match.end - 1);
      if (startCell == null || endCell == null) continue;

      results.add(
        TerminalSearchMatch(
          range: BufferRangeLine(
            CellOffset(startCell.x, startCell.y),
            CellOffset(endCell.x + endCell.width, endCell.y),
          ),
          text: logicalLine.text.substring(match.start, match.end),
        ),
      );
      if (results.length >= maxResults) break;
    }
  }

  return results;
}