diff --git a/src/handler/diffHandler.ts b/src/handler/diffHandler.ts index 830a1c4..ebbaa1a 100644 --- a/src/handler/diffHandler.ts +++ b/src/handler/diffHandler.ts @@ -1,5 +1,8 @@ import * as vscode from 'vscode'; import * as path from 'path'; +import * as fs from 'fs'; +import * as os from 'os'; +import { exec } from 'child_process'; import { createTempSubdirectory } from '../util/commonUtil'; import { regInMessage, regOutMessage } from '../util/reg_messages'; @@ -8,6 +11,7 @@ import { logger } from '../util/logger'; import { FilePairManager } from '../util/diffFilePairs'; import { UiUtilWrapper } from '../util/uiUtil'; import { getFileContent } from '../util/commonUtil'; +import { ExtensionContextHolder } from '@/util/extensionContext'; async function getDocumentText(): Promise<{ text: string; beforSelect: string; select: string, afterSelect: string } | undefined> { @@ -106,6 +110,105 @@ async function getNewCode(message: any): Promise { return newCode; } +function getCodeEditorPath() { + const platform = os.platform(); + const arch = os.arch(); + + let binaryName; + + if (platform === 'darwin') { + if (arch === 'arm64') { + binaryName = 'aarch64-apple-darwin-code_editor'; + } else if (arch === 'x64') { + binaryName = 'x86_64-apple-darwin-code_editor'; + } + } else if (platform === 'win32' && arch === 'x64') { + binaryName = 'x86_64-pc-windows-msvc-code_editor.exe'; + } else if (platform === 'linux' && arch === 'x64') { + binaryName = 'x86_64-unknown-linux-musl-code_editor'; + } + + if (!binaryName) { + logger.channel()?.error(`Error: No matching binary for platform ${platform} and architecture ${arch}`); + return undefined; + } + + return path.join(UiUtilWrapper.extensionPath(), 'tools', 'code-editor', binaryName); +} + +async function applyDiffToCode(message: any): Promise { + const validVisibleTextEditors = vscode.window.visibleTextEditors.filter(editor => editor.viewColumn !== undefined); + + if (validVisibleTextEditors.length > 1) { + vscode.window.showErrorMessage(`There are more then one visible text editors. Please close all but one and try again.`); + return undefined; + } + + const editor = validVisibleTextEditors[0]; + if (!editor) { + return undefined; + } + + // get whole text in editor + const srcCode = editor.document.getText(); + let newCode = message.content; + + // Create temporary files + const tempDir = os.tmpdir(); + const srcTempFile = path.join(tempDir, 'temp_file_1'); + const newTempFile = path.join(tempDir, 'temp_file_2'); + const resultTempFile = path.join(tempDir, 'result_temp_file'); + + try { + // Save srcCode and newCode to temp files + await fs.promises.writeFile(srcTempFile, srcCode); + await fs.promises.writeFile(newTempFile, newCode); + + // Call the code_editor process + const codeEditorPath = getCodeEditorPath(); + if (!codeEditorPath) { + return undefined; + } + + // 使用 Promise 包装 exec 调用,以获取退出码 + const execWithExitCode = () => new Promise<{ exitCode: number | null, stdout: string, stderr: string }>((resolve, reject) => { + exec(`${codeEditorPath} ${srcTempFile} ${newTempFile} ${resultTempFile}`, (error, stdout, stderr) => { + if (error && 'code' in error) { + // error 是 ExecException 类型 + resolve({ exitCode: error.code || 1, stdout, stderr }); + } else if (error) { + // 其他类型的错误 + reject(error); + } else { + resolve({ exitCode: 0, stdout, stderr }); + } + }); + }); + + const { exitCode, stdout, stderr } = await execWithExitCode(); + + if (exitCode !== 0) { + logger.channel()?.error(`Error executing code_editor. Exit code: ${exitCode}. Stderr: ${stderr}`); + return undefined; + } + + // Read the result from the temp file + newCode = await fs.promises.readFile(resultTempFile, 'utf-8'); + } catch (error) { + console.error(`Error in applyDiffToCode: ${error}`); + return undefined; + } finally { + // Clean up temporary files + await Promise.all([ + fs.promises.unlink(srcTempFile).catch(() => {}), + fs.promises.unlink(newTempFile).catch(() => {}), + fs.promises.unlink(resultTempFile).catch(() => {}) + ]); + } + + return newCode; +} + regInMessage({ command: 'show_diff', content: '', fileName: '' }); export async function applyCodeWithDiff(message: any, panel: vscode.WebviewPanel | vscode.WebviewView | undefined): Promise { const newCode = await getNewCode(message); @@ -116,3 +219,14 @@ export async function applyCodeWithDiff(message: any, panel: vscode.WebviewPanel diffView(newCode, message.fileName); return; } + +regInMessage({ command: 'apply_with_diff', content: '', fileName: '' }); +export async function applyEditCodeWithDiff(message: any, panel: vscode.WebviewPanel | vscode.WebviewView | undefined): Promise { + const newCode = await applyDiffToCode(message); + if (!newCode) { + return; + } + + diffView(newCode, message.fileName); + return; +} \ No newline at end of file