searchText method

  1. @override
Future<List<TextMatch>> searchText(
  1. String pattern, {
  2. String? glob,
  3. bool ignoreCase = false,
  4. int context = 0,
  5. int? limit,
})
override

Searches file contents for pattern (a regular expression). glob limits which files are searched; context lines of surrounding text are attached.

Implementation

@override
Future<List<TextMatch>> searchText(
  String pattern, {
  String? glob,
  bool ignoreCase = false,
  int context = 0,
  int? limit,
}) async {
  final re = RegExp(pattern, caseSensitive: !ignoreCase);
  final cap = limit ?? config.maxResults;
  final results = <TextMatch>[];
  await for (final ent in Directory(
    root,
  ).list(recursive: true, followLinks: false)) {
    if (ent is! File) continue;
    final rel = _relativeOf(ent.path);
    if (_ignored(rel)) continue;
    if (!matchesGlob(rel, glob)) continue;
    if (ent.lengthSync() > config.maxFileBytes) continue;
    List<String> lines;
    try {
      lines = ent.readAsStringSync().split('\n');
    } on FileSystemException {
      continue; // binary/unreadable
    }
    for (var i = 0; i < lines.length; i++) {
      final m = re.firstMatch(lines[i]);
      if (m == null) continue;
      results.add(
        TextMatch(
          path: rel,
          line: i + 1,
          column: m.start + 1,
          text: lines[i],
          before: context > 0
              ? lines.sublist((i - context).clamp(0, i), i)
              : const [],
          after: context > 0
              ? lines.sublist(
                  (i + 1).clamp(0, lines.length),
                  (i + 1 + context).clamp(0, lines.length),
                )
              : const [],
        ),
      );
      if (results.length >= cap) return results;
    }
  }
  return results;
}