Browse Source

文件夹加载功能完成

master
hejl 2 months ago
parent
commit
9b2a2f9d03
  1. 91
      win_text_editor/lib/modules/content_search/providers/content_search_controller.dart
  2. 25
      win_text_editor/lib/modules/content_search/services/content_search_service.dart
  3. 8
      win_text_editor/lib/modules/content_search/widgets/content_search_view.dart
  4. 50
      win_text_editor/lib/modules/content_search/widgets/directory_settings.dart

91
win_text_editor/lib/modules/content_search/providers/content_search_controller.dart

@ -67,6 +67,7 @@ class ContentSearchController with ChangeNotifier { @@ -67,6 +67,7 @@ class ContentSearchController with ChangeNotifier {
set searchDirectory(String value) {
_searchDirectory = value;
Logger().debug('Updating searchDirectory to: $value');
notifyListeners();
}
@ -100,67 +101,6 @@ class ContentSearchController with ChangeNotifier { @@ -100,67 +101,6 @@ class ContentSearchController with ChangeNotifier {
notifyListeners();
}
Future<void> performCustomSearch() async {
final results = <SearchResult>[];
int count = 0;
final dir = Directory(_searchDirectory);
await for (final entity in dir.list(recursive: true)) {
if (entity is File && _matchesFileType(entity.path, fileType)) {
try {
final lines = await entity.readAsLines();
for (int i = 0; i < lines.length; i++) {
final line = lines[i].trim();
//2 );
if (line.length < 3) continue;
final script = 'match(${jsonEncode(line)});';
final result = _jsRuntime.evaluate(script);
if (result.isError) {
Logger().error('JavaScript 执行错误: ${result.stringResult}');
continue;
}
if (result.stringResult == 'true') {
if (searchMode == SearchMode.locate) {
results.add(
SearchResult(
filePath: entity.path,
lineNumber: i + 1,
lineContent: line,
matches: [],
queryTerm: "自定义",
),
);
} else {
count = count + 1;
}
}
}
} catch (e) {
Logger().error('Error reading file ${entity.path}: $e');
}
}
}
if (searchMode == SearchMode.locate) {
Logger().debug("处理结果--定位${results.length.toString()}");
_results.addAll(results);
} else {
Logger().debug("处理结果--计数${count.toString()}");
_results.add(
SearchResult(
filePath: "JavaScript",
lineNumber: count,
lineContent: '',
matches: [],
queryTerm: "JavaScript",
),
);
}
}
Future<void> startSearch() async {
_results.clear();
@ -178,27 +118,12 @@ class ContentSearchController with ChangeNotifier { @@ -178,27 +118,12 @@ class ContentSearchController with ChangeNotifier {
}
if (customRule) {
final jsFunction = 'function match(content) {$searchQuery};';
try {
// JS
final result = _jsRuntime.evaluate(jsFunction);
if (result.isError) {
Logger().error('JavaScript 语法错误: ${result.rawResult.toString()}');
return;
}
final test = _jsRuntime.evaluate("match('test');");
if (test.stringResult != 'true' && test.stringResult != 'false') {
Logger().error('自定规则逻辑错误,没有返回布尔值,返回值为: ${test.stringResult}');
return;
}
} catch (e) {
Logger().error('JavaScript 语法检查错误: $e');
final validationResult = ContentSearchService.validateJsRule(searchQuery);
if (validationResult.isError) {
Logger().error('JavaScript 语法错误: ${validationResult.rawResult.toString()}');
return;
} finally {
notifyListeners();
_jsRuntime.dispose();
}
_results.addAll(
await ContentSearchService.performCustomSearch(
directory: searchDirectory,
@ -256,10 +181,4 @@ class ContentSearchController with ChangeNotifier { @@ -256,10 +181,4 @@ class ContentSearchController with ChangeNotifier {
searchDirectory = dir;
}
}
bool _matchesFileType(String filePath, String fileType) {
if (fileType == '*.*') return true;
final ext = path.extension(filePath).toLowerCase();
return ext == fileType.toLowerCase();
}
}

25
win_text_editor/lib/modules/content_search/services/content_search_service.dart

@ -288,4 +288,29 @@ class ContentSearchService { @@ -288,4 +288,29 @@ class ContentSearchService {
Logger().error('Error reading file ${file.path}: $e');
}
}
// ContentSearchService
/// JavaScript
static JsEvalResult validateJsRule(String jsFunction) {
final jsRuntime = getJavascriptRuntime();
try {
final jsCode = 'function match(content) {$jsFunction};';
// JS
final result = jsRuntime.evaluate(jsCode);
if (result.isError) {
return result;
}
//
final test = jsRuntime.evaluate("match('test');");
if (test.stringResult != 'true' && test.stringResult != 'false') {
return JsEvalResult('Custom rule must return boolean (true/false)', null, isError: true);
}
return test;
} finally {
jsRuntime.dispose();
}
}
}

8
win_text_editor/lib/modules/content_search/widgets/content_search_view.dart

@ -46,13 +46,13 @@ class ContentSearchViewState extends BaseViewState { @@ -46,13 +46,13 @@ class ContentSearchViewState extends BaseViewState {
Widget build(BuildContext context) {
return ChangeNotifierProvider.value(
value: _controller,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: const Padding(
padding: EdgeInsets.all(4.0),
child: Column(
children: [
const DirectorySettings(), // controller
DirectorySettings(), // controller
SearchSettings(),
const Expanded(child: ResultsView()),
Expanded(child: ResultsView()),
],
),
),

50
win_text_editor/lib/modules/content_search/widgets/directory_settings.dart

@ -12,25 +12,13 @@ class DirectorySettings extends StatefulWidget { @@ -12,25 +12,13 @@ class DirectorySettings extends StatefulWidget {
class _DirectorySettingsState extends State<DirectorySettings> {
late TextEditingController _searchDirectoryController;
late TextEditingController _fileTypeController;
late ContentSearchController _controller;
@override
void initState() {
super.initState();
_controller = context.read<ContentSearchController>();
_searchDirectoryController = TextEditingController(text: _controller.searchDirectory);
_fileTypeController = TextEditingController(text: _controller.fileType);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
final newController = context.read<ContentSearchController>();
if (_controller != newController) {
_controller = newController;
_searchDirectoryController.text = _controller.searchDirectory;
_fileTypeController.text = _controller.fileType;
}
final controller = context.read<ContentSearchController>();
_searchDirectoryController = TextEditingController(text: controller.searchDirectory);
_fileTypeController = TextEditingController(text: controller.fileType);
}
@override
@ -42,6 +30,17 @@ class _DirectorySettingsState extends State<DirectorySettings> { @@ -42,6 +30,17 @@ class _DirectorySettingsState extends State<DirectorySettings> {
@override
Widget build(BuildContext context) {
// 使 Consumer ContentSearchController
return Consumer<ContentSearchController>(
builder: (context, controller, child) {
// TextEditingController
if (_searchDirectoryController.text != controller.searchDirectory) {
_searchDirectoryController.text = controller.searchDirectory;
}
if (_fileTypeController.text != controller.fileType) {
_fileTypeController.text = controller.fileType;
}
return Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
@ -50,30 +49,39 @@ class _DirectorySettingsState extends State<DirectorySettings> { @@ -50,30 +49,39 @@ class _DirectorySettingsState extends State<DirectorySettings> {
Expanded(
child: TextField(
controller: _searchDirectoryController,
decoration: const InputDecoration(labelText: '搜索目录', border: OutlineInputBorder()),
onChanged: (value) => _controller.searchDirectory = value,
decoration: const InputDecoration(
labelText: '搜索目录',
border: OutlineInputBorder(),
),
onChanged: (value) => controller.searchDirectory = value,
),
),
const SizedBox(width: 8),
SizedBox(
width: 100,
child: TextField(
controller: _fileTypeController,
decoration: const InputDecoration(labelText: '文件类型', border: OutlineInputBorder()),
onChanged: (value) => _controller.fileType = value,
decoration: const InputDecoration(
labelText: '文件类型',
border: OutlineInputBorder(),
),
onChanged: (value) => controller.fileType = value,
),
),
const SizedBox(width: 8),
IconButton(
icon: const Icon(Icons.folder_open),
onPressed: () async {
await _controller.pickDirectory();
_searchDirectoryController.text = _controller.searchDirectory;
await controller.pickDirectory();
// _searchDirectoryController.text
// Consumer
},
),
],
),
),
);
},
);
}
}

Loading…
Cancel
Save