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 {
set searchDirectory(String value) { set searchDirectory(String value) {
_searchDirectory = value; _searchDirectory = value;
Logger().debug('Updating searchDirectory to: $value');
notifyListeners(); notifyListeners();
} }
@ -100,67 +101,6 @@ class ContentSearchController with ChangeNotifier {
notifyListeners(); 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 { Future<void> startSearch() async {
_results.clear(); _results.clear();
@ -178,27 +118,12 @@ class ContentSearchController with ChangeNotifier {
} }
if (customRule) { if (customRule) {
final jsFunction = 'function match(content) {$searchQuery};'; final validationResult = ContentSearchService.validateJsRule(searchQuery);
try { if (validationResult.isError) {
// JS Logger().error('JavaScript 语法错误: ${validationResult.rawResult.toString()}');
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');
return; return;
} finally {
notifyListeners();
_jsRuntime.dispose();
} }
_results.addAll( _results.addAll(
await ContentSearchService.performCustomSearch( await ContentSearchService.performCustomSearch(
directory: searchDirectory, directory: searchDirectory,
@ -256,10 +181,4 @@ class ContentSearchController with ChangeNotifier {
searchDirectory = dir; 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 {
Logger().error('Error reading file ${file.path}: $e'); 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 {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ChangeNotifierProvider.value( return ChangeNotifierProvider.value(
value: _controller, value: _controller,
child: Padding( child: const Padding(
padding: const EdgeInsets.all(4.0), padding: EdgeInsets.all(4.0),
child: Column( child: Column(
children: [ children: [
const DirectorySettings(), // controller DirectorySettings(), // controller
SearchSettings(), 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 {
class _DirectorySettingsState extends State<DirectorySettings> { class _DirectorySettingsState extends State<DirectorySettings> {
late TextEditingController _searchDirectoryController; late TextEditingController _searchDirectoryController;
late TextEditingController _fileTypeController; late TextEditingController _fileTypeController;
late ContentSearchController _controller;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_controller = context.read<ContentSearchController>(); final controller = context.read<ContentSearchController>();
_searchDirectoryController = TextEditingController(text: _controller.searchDirectory); _searchDirectoryController = TextEditingController(text: controller.searchDirectory);
_fileTypeController = TextEditingController(text: _controller.fileType); _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;
}
} }
@override @override
@ -42,6 +30,17 @@ class _DirectorySettingsState extends State<DirectorySettings> {
@override @override
Widget build(BuildContext context) { 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( return Card(
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
@ -50,30 +49,39 @@ class _DirectorySettingsState extends State<DirectorySettings> {
Expanded( Expanded(
child: TextField( child: TextField(
controller: _searchDirectoryController, controller: _searchDirectoryController,
decoration: const InputDecoration(labelText: '搜索目录', border: OutlineInputBorder()), decoration: const InputDecoration(
onChanged: (value) => _controller.searchDirectory = value, labelText: '搜索目录',
border: OutlineInputBorder(),
), ),
onChanged: (value) => controller.searchDirectory = value,
), ),
),
const SizedBox(width: 8), const SizedBox(width: 8),
SizedBox( SizedBox(
width: 100, width: 100,
child: TextField( child: TextField(
controller: _fileTypeController, controller: _fileTypeController,
decoration: const InputDecoration(labelText: '文件类型', border: OutlineInputBorder()), decoration: const InputDecoration(
onChanged: (value) => _controller.fileType = value, labelText: '文件类型',
border: OutlineInputBorder(),
), ),
onChanged: (value) => controller.fileType = value,
), ),
),
const SizedBox(width: 8), const SizedBox(width: 8),
IconButton( IconButton(
icon: const Icon(Icons.folder_open), icon: const Icon(Icons.folder_open),
onPressed: () async { onPressed: () async {
await _controller.pickDirectory(); await controller.pickDirectory();
_searchDirectoryController.text = _controller.searchDirectory; // _searchDirectoryController.text
// Consumer
}, },
), ),
], ],
), ),
), ),
); );
},
);
} }
} }

Loading…
Cancel
Save