Browse Source

增加文件搜索功能

master
hejl 4 months ago
parent
commit
5e609e9619
  1. 2
      win_text_editor/lib/app/providers/editor_provider.dart
  2. 2
      win_text_editor/lib/app/providers/tab_provider.dart
  3. 93
      win_text_editor/lib/app/services/search_in_filies.dart
  4. 2
      win_text_editor/lib/app/widgets/file_explorer.dart
  5. 20
      win_text_editor/pubspec.lock
  6. 1
      win_text_editor/pubspec.yaml
  7. 9
      win_text_editor/windows/CMakeLists.txt

2
win_text_editor/lib/app/providers/editor_provider.dart

@ -104,7 +104,7 @@ class EditorProvider with ChangeNotifier { @@ -104,7 +104,7 @@ class EditorProvider with ChangeNotifier {
if (!_tabLoadingStates[tabId]!) break; //
final chunkLines = lines.sublist(i, min(i + linesPerChunk, lines.length));
_tabs[index].chunks!.addAll(chunkLines);
_tabs[index].chunks.addAll(chunkLines);
notifyListeners();
await Future.delayed(Duration.zero); // UI更新

2
win_text_editor/lib/app/providers/tab_provider.dart

@ -53,7 +53,7 @@ class TabProvider with ChangeNotifier { @@ -53,7 +53,7 @@ class TabProvider with ChangeNotifier {
try {
return _tabs.firstWhere((tab) => tab.id == tabId);
} catch (e) {
Logger().error("找不到选项卡: ${tabId}", source: 'EditorProvider');
Logger().error("找不到选项卡: $tabId", source: 'EditorProvider');
return null;
}
}

93
win_text_editor/lib/app/services/search_in_filies.dart

@ -0,0 +1,93 @@ @@ -0,0 +1,93 @@
import 'dart:io';
import 'dart:collection';
Future<Map<String, int>> searchInFiles({
required String folderPath,
required String filePattern,
required List<String> searchTerms,
required bool caseSensitive,
required bool wholeWord,
}) async {
// 0
final result = HashMap<String, int>(
equals: caseSensitive ? null : (a, b) => a.toLowerCase() == b.toLowerCase(),
hashCode: caseSensitive ? null : (s) => s.toLowerCase().hashCode,
);
for (final term in searchTerms) {
result[term] = 0;
}
//
final dir = Directory(folderPath);
if (!await dir.exists()) {
throw ArgumentError('Directory does not exist: $folderPath');
}
final files = await dir.list()
.where((entity) => entity is File)
.cast<File>()
.where((file) => _matchesPattern(file.path, filePattern))
.toList();
//
final regexMap = <String, RegExp>{};
for (final term in searchTerms) {
final pattern = wholeWord
? r'(?<!\w)' + RegExp.escape(term) + r'(?!\w)'
: term;
regexMap[term] = RegExp(
pattern,
caseSensitive: caseSensitive,
);
}
//
await Future.wait(files.map((file) async {
try {
final content = await file.readAsString();
for (final term in searchTerms) {
final regex = regexMap[term]!;
final matches = regex.allMatches(content);
result[term] = result[term]! + matches.length;
}
} catch (e) {
print('Error reading file ${file.path}: $e');
}
}));
// 0
result.removeWhere((_, count) => count == 0);
return result;
}
bool _matchesPattern(String fileName, String pattern) {
// *.txt
if (pattern == '*') return true;
if (pattern.startsWith('*.')) {
final ext = pattern.substring(1);
return fileName.toLowerCase().endsWith(ext.toLowerCase());
}
//
return RegExp(pattern.replaceAll('.', r'\.').replaceAll('*', '.*'),
caseSensitive: false).hasMatch(fileName);
}
// 使
void main() async {
final result = await searchInFiles(
folderPath: '/path/to/your/folder',
filePattern: '*.txt', // '*.dart'
searchTerms: ['Flutter', 'Dart', 'widget', 'main'],
caseSensitive: false,
wholeWord: true,
);
print('Search results:');
result.forEach((term, count) {
print('$term: $count');
});
}

2
win_text_editor/lib/app/widgets/file_explorer.dart

@ -1,4 +1,3 @@ @@ -1,4 +1,3 @@
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
@ -8,7 +7,6 @@ import 'package:win_text_editor/app/providers/tab_provider.dart'; @@ -8,7 +7,6 @@ import 'package:win_text_editor/app/providers/tab_provider.dart';
import '../models/file_node.dart';
import '../providers/file_provider.dart';
import '../providers/editor_provider.dart';
import 'dart:math';

20
win_text_editor/pubspec.lock

@ -117,10 +117,10 @@ packages: @@ -117,10 +117,10 @@ packages:
dependency: "direct main"
description:
name: file_picker
sha256: a222f231db4f822fc49e3b753674bda630e981873c84bf8604bceeb77fce0b24
sha256: dd51fd20fdc45e073529c102376d54deba3e120603fe711c848ce44575b838e6
url: "https://pub.flutter-io.cn"
source: hosted
version: "10.1.7"
version: "10.1.8"
flutter:
dependency: "direct main"
description: flutter
@ -280,6 +280,14 @@ packages: @@ -280,6 +280,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.3.0"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646"
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.1.0"
platform:
dependency: transitive
description:
@ -413,6 +421,14 @@ packages: @@ -413,6 +421,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
xml:
dependency: "direct main"
description:
name: xml
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.5.0"
sdks:
dart: ">=3.7.0 <4.0.0"
flutter: ">=3.27.0"

1
win_text_editor/pubspec.yaml

@ -17,6 +17,7 @@ dependencies: @@ -17,6 +17,7 @@ dependencies:
flutter_syntax_view: ^4.1.7
expandable: ^5.0.1
collection: ^1.17.0
xml: ^6.4.0
dev_dependencies:
flutter_test:

9
win_text_editor/windows/CMakeLists.txt

@ -2,6 +2,15 @@ @@ -2,6 +2,15 @@
cmake_minimum_required(VERSION 3.14)
project(win_text_editor LANGUAGES CXX)
if(MSVC)
# CRT MSVCRT.dll
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
add_compile_options(
$<$<C_COMPILER_ID:MSVC>:/MT$<$<CONFIG:Debug>:d>>
$<$<CXX_COMPILER_ID:MSVC>:/MT$<$<CONFIG:Debug>:d>>
)
endif()
# The name of the executable created for the application. Change this to change
# the on-disk name of your application.
set(BINARY_NAME "win_text_editor")

Loading…
Cancel
Save