451 lines
13 KiB
TypeScript
451 lines
13 KiB
TypeScript
import * as vscode from "vscode";
|
|
import * as path from "path";
|
|
|
|
/**
|
|
* 创建文件(本来不存在的情况)
|
|
*/
|
|
export async function createFile(
|
|
filePath: string,
|
|
content: string = ""
|
|
): Promise<void> {
|
|
try {
|
|
// 如果是相对路径,转换为绝对路径
|
|
let absolutePath = filePath;
|
|
if (!path.isAbsolute(filePath)) {
|
|
const workspaceFolders = vscode.workspace.workspaceFolders;
|
|
if (workspaceFolders && workspaceFolders.length > 0) {
|
|
absolutePath = path.join(workspaceFolders[0].uri.fsPath, filePath);
|
|
} else {
|
|
throw new Error(
|
|
"请先打开一个文件夹作为工作区,这样我就能为您创建文件了"
|
|
);
|
|
}
|
|
}
|
|
|
|
const fileUri = vscode.Uri.file(absolutePath);
|
|
|
|
// 检测文件是否已存在
|
|
try {
|
|
await vscode.workspace.fs.stat(fileUri);
|
|
throw new Error(`文件已存在: ${absolutePath}`);
|
|
} catch (error: any) {
|
|
// 如果文件不存在,继续创建
|
|
if (error.code !== "FileNotFound") {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// 确保目录存在
|
|
const dirPath = path.dirname(absolutePath);
|
|
const dirUri = vscode.Uri.file(dirPath);
|
|
try {
|
|
await vscode.workspace.fs.stat(dirUri);
|
|
} catch {
|
|
await vscode.workspace.fs.createDirectory(dirUri);
|
|
}
|
|
|
|
// 创建文件
|
|
const contentBytes = Buffer.from(content, "utf-8");
|
|
await vscode.workspace.fs.writeFile(fileUri, contentBytes);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 创建文件(如果存在则覆盖)
|
|
*/
|
|
export async function createOrOverwriteFile(
|
|
filePath: string,
|
|
content: string = ""
|
|
): Promise<void> {
|
|
try {
|
|
// 如果是相对路径,转换为绝对路径
|
|
let absolutePath = filePath;
|
|
if (!path.isAbsolute(filePath)) {
|
|
const workspaceFolders = vscode.workspace.workspaceFolders;
|
|
if (workspaceFolders && workspaceFolders.length > 0) {
|
|
absolutePath = path.join(workspaceFolders[0].uri.fsPath, filePath);
|
|
} else {
|
|
throw new Error(
|
|
"请先打开一个文件夹作为工作区,这样我就能为您创建文件了"
|
|
);
|
|
}
|
|
}
|
|
|
|
// 确保目录存在
|
|
const dirPath = path.dirname(absolutePath);
|
|
const dirUri = vscode.Uri.file(dirPath);
|
|
try {
|
|
await vscode.workspace.fs.stat(dirUri);
|
|
} catch {
|
|
await vscode.workspace.fs.createDirectory(dirUri);
|
|
}
|
|
|
|
// 创建或覆盖文件
|
|
const fileUri = vscode.Uri.file(absolutePath);
|
|
const contentBytes = Buffer.from(content, "utf-8");
|
|
await vscode.workspace.fs.writeFile(fileUri, contentBytes);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 创建目录
|
|
*/
|
|
export async function createDirectory(dirPath: string): Promise<void> {
|
|
try {
|
|
// 如果是相对路径,转换为绝对路径
|
|
let absolutePath = dirPath;
|
|
if (!path.isAbsolute(dirPath)) {
|
|
const workspaceFolders = vscode.workspace.workspaceFolders;
|
|
if (workspaceFolders && workspaceFolders.length > 0) {
|
|
absolutePath = path.join(workspaceFolders[0].uri.fsPath, dirPath);
|
|
} else {
|
|
throw new Error(
|
|
"请先打开一个文件夹作为工作区,这样我就能为您创建目录了"
|
|
);
|
|
}
|
|
}
|
|
|
|
const dirUri = vscode.Uri.file(absolutePath);
|
|
|
|
// 检测创建目录是否存在
|
|
try {
|
|
const stat = await vscode.workspace.fs.stat(dirUri);
|
|
if (stat.type === vscode.FileType.Directory) {
|
|
throw new Error(`目录已存在: ${absolutePath}`);
|
|
} else {
|
|
throw new Error(`路径已存在且不是目录: ${absolutePath}`);
|
|
}
|
|
} catch (error: any) {
|
|
// 如果目录不存在,继续创建
|
|
if (error.code !== "FileNotFound") {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// 创建目录
|
|
await vscode.workspace.fs.createDirectory(dirUri);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 批量创建文件
|
|
*/
|
|
export async function createMultipleFiles(
|
|
files: { path: string; content: string }[]
|
|
): Promise<{ path: string; success: boolean; error?: string }[]> {
|
|
const results = [];
|
|
|
|
for (const file of files) {
|
|
try {
|
|
await createFile(file.path, file.content);
|
|
results.push({ path: file.path, success: true });
|
|
} catch (error) {
|
|
results.push({
|
|
path: file.path,
|
|
success: false,
|
|
error: error instanceof Error ? error.message : "未知错误",
|
|
});
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
// 删除文件
|
|
export async function deleteFile(filePath: string): Promise<void> {
|
|
try {
|
|
// 如果是相对路径,转换为绝对路径
|
|
let absolutePath = filePath;
|
|
if (!path.isAbsolute(filePath)) {
|
|
const workspaceFolders = vscode.workspace.workspaceFolders;
|
|
if (workspaceFolders && workspaceFolders.length > 0) {
|
|
absolutePath = path.join(workspaceFolders[0].uri.fsPath, filePath);
|
|
} else {
|
|
throw new Error(
|
|
"请先打开一个文件夹作为工作区,这样我就能为您删除文件了"
|
|
);
|
|
}
|
|
}
|
|
|
|
const fileUri = vscode.Uri.file(absolutePath);
|
|
|
|
// 检查文件是否存在
|
|
try {
|
|
const stat = await vscode.workspace.fs.stat(fileUri);
|
|
if (stat.type !== vscode.FileType.File) {
|
|
throw new Error(`路径不是文件: ${absolutePath}`);
|
|
}
|
|
} catch (error) {
|
|
throw new Error(`文件不存在: ${absolutePath}`);
|
|
}
|
|
|
|
// 删除文件
|
|
await vscode.workspace.fs.delete(fileUri);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// 修改文件内容(完全替换)
|
|
export async function updateFile(
|
|
filePath: string,
|
|
content: string
|
|
): Promise<void> {
|
|
try {
|
|
// 如果是相对路径,转换为绝对路径
|
|
let absolutePath = filePath;
|
|
if (!path.isAbsolute(filePath)) {
|
|
const workspaceFolders = vscode.workspace.workspaceFolders;
|
|
if (workspaceFolders && workspaceFolders.length > 0) {
|
|
absolutePath = path.join(workspaceFolders[0].uri.fsPath, filePath);
|
|
} else {
|
|
throw new Error(
|
|
"请先打开一个文件夹作为工作区,这样我就能为您修改文件了"
|
|
);
|
|
}
|
|
}
|
|
|
|
const fileUri = vscode.Uri.file(absolutePath);
|
|
|
|
// 检查文件是否存在
|
|
try {
|
|
const stat = await vscode.workspace.fs.stat(fileUri);
|
|
if (stat.type !== vscode.FileType.File) {
|
|
throw new Error(`路径不是文件: ${absolutePath}`);
|
|
}
|
|
} catch (error) {
|
|
throw new Error(`文件不存在: ${absolutePath}`);
|
|
}
|
|
|
|
// 修改文件内容
|
|
const contentBytes = Buffer.from(content, "utf-8");
|
|
await vscode.workspace.fs.writeFile(fileUri, contentBytes);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 追加文件内容
|
|
*/
|
|
export async function appendToFile(
|
|
filePath: string,
|
|
content: string
|
|
): Promise<void> {
|
|
try {
|
|
// 如果是相对路径,转换为绝对路径
|
|
let absolutePath = filePath;
|
|
if (!path.isAbsolute(filePath)) {
|
|
const workspaceFolders = vscode.workspace.workspaceFolders;
|
|
if (workspaceFolders && workspaceFolders.length > 0) {
|
|
absolutePath = path.join(workspaceFolders[0].uri.fsPath, filePath);
|
|
} else {
|
|
throw new Error(
|
|
"请先打开一个文件夹作为工作区,这样我就能为您追加文件内容了"
|
|
);
|
|
}
|
|
}
|
|
|
|
const fileUri = vscode.Uri.file(absolutePath);
|
|
|
|
// 检查文件是否存在并读取原内容
|
|
let existingContent = "";
|
|
try {
|
|
const contentBytes = await vscode.workspace.fs.readFile(fileUri);
|
|
existingContent = Buffer.from(contentBytes).toString("utf-8");
|
|
} catch (error) {
|
|
throw new Error(`文件不存在: ${absolutePath}`);
|
|
}
|
|
|
|
// 追加内容
|
|
const newContent = existingContent + content;
|
|
const contentBytes = Buffer.from(newContent, "utf-8");
|
|
await vscode.workspace.fs.writeFile(fileUri, contentBytes);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// 部分修改文件内容(查找替换)
|
|
export async function replaceFile(
|
|
filePath: string,
|
|
searchValue: string | RegExp,
|
|
replaceValue: string
|
|
): Promise<void> {
|
|
try {
|
|
// 如果是相对路径,转换为绝对路径
|
|
let absolutePath = filePath;
|
|
if (!path.isAbsolute(filePath)) {
|
|
const workspaceFolders = vscode.workspace.workspaceFolders;
|
|
if (workspaceFolders && workspaceFolders.length > 0) {
|
|
absolutePath = path.join(workspaceFolders[0].uri.fsPath, filePath);
|
|
} else {
|
|
throw new Error(
|
|
"请先打开一个文件夹作为工作区,这样我就能为您修改文件了"
|
|
);
|
|
}
|
|
}
|
|
|
|
const fileUri = vscode.Uri.file(absolutePath);
|
|
|
|
// 读取文件内容
|
|
let fileContent: string;
|
|
try {
|
|
const contentBytes = await vscode.workspace.fs.readFile(fileUri);
|
|
fileContent = Buffer.from(contentBytes).toString("utf-8");
|
|
} catch (error) {
|
|
throw new Error(`文件不存在: ${absolutePath}`);
|
|
}
|
|
|
|
// 转义特殊字符,将字符串作为字面量处理
|
|
const escapeRegExp = (str: string) => {
|
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
};
|
|
|
|
// 替换内容 - 如果是字符串,先转义特殊字符
|
|
let newContent: string;
|
|
if (typeof searchValue === "string") {
|
|
const escapedSearch = escapeRegExp(searchValue);
|
|
newContent = fileContent.replace(
|
|
new RegExp(escapedSearch, "g"),
|
|
replaceValue
|
|
);
|
|
} else {
|
|
newContent = fileContent.replace(searchValue, replaceValue);
|
|
}
|
|
|
|
// 检查是否有内容被替换
|
|
if (fileContent === newContent) {
|
|
throw new Error(`未找到要替换的内容: ${searchValue}`);
|
|
}
|
|
|
|
// 写回文件
|
|
const contentBytes = Buffer.from(newContent, "utf-8");
|
|
await vscode.workspace.fs.writeFile(fileUri, contentBytes);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// 在指定位置插入内容
|
|
export async function insertAtLine(
|
|
filePath: string,
|
|
lineNumber: number,
|
|
content: string
|
|
): Promise<void> {
|
|
try {
|
|
// 如果是相对路径,转换为绝对路径
|
|
let absolutePath = filePath;
|
|
if (!path.isAbsolute(filePath)) {
|
|
const workspaceFolders = vscode.workspace.workspaceFolders;
|
|
if (workspaceFolders && workspaceFolders.length > 0) {
|
|
absolutePath = path.join(workspaceFolders[0].uri.fsPath, filePath);
|
|
} else {
|
|
throw new Error(
|
|
"请先打开一个文件夹作为工作区,这样我就能为您修改文件了"
|
|
);
|
|
}
|
|
}
|
|
|
|
const fileUri = vscode.Uri.file(absolutePath);
|
|
|
|
// 读取文件内容
|
|
let fileContent: string;
|
|
try {
|
|
const contentBytes = await vscode.workspace.fs.readFile(fileUri);
|
|
fileContent = Buffer.from(contentBytes).toString("utf-8");
|
|
} catch (error) {
|
|
throw new Error(`文件不存在: ${absolutePath}`);
|
|
}
|
|
|
|
const lines = fileContent.split("\n");
|
|
|
|
// 插入内容
|
|
lines.splice(lineNumber, 0, content);
|
|
|
|
// 写回文件
|
|
const newContent = lines.join("\n");
|
|
const newContentBytes = Buffer.from(newContent, "utf-8");
|
|
await vscode.workspace.fs.writeFile(fileUri, newContentBytes);
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 重命名文件
|
|
*/
|
|
export async function renameFile(
|
|
oldPath: string,
|
|
newPath: string
|
|
): Promise<void> {
|
|
try {
|
|
// 如果是相对路径,转换为绝对路径
|
|
let absoluteOldPath = oldPath;
|
|
let absoluteNewPath = newPath;
|
|
const workspaceFolders = vscode.workspace.workspaceFolders;
|
|
if (workspaceFolders && workspaceFolders.length > 0) {
|
|
const workspaceRoot = workspaceFolders[0].uri.fsPath;
|
|
|
|
if (!path.isAbsolute(oldPath)) {
|
|
absoluteOldPath = path.join(workspaceRoot, oldPath);
|
|
}
|
|
|
|
if (!path.isAbsolute(newPath)) {
|
|
absoluteNewPath = path.join(workspaceRoot, newPath);
|
|
}
|
|
} else {
|
|
throw new Error(
|
|
"请先打开一个文件夹作为工作区,这样我就能为您重命名文件了"
|
|
);
|
|
}
|
|
|
|
const oldUri = vscode.Uri.file(absoluteOldPath);
|
|
const newUri = vscode.Uri.file(absoluteNewPath);
|
|
|
|
// 检查原文件是否存在
|
|
try {
|
|
await vscode.workspace.fs.stat(oldUri);
|
|
} catch (error) {
|
|
throw new Error(`文件不存在: ${absoluteOldPath}`);
|
|
}
|
|
|
|
// 检查新文件名是否已存在
|
|
try {
|
|
await vscode.workspace.fs.stat(newUri);
|
|
throw new Error(`目标文件已存在: ${absoluteNewPath}`);
|
|
} catch (error: any) {
|
|
// 如果文件不存在,继续重命名
|
|
if (
|
|
error.code !== "FileNotFound" &&
|
|
!error.message.includes("目标文件已存在")
|
|
) {
|
|
throw error;
|
|
}
|
|
if (error.message.includes("目标文件已存在")) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// 确保目标目录存在
|
|
const newDir = path.dirname(absoluteNewPath);
|
|
const newDirUri = vscode.Uri.file(newDir);
|
|
try {
|
|
await vscode.workspace.fs.stat(newDirUri);
|
|
} catch {
|
|
await vscode.workspace.fs.createDirectory(newDirUri);
|
|
}
|
|
|
|
// 重命名文件
|
|
await vscode.workspace.fs.rename(oldUri, newUri, { overwrite: false });
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|