release: v5.4.2 - terminal模拟器 + Operit桥接
新增插件: - terminal: 持久交互式终端,纯标准库,全平台,13个测试 - operit_bridge: Operit AI工具格式桥接,47个脚本288个工具,12个测试 其他: - plugins/operit/: 47个Operit官方脚本 - 更新plugin_registry.json/plugins_config.py - 更新about.txt/CHANGELOG.md至v5.4.2
This commit is contained in:
1 parent
b8faaae0c6
commit
dfe21298b9
56 files changed
+32586
-1
No files matched your search
@@ -0,0 +1,794 @@
|
||||
/* METADATA
|
||||
{
|
||||
name: code_reader
|
||||
|
||||
display_name: {
|
||||
zh: "代码读取器"
|
||||
en: "Code Reader"
|
||||
}
|
||||
description: { zh: "提供代码匹配抓取功能", en: "Provide code searching and extraction utilities." },
|
||||
enabledByDefault: true
|
||||
|
||||
category: "File"
|
||||
tools: [
|
||||
{
|
||||
name: search_code_in_folder
|
||||
description: { zh: "在文件夹中搜索匹配的代码", en: "Search for matching code in a folder." }
|
||||
parameters: [
|
||||
{
|
||||
name: folder_path
|
||||
description: { zh: "要搜索的文件夹路径", en: "Folder path to search." }
|
||||
type: string
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: pattern
|
||||
description: { zh: "要搜索的代码模式(字符串或正则表达式)", en: "Pattern to search for (string or regular expression)." }
|
||||
type: string
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: file_extensions
|
||||
description: { zh: "要搜索的文件扩展名列表(如 \".ts,.js\")", en: "File extension list to include (e.g. \".ts,.js\")." }
|
||||
type: string
|
||||
required: false
|
||||
},
|
||||
{
|
||||
name: recursive
|
||||
description: { zh: "是否递归搜索子文件夹(true/false)", en: "Whether to search subfolders recursively (true/false)." }
|
||||
type: string
|
||||
required: false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: extract_functions
|
||||
description: { zh: "提取文件夹中的所有函数定义", en: "Extract all function definitions from a folder." }
|
||||
parameters: [
|
||||
{
|
||||
name: folder_path
|
||||
description: { zh: "要搜索的文件夹路径", en: "Folder path to search." }
|
||||
type: string
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: function_name_pattern
|
||||
description: { zh: "函数名匹配模式(可选)", en: "Function name matching pattern (optional)." }
|
||||
type: string
|
||||
required: false
|
||||
},
|
||||
{
|
||||
name: file_extensions
|
||||
description: { zh: "要搜索的文件扩展名列表(如 \".ts,.js\")", en: "File extension list to include (e.g. \".ts,.js\")." }
|
||||
type: string
|
||||
required: false
|
||||
},
|
||||
{
|
||||
name: recursive
|
||||
description: { zh: "是否递归搜索子文件夹(true/false)", en: "Whether to search subfolders recursively (true/false)." }
|
||||
type: string
|
||||
required: false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: extract_function_block
|
||||
description: { zh: "提取特定函数的代码块", en: "Extract the code block for a specific function." }
|
||||
parameters: [
|
||||
{
|
||||
name: file_path
|
||||
description: { zh: "要读取的文件路径", en: "File path to read." }
|
||||
type: string
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: function_name
|
||||
description: { zh: "要提取的函数名称", en: "Function name to extract." }
|
||||
type: string
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: include_line_numbers
|
||||
description: { zh: "是否在结果中包含行号(true/false)", en: "Whether to include line numbers in the result (true/false)." }
|
||||
type: string
|
||||
required: false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: find_code_blocks
|
||||
description: { zh: "查找文件中的代码块", en: "Find code blocks in a file." }
|
||||
parameters: [
|
||||
{
|
||||
name: file_path
|
||||
description: { zh: "要读取的文件路径", en: "File path to read." }
|
||||
type: string
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: block_pattern
|
||||
description: { zh: "代码块匹配模式(如类定义、接口等)", en: "Code block matching pattern (e.g., class definition, interface, etc.)." }
|
||||
type: string
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: include_line_numbers
|
||||
description: { zh: "是否在结果中包含行号(true/false)", en: "Whether to include line numbers in the result (true/false)." }
|
||||
type: string
|
||||
required: false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: read_regex_matches
|
||||
description: { zh: "读取文件中匹配正则表达式的内容", en: "Read content in a file that matches a regular expression." }
|
||||
parameters: [
|
||||
{
|
||||
name: file_path
|
||||
description: { zh: "要读取的文件路径", en: "File path to read." }
|
||||
type: string
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: regex
|
||||
description: { zh: "正则表达式字符串", en: "Regular expression string." }
|
||||
type: string
|
||||
required: true
|
||||
},
|
||||
{
|
||||
name: include_line_numbers
|
||||
description: { zh: "是否在结果中包含行号(true/false)", en: "Whether to include line numbers in the result (true/false)." }
|
||||
type: string
|
||||
required: false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Writer模块 - 提供代码抓取和分析功能
|
||||
*/
|
||||
const writer = (function () {
|
||||
|
||||
/**
|
||||
* 参数类型转换函数 - 将输入参数转换为期望的数据类型
|
||||
* @param params 输入参数对象
|
||||
* @param paramTypes 参数类型定义
|
||||
* @returns 转换后的参数对象
|
||||
*/
|
||||
function convertParamTypes(params: Record<string, any>, paramTypes: Record<string, string>): Record<string, any> {
|
||||
if (!params || !paramTypes) return params;
|
||||
|
||||
const result: Record<string, any> = {};
|
||||
|
||||
for (const key in params) {
|
||||
if (params[key] === undefined || params[key] === undefined) {
|
||||
result[key] = params[key];
|
||||
continue;
|
||||
}
|
||||
|
||||
const expectedType = paramTypes[key];
|
||||
if (!expectedType) {
|
||||
// 如果没有指定类型,保持原样
|
||||
result[key] = params[key];
|
||||
continue;
|
||||
}
|
||||
|
||||
// 获取参数值
|
||||
const value = params[key];
|
||||
|
||||
try {
|
||||
switch (expectedType.toLowerCase()) {
|
||||
case 'number':
|
||||
// 将字符串转换为数字
|
||||
if (typeof value === 'string') {
|
||||
if (value.includes('.')) {
|
||||
result[key] = parseFloat(value);
|
||||
} else {
|
||||
result[key] = parseInt(value, 10);
|
||||
}
|
||||
|
||||
// 检查转换结果是否为有效数字
|
||||
if (isNaN(result[key])) {
|
||||
throw new Error(`参数 ${key} 无法转换为数字: ${value}`);
|
||||
}
|
||||
} else {
|
||||
result[key] = value;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'boolean':
|
||||
// 将字符串转换为布尔值
|
||||
if (typeof value === 'string') {
|
||||
const lowerValue = value.toLowerCase();
|
||||
if (lowerValue === 'true' || lowerValue === '1' || lowerValue === 'yes') {
|
||||
result[key] = true;
|
||||
} else if (lowerValue === 'false' || lowerValue === '0' || lowerValue === 'no') {
|
||||
result[key] = false;
|
||||
} else {
|
||||
throw new Error(`参数 ${key} 无法转换为布尔值: ${value}`);
|
||||
}
|
||||
} else {
|
||||
result[key] = value;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'array':
|
||||
// 将字符串转换为数组
|
||||
if (typeof value === 'string') {
|
||||
try {
|
||||
result[key] = JSON.parse(value);
|
||||
if (!Array.isArray(result[key])) {
|
||||
throw new Error('解析结果不是数组');
|
||||
}
|
||||
} catch (e) {
|
||||
throw new Error(`参数 ${key} 无法转换为数组: ${value}`);
|
||||
}
|
||||
} else {
|
||||
result[key] = value;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
// 将字符串转换为对象
|
||||
if (typeof value === 'string') {
|
||||
try {
|
||||
result[key] = JSON.parse(value);
|
||||
if (Array.isArray(result[key]) || typeof result[key] !== 'object') {
|
||||
throw new Error('解析结果不是对象');
|
||||
}
|
||||
} catch (e) {
|
||||
throw new Error(`参数 ${key} 无法转换为对象: ${value}`);
|
||||
}
|
||||
} else {
|
||||
result[key] = value;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// 其他类型或未指定类型,保持原样
|
||||
result[key] = value;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`参数类型转换错误: ${error.message}`);
|
||||
// 转换失败时保留原始值
|
||||
result[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 包装函数 - 统一处理所有Writer函数的返回结果
|
||||
* @param func 原始函数
|
||||
* @param params 函数参数
|
||||
* @param successMessage 成功消息
|
||||
* @param failMessage 失败消息
|
||||
*/
|
||||
async function writer_wrap<T>(
|
||||
func: (params: any) => Promise<any>,
|
||||
params: any,
|
||||
successMessage: string,
|
||||
failMessage: string
|
||||
): Promise<void> {
|
||||
try {
|
||||
console.log(`开始执行函数: ${func.name || '匿名函数'}`);
|
||||
console.log(`参数:`, JSON.stringify(params, undefined, 2));
|
||||
|
||||
// 执行原始函数
|
||||
const result = await func(params);
|
||||
|
||||
console.log(`函数 ${func.name || '匿名函数'} 执行结果:`, JSON.stringify(result, undefined, 2));
|
||||
|
||||
// 如果原始函数已经调用了complete,就不需要再次调用
|
||||
if (result === undefined) return;
|
||||
|
||||
// 根据结果类型处理
|
||||
if (typeof result === "boolean") {
|
||||
// 布尔类型结果
|
||||
complete({
|
||||
success: result,
|
||||
message: result ? successMessage : failMessage
|
||||
});
|
||||
} else {
|
||||
// 数据类型结果
|
||||
complete({
|
||||
success: true,
|
||||
message: successMessage,
|
||||
data: result
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
// 详细记录错误信息
|
||||
console.error(`函数 ${func.name || '匿名函数'} 执行失败!`);
|
||||
console.error(`错误信息: ${error.message}`);
|
||||
console.error(`错误堆栈: ${error.stack}`);
|
||||
|
||||
// 处理错误
|
||||
complete({
|
||||
success: false,
|
||||
message: `${failMessage}: ${error.message}`,
|
||||
error_stack: error.stack
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归读取目录中的所有文件
|
||||
* @param dir 目录路径
|
||||
* @param fileList 文件列表累加器
|
||||
* @param extensions 文件扩展名过滤列表
|
||||
* @returns 文件路径列表
|
||||
*/
|
||||
async function readFilesRecursively(dir: string, fileList: string[] = [], extensions?: string[]): Promise<string[]> {
|
||||
try {
|
||||
// 使用Tools.Files.list替代fs.readdirSync
|
||||
const listResult = await Tools.Files.list(dir);
|
||||
const entries = listResult.entries || [];
|
||||
|
||||
// 遍历目录条目
|
||||
for (const entry of entries) {
|
||||
const filePath = `${dir}/${entry.name}`;
|
||||
|
||||
if (entry.isDirectory) {
|
||||
// 递归处理子目录
|
||||
await readFilesRecursively(filePath, fileList, extensions);
|
||||
} else {
|
||||
// 过滤文件扩展名
|
||||
if (!extensions || extensions.length === 0 ||
|
||||
extensions.some(ext => entry.name.toLowerCase().endsWith(ext.toLowerCase()))) {
|
||||
fileList.push(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`读取目录失败: ${error.message}`);
|
||||
}
|
||||
|
||||
return fileList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在文件夹中搜索匹配的代码
|
||||
* @param params 搜索参数
|
||||
* @returns 搜索结果
|
||||
*/
|
||||
async function search_code_in_folder(params: any): Promise<any> {
|
||||
const paramTypes = {
|
||||
recursive: 'boolean',
|
||||
};
|
||||
|
||||
params = convertParamTypes(params, paramTypes);
|
||||
|
||||
const {
|
||||
folder_path,
|
||||
pattern,
|
||||
file_extensions = '.js,.ts,.jsx,.tsx,.java,.cs,.py',
|
||||
recursive = true
|
||||
} = params;
|
||||
|
||||
// 验证必需参数
|
||||
if (!folder_path) {
|
||||
throw new Error('文件夹路径不能为空');
|
||||
}
|
||||
if (!pattern) {
|
||||
throw new Error('搜索模式不能为空');
|
||||
}
|
||||
|
||||
try {
|
||||
const patternRegex = new RegExp(pattern, 'gm');
|
||||
const extensions = file_extensions.split(',');
|
||||
let files: string[];
|
||||
|
||||
// 根据recursive参数决定是否递归搜索
|
||||
if (recursive) {
|
||||
files = await readFilesRecursively(folder_path, [], extensions);
|
||||
} else {
|
||||
// 使用Tools.Files.list替代fs.readdirSync
|
||||
const listResult = await Tools.Files.list(folder_path);
|
||||
const entries = listResult.entries || [];
|
||||
|
||||
files = entries
|
||||
.filter(entry =>
|
||||
!entry.isDirectory &&
|
||||
extensions.some(ext => entry.name.toLowerCase().endsWith(ext.toLowerCase()))
|
||||
)
|
||||
.map(entry => `${folder_path}/${entry.name}`);
|
||||
}
|
||||
|
||||
// 搜索结果
|
||||
const results: any[] = [];
|
||||
|
||||
for (const file of files) {
|
||||
try {
|
||||
// 使用Tools.Files.read替代fs.readFileSync
|
||||
const fileResult = await Tools.Files.read(file);
|
||||
const content = fileResult.content || '';
|
||||
const matches: any[] = [];
|
||||
let match;
|
||||
|
||||
// 使用正则表达式查找所有匹配项
|
||||
patternRegex.lastIndex = 0; // 重置正则表达式索引
|
||||
while ((match = patternRegex.exec(content)) !== undefined) {
|
||||
const lineNumber = content.substring(0, match.index).split('\n').length;
|
||||
const lineContent = content.split('\n')[lineNumber - 1];
|
||||
|
||||
matches.push({
|
||||
match: match[0],
|
||||
line: lineNumber,
|
||||
content: lineContent
|
||||
});
|
||||
}
|
||||
|
||||
if (matches.length > 0) {
|
||||
results.push({
|
||||
file: file,
|
||||
matches: matches
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`处理文件 ${file} 时出错: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
} catch (error) {
|
||||
throw new Error(`搜索代码时出错: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提取文件夹中的所有函数定义
|
||||
* @param params 提取参数
|
||||
* @returns 提取结果
|
||||
*/
|
||||
async function extract_functions(params: any): Promise<any> {
|
||||
const paramTypes = {
|
||||
recursive: 'boolean',
|
||||
};
|
||||
|
||||
params = convertParamTypes(params, paramTypes);
|
||||
|
||||
const {
|
||||
folder_path,
|
||||
function_name_pattern = '.*',
|
||||
file_extensions = '.js,.ts,.jsx,.tsx',
|
||||
recursive = true
|
||||
} = params;
|
||||
|
||||
// 验证必需参数
|
||||
if (!folder_path) {
|
||||
throw new Error('文件夹路径不能为空');
|
||||
}
|
||||
|
||||
try {
|
||||
// 函数定义的正则表达式模式
|
||||
// 匹配函数声明、函数表达式、箭头函数、类方法等
|
||||
const functionPatterns = [
|
||||
// 函数声明: function name() {}
|
||||
`function\\s+(${function_name_pattern})\\s*\\([^)]*\\)\\s*\\{`,
|
||||
// 函数表达式: const name = function() {}
|
||||
`(?:const|let|var)\\s+(${function_name_pattern})\\s*=\\s*function\\s*\\([^)]*\\)\\s*\\{`,
|
||||
// 箭头函数: const name = () => {}
|
||||
`(?:const|let|var)\\s+(${function_name_pattern})\\s*=\\s*\\([^)]*\\)\\s*=>\\s*\\{`,
|
||||
// 类方法: name() {}
|
||||
`(?:async\\s+)?(${function_name_pattern})\\s*\\([^)]*\\)\\s*\\{`
|
||||
];
|
||||
|
||||
// 合并所有模式
|
||||
const combinedPattern = functionPatterns.join('|');
|
||||
|
||||
// 使用通用代码搜索功能查找所有函数
|
||||
return await search_code_in_folder({
|
||||
folder_path,
|
||||
pattern: combinedPattern,
|
||||
file_extensions,
|
||||
recursive
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
throw new Error(`提取函数时出错: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提取特定函数的代码块
|
||||
* @param params 提取参数
|
||||
* @returns 提取结果
|
||||
*/
|
||||
async function extract_function_block(params: any): Promise<any> {
|
||||
const paramTypes = {
|
||||
include_line_numbers: 'boolean',
|
||||
};
|
||||
|
||||
params = convertParamTypes(params, paramTypes);
|
||||
|
||||
const {
|
||||
file_path,
|
||||
function_name,
|
||||
include_line_numbers = false
|
||||
} = params;
|
||||
|
||||
// 验证必需参数
|
||||
if (!file_path) {
|
||||
throw new Error('文件路径不能为空');
|
||||
}
|
||||
if (!function_name) {
|
||||
throw new Error('函数名称不能为空');
|
||||
}
|
||||
|
||||
try {
|
||||
// 使用Tools.Files.read替代fs.readFileSync
|
||||
const fileResult = await Tools.Files.read(file_path);
|
||||
const content = fileResult.content || '';
|
||||
const lines = content.split('\n');
|
||||
|
||||
// 函数定义的正则表达式模式
|
||||
const functionPatterns = [
|
||||
// 函数声明: function name() {}
|
||||
`function\\s+${function_name}\\s*\\([^)]*\\)\\s*\\{`,
|
||||
// 函数表达式: const name = function() {}
|
||||
`(?:const|let|var)\\s+${function_name}\\s*=\\s*function\\s*\\([^)]*\\)\\s*\\{`,
|
||||
// 箭头函数: const name = () => {}
|
||||
`(?:const|let|var)\\s+${function_name}\\s*=\\s*\\([^)]*\\)\\s*=>\\s*\\{`,
|
||||
// 类方法: name() {}
|
||||
`(?:async\\s+)?${function_name}\\s*\\([^)]*\\)\\s*\\{`
|
||||
];
|
||||
|
||||
// 合并所有模式
|
||||
const combinedPattern = functionPatterns.join('|');
|
||||
const functionRegex = new RegExp(combinedPattern);
|
||||
|
||||
// 查找函数定义行
|
||||
let startLine = -1;
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (functionRegex.test(lines[i])) {
|
||||
startLine = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (startLine === -1) {
|
||||
return { error: `未找到函数: ${function_name}` };
|
||||
}
|
||||
|
||||
// 追踪括号匹配,找到函数结束位置
|
||||
let bracesCount = 0;
|
||||
let endLine = startLine;
|
||||
|
||||
// 检查函数定义那一行的花括号
|
||||
const openingBraces = (lines[startLine].match(/{/g) || []).length;
|
||||
const closingBraces = (lines[startLine].match(/}/g) || []).length;
|
||||
bracesCount = openingBraces - closingBraces;
|
||||
|
||||
// 继续向下查找匹配的闭合括号
|
||||
for (let i = startLine + 1; i < lines.length; i++) {
|
||||
const openBraces = (lines[i].match(/{/g) || []).length;
|
||||
const closeBraces = (lines[i].match(/}/g) || []).length;
|
||||
|
||||
bracesCount += openBraces;
|
||||
bracesCount -= closeBraces;
|
||||
|
||||
// 当括号计数归零,找到函数结束位置
|
||||
if (bracesCount === 0) {
|
||||
endLine = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 提取函数代码块
|
||||
const functionBlock = lines.slice(startLine, endLine + 1).join('\n');
|
||||
|
||||
const result: any = {
|
||||
function_name,
|
||||
code: functionBlock,
|
||||
};
|
||||
|
||||
if (include_line_numbers) {
|
||||
result.start_line = startLine + 1; // 转换为1-based索引
|
||||
result.end_line = endLine + 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
} catch (error) {
|
||||
throw new Error(`提取函数代码块时出错: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找文件中的代码块
|
||||
* @param params 查找参数
|
||||
* @returns 查找结果
|
||||
*/
|
||||
async function find_code_blocks(params: any): Promise<any> {
|
||||
const paramTypes = {
|
||||
include_line_numbers: 'boolean',
|
||||
};
|
||||
|
||||
params = convertParamTypes(params, paramTypes);
|
||||
|
||||
const {
|
||||
file_path,
|
||||
block_pattern,
|
||||
include_line_numbers = false
|
||||
} = params;
|
||||
|
||||
// 验证必需参数
|
||||
if (!file_path) {
|
||||
throw new Error('文件路径不能为空');
|
||||
}
|
||||
if (!block_pattern) {
|
||||
throw new Error('代码块匹配模式不能为空');
|
||||
}
|
||||
|
||||
try {
|
||||
// 使用Tools.Files.read替代fs.readFileSync
|
||||
const fileResult = await Tools.Files.read(file_path);
|
||||
const content = fileResult.content || '';
|
||||
const blockRegex = new RegExp(block_pattern, 'gm');
|
||||
|
||||
const matches: any[] = [];
|
||||
let match;
|
||||
|
||||
// 使用正则表达式查找所有匹配项
|
||||
while ((match = blockRegex.exec(content)) !== undefined) {
|
||||
const matchText = match[0];
|
||||
const startIndex = match.index;
|
||||
|
||||
// 查找代码块的开始和结束位置
|
||||
const lines = content.substring(0, startIndex).split('\n');
|
||||
const startLine = lines.length;
|
||||
|
||||
let endIndex = startIndex + matchText.length;
|
||||
let bracesCount = 0;
|
||||
|
||||
// 如果匹配到的是代码块开始,需要找到对应的结束
|
||||
if (matchText.includes('{')) {
|
||||
// 计算初始左括号数量
|
||||
const initialOpenBraces = (matchText.match(/{/g) || []).length;
|
||||
const initialCloseBraces = (matchText.match(/}/g) || []).length;
|
||||
bracesCount = initialOpenBraces - initialCloseBraces;
|
||||
|
||||
// 如果括号不平衡,继续向后查找
|
||||
if (bracesCount > 0) {
|
||||
const remainingContent = content.substring(endIndex);
|
||||
let currentPos = 0;
|
||||
|
||||
// 逐字符扫描,跟踪括号嵌套
|
||||
for (let i = 0; i < remainingContent.length; i++) {
|
||||
const char = remainingContent[i];
|
||||
|
||||
if (char === '{') {
|
||||
bracesCount++;
|
||||
} else if (char === '}') {
|
||||
bracesCount--;
|
||||
|
||||
// 找到匹配的闭合括号
|
||||
if (bracesCount === 0) {
|
||||
currentPos = i + 1; // +1 包含闭合括号
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新块的结束位置
|
||||
endIndex += currentPos;
|
||||
}
|
||||
}
|
||||
|
||||
// 提取完整的代码块
|
||||
const codeBlock = content.substring(startIndex, endIndex);
|
||||
|
||||
// 确定结束行号
|
||||
const blockLines = codeBlock.split('\n');
|
||||
const endLine = startLine + blockLines.length - 1;
|
||||
|
||||
const result: any = {
|
||||
block: codeBlock,
|
||||
};
|
||||
|
||||
if (include_line_numbers) {
|
||||
result.start_line = startLine;
|
||||
result.end_line = endLine;
|
||||
}
|
||||
|
||||
matches.push(result);
|
||||
}
|
||||
|
||||
return {
|
||||
file: file_path,
|
||||
blocks: matches
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
throw new Error(`查找代码块时出错: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取文件中匹配正则表达式的内容
|
||||
* @param params 读取参数
|
||||
* @returns 读取结果
|
||||
*/
|
||||
async function read_regex_matches(params: any): Promise<any> {
|
||||
const paramTypes = {
|
||||
include_line_numbers: 'boolean',
|
||||
};
|
||||
|
||||
params = convertParamTypes(params, paramTypes);
|
||||
|
||||
const {
|
||||
file_path,
|
||||
regex,
|
||||
include_line_numbers = false
|
||||
} = params;
|
||||
|
||||
// 验证必需参数
|
||||
if (!file_path) {
|
||||
throw new Error('文件路径不能为空');
|
||||
}
|
||||
if (!regex) {
|
||||
throw new Error('正则表达式不能为空');
|
||||
}
|
||||
|
||||
try {
|
||||
// 使用Tools.Files.read替代fs.readFileSync
|
||||
const fileResult = await Tools.Files.read(file_path);
|
||||
const content = fileResult.content || '';
|
||||
const lines = content.split('\n');
|
||||
const pattern = new RegExp(regex, 'gm');
|
||||
|
||||
const matches: any[] = [];
|
||||
let match;
|
||||
|
||||
// 使用正则表达式查找所有匹配项
|
||||
while ((match = pattern.exec(content)) !== undefined) {
|
||||
const lineNumber = content.substring(0, match.index).split('\n').length;
|
||||
const lineContent = content.split('\n')[lineNumber - 1];
|
||||
|
||||
const result: any = {
|
||||
match: match[0],
|
||||
content: lineContent,
|
||||
};
|
||||
|
||||
if (include_line_numbers) {
|
||||
result.line = lineNumber;
|
||||
}
|
||||
|
||||
// 添加捕获组
|
||||
if (match.length > 1) {
|
||||
result.groups = match.slice(1);
|
||||
}
|
||||
|
||||
matches.push(result);
|
||||
}
|
||||
|
||||
return {
|
||||
file: file_path,
|
||||
matches: matches
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
throw new Error(`匹配正则表达式时出错: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 返回模块公共方法
|
||||
return {
|
||||
search_code_in_folder: (params: any) => writer_wrap(search_code_in_folder, params, '代码搜索完成', '代码搜索失败'),
|
||||
extract_functions: (params: any) => writer_wrap(extract_functions, params, '函数提取完成', '函数提取失败'),
|
||||
extract_function_block: (params: any) => writer_wrap(extract_function_block, params, '函数代码块提取完成', '函数代码块提取失败'),
|
||||
find_code_blocks: (params: any) => writer_wrap(find_code_blocks, params, '代码块查找完成', '代码块查找失败'),
|
||||
read_regex_matches: (params: any) => writer_wrap(read_regex_matches, params, '正则表达式匹配完成', '正则表达式匹配失败')
|
||||
};
|
||||
})();
|
||||
|
||||
// 导出所有函数
|
||||
exports.search_code_in_folder = writer.search_code_in_folder;
|
||||
exports.extract_functions = writer.extract_functions;
|
||||
exports.extract_function_block = writer.extract_function_block;
|
||||
exports.find_code_blocks = writer.find_code_blocks;
|
||||
exports.read_regex_matches = writer.read_regex_matches;
|
||||
Reference in new issue
Block a user