import * as vscode from "vscode"; import { readFileContent } from "./readFiles"; import { createFile, createOrOverwriteFile, deleteFile, updateFile, renameFile, replaceFile, } from "./createFiles"; /** * 处理用户消息 */ export async function handleUserMessage( panel: vscode.WebviewPanel, text: string ) { console.log("收到用户消息:", text); // 检查是否是文件操作命令 const fileOperation = parseFileOperation(text); console.log("解析结果:", fileOperation); if (fileOperation) { console.log("执行文件操作:", fileOperation.type, fileOperation.filePath); await handleFileOperation(panel, fileOperation); return; } // 普通消息处理 console.log("作为普通消息处理"); const reply = getMockReply(text); setTimeout(() => { panel.webview.postMessage({ command: "receiveMessage", text: reply, }); }, 500); } /** * 解析文件操作命令 */ function parseFileOperation(text: string): { type: "create" | "delete" | "read" | "update" | "rename" | "replace"; filePath: string; content?: string; newPath?: string; searchText?: string; replaceText?: string; } | null { const lowerText = text.toLowerCase().trim(); // 匹配创建文件:创建一个 xxx.ts 文件 const createMatch = lowerText.match(/创建(?:一个)?(.+?\.\w+)(?:文件)?/); if (createMatch) { const filePath = createMatch[1].trim(); return { type: "create", filePath: filePath, content: getDefaultContent(filePath), }; } // 匹配删除文件:删除 xxx.ts 文件 const deleteMatch = lowerText.match(/删除(.+?\.\w+)(?:文件)?/); if (deleteMatch) { const filePath = deleteMatch[1].trim(); return { type: "delete", filePath: filePath, }; } // 匹配重命名文件:将 xxx.ts 重命名为 yyy.ts 或 把 xxx.ts 改名为 yyy.ts(优先匹配,避免被修改匹配) const renameMatch = lowerText.match(/(?:将|把)\s*(.+?\.\w+)\s*(?:重命名|改名)\s*(?:为|成)\s*(.+?\.\w+)/); if (renameMatch) { const oldPath = renameMatch[1].trim(); const newPath = renameMatch[2].trim(); return { type: "rename", filePath: oldPath, newPath: newPath, }; } // 匹配替换内容:支持多种格式 // 格式1: 在 xxx.ts 中将 "aaa" 替换为 "bbb" // 格式2: 将 xxx.ts 文件 "aaa" 替换为 "bbb" // 格式3: 将 xxx.ts 文件 'aaa' 替换为 'bbb' const replaceMatch1 = lowerText.match(/在\s*(.+?\.\w+)\s*(?:文件)?中?\s*(?:将|把)\s*["'](.+?)["']\s*替换\s*(?:为|成)\s*["'](.+?)["']/); if (replaceMatch1) { const filePath = replaceMatch1[1].trim(); const searchText = replaceMatch1[2].trim(); const replaceText = replaceMatch1[3].trim(); return { type: "replace", filePath: filePath, searchText: searchText, replaceText: replaceText, }; } // 格式2: 将 xxx.ts 文件 "aaa" 替换为 "bbb" const replaceMatch2 = lowerText.match(/(?:将|把)\s*(.+?\.\w+)\s*(?:文件)?\s*["'](.+?)["']\s*替换\s*(?:为|成)\s*["'](.+?)["']/); if (replaceMatch2) { const filePath = replaceMatch2[1].trim(); const searchText = replaceMatch2[2].trim(); const replaceText = replaceMatch2[3].trim(); return { type: "replace", filePath: filePath, searchText: searchText, replaceText: replaceText, }; } // 匹配读取文件:读取 xxx.ts 文件 或 打开 xxx.ts const readMatch = lowerText.match(/(?:读取|打开)\s*(.+?\.\w+)\s*(?:文件)?/); if (readMatch) { const filePath = readMatch[1].trim(); return { type: "read", filePath: filePath, }; } // 匹配修改文件:修改 xxx.ts 文件(放在最后,避免误匹配) const updateMatch = lowerText.match(/修改\s*(.+?\.\w+)\s*(?:文件)?/); if (updateMatch) { const filePath = updateMatch[1].trim(); return { type: "update", filePath: filePath, }; } return null; } /** * 处理文件操作 */ async function handleFileOperation( panel: vscode.WebviewPanel, operation: { type: "create" | "delete" | "read" | "update" | "rename" | "replace"; filePath: string; content?: string; newPath?: string; searchText?: string; replaceText?: string; } ) { try { switch (operation.type) { case "create": await createFile(operation.filePath, operation.content || ""); panel.webview.postMessage({ command: "receiveMessage", text: `✅ 文件创建成功: ${operation.filePath}`, }); vscode.window.showInformationMessage( `文件创建成功: ${operation.filePath}` ); break; case "delete": await deleteFile(operation.filePath); panel.webview.postMessage({ command: "receiveMessage", text: `✅ 文件删除成功: ${operation.filePath}`, }); vscode.window.showInformationMessage( `文件删除成功: ${operation.filePath}` ); break; case "read": const content = await readFileContent(operation.filePath); panel.webview.postMessage({ command: "fileContent", content: content, filePath: operation.filePath, }); break; case "update": const currentContent = await readFileContent(operation.filePath); panel.webview.postMessage({ command: "editFile", content: currentContent, filePath: operation.filePath, }); break; case "rename": if (!operation.newPath) { throw new Error("缺少新文件名"); } await renameFile(operation.filePath, operation.newPath); panel.webview.postMessage({ command: "receiveMessage", text: `✅ 文件重命名成功: ${operation.filePath} → ${operation.newPath}`, }); vscode.window.showInformationMessage( `文件重命名成功: ${operation.filePath} → ${operation.newPath}` ); break; case "replace": if (!operation.searchText || !operation.replaceText) { throw new Error("缺少替换内容"); } await replaceFile( operation.filePath, operation.searchText, operation.replaceText ); panel.webview.postMessage({ command: "receiveMessage", text: `✅ 文件内容替换成功: ${operation.filePath}`, }); vscode.window.showInformationMessage( `文件内容替换成功: ${operation.filePath}` ); break; } } catch (error) { const errorMsg = error instanceof Error ? error.message : "操作失败"; panel.webview.postMessage({ command: "receiveMessage", text: `❌ ${errorMsg}`, }); vscode.window.showErrorMessage(errorMsg); } } /** * 根据文件扩展名生成默认内容 */ function getDefaultContent(filePath: string): string { const ext = filePath.split(".").pop()?.toLowerCase(); switch (ext) { case "ts": return `// ${filePath}\n\nexport {};\n`; case "js": return `// ${filePath}\n\n`; case "json": return "{\n \n}\n"; case "md": return `# ${filePath}\n\n`; case "html": return ` Document `; case "css": return `/* ${filePath} */\n\n`; case "v": case "sv": return `// ${filePath}\n\nmodule ${ filePath.split(".")[0] } (\n \n);\n\nendmodule\n`; default: return ""; } } /** * 处理文件读取请求 */ export async function handleReadFile( panel: vscode.WebviewPanel, filePath: string ) { try { const content = await readFileContent(filePath); panel.webview.postMessage({ command: "fileContent", content: content, filePath: filePath, }); } catch (error) { panel.webview.postMessage({ command: "fileError", error: error instanceof Error ? error.message : "读取文件失败", }); } } /** * 处理文件创建请求 */ export async function handleCreateFile( panel: vscode.WebviewPanel, filePath: string, content: string, overwrite: boolean = false //是否覆盖 ) { try { if (overwrite) { await createOrOverwriteFile(filePath, content); } else { await createFile(filePath, content); } panel.webview.postMessage({ command: "fileCreated", filePath: filePath, message: " 文件创建成功", }); vscode.window.showInformationMessage(`文件创建成功: ${filePath}`); } catch (error) { panel.webview.postMessage({ command: "fileCreateError", error: error instanceof Error ? error.message : "创建文件失败", }); vscode.window.showErrorMessage( `创建文件失败: ${error instanceof Error ? error.message : "未知错误"}` ); } } /** * 处理文件更新请求 */ export async function handleUpdateFile( panel: vscode.WebviewPanel, filePath: string, content: string ) { try { await updateFile(filePath, content); panel.webview.postMessage({ command: "fileUpdated", filePath: filePath, message: " 文件更新成功", }); vscode.window.showInformationMessage(`文件更新成功: ${filePath}`); } catch (error) { panel.webview.postMessage({ command: "fileUpdateError", error: error instanceof Error ? error.message : "更新文件失败", }); vscode.window.showErrorMessage( `更新文件失败: ${error instanceof Error ? error.message : "未知错误"}` ); } } /** * 处理文件重命名请求 */ export async function handleRenameFile( panel: vscode.WebviewPanel, oldPath: string, newPath: string ) { try { await renameFile(oldPath, newPath); panel.webview.postMessage({ command: "fileRenamed", oldPath: oldPath, newPath: newPath, message: "文件重命名成功", }); vscode.window.showInformationMessage( `文件重命名成功: ${oldPath} → ${newPath}` ); } catch (error) { panel.webview.postMessage({ command: "fileRenameError", error: error instanceof Error ? error.message : "重命名文件失败", }); vscode.window.showErrorMessage( `重命名文件失败: ${error instanceof Error ? error.message : "未知错误"}` ); } } /** * 处理文件内容替换请求 */ export async function handleReplaceInFile( panel: vscode.WebviewPanel, filePath: string, searchText: string, replaceText: string ) { try { await replaceFile(filePath, searchText, replaceText); panel.webview.postMessage({ command: "fileReplaced", filePath: filePath, message: "文件内容替换成功", }); vscode.window.showInformationMessage(`文件内容替换成功: ${filePath}`); } catch (error) { panel.webview.postMessage({ command: "fileReplaceError", error: error instanceof Error ? error.message : "替换文件内容失败", }); vscode.window.showErrorMessage( `替换文件内容失败: ${error instanceof Error ? error.message : "未知错误"}` ); } } /** * 获取模拟回复 */ function getMockReply(question: string): string { const replies = [ `已收到您的问题:"${question}" 这是一个演示版本,实际需要连接AI服务。 示例回复:这是一个计数器模板: \`\`\`verilog module counter ( input clk, input rst_n, output reg [3:0] count ); always @(posedge clk or negedge rst_n) begin if (!rst_n) count <= 0; else count <= count + 1; end endmodule \`\`\``, `感谢提问!关于"${question}",在真实版本中我会: 1. 分析您的代码上下文 2. 提供优化建议 3. 生成完整代码 4. 解释设计原理 当前是演示版,请点击侧边栏按钮快速生成代码。`, ]; return replies[Math.floor(Math.random() * replies.length)]; } /** * 将代码插入到编辑器 */ export function insertCodeToEditor(code: string) { const editor = vscode.window.activeTextEditor; if (editor) { editor.edit((editBuilder) => { editBuilder.insert(editor.selection.active, code); }); vscode.window.showInformationMessage("代码已插入"); } else { vscode.window.showWarningMessage("请先打开一个编辑器"); } }