1.0.2 优化打开逻辑
This commit is contained in:
@@ -3,6 +3,57 @@ import { FileModel, FileEntry } from './model';
|
||||
import { FileProvider } from './provider';
|
||||
import { FunctionExtractor } from './functionExtractor';
|
||||
|
||||
// 查找已打开的文档
|
||||
function findExistingDocument(filePath: string): vscode.TextDocument | undefined {
|
||||
const documents = vscode.workspace.textDocuments;
|
||||
for (const doc of documents) {
|
||||
if (doc.uri.scheme === 'squirrel' && doc.uri.path === `/${filePath}`) {
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// 打开文件的通用函数
|
||||
async function openFile(model: FileModel, provider: FileProvider, entry: FileEntry): Promise<void> {
|
||||
if (!model.getIsConnected()) {
|
||||
vscode.window.showErrorMessage('请先连接到 pvfUtility API');
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否已经有相同的文件打开
|
||||
const existingDocument = findExistingDocument(entry.key);
|
||||
if (existingDocument) {
|
||||
// 如果文件已打开,则聚焦到该标签页
|
||||
await vscode.window.showTextDocument(existingDocument);
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果文件未打开,则在新标签页中打开
|
||||
try {
|
||||
await vscode.window.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: `正在加载文件 ${entry.name}...`,
|
||||
cancellable: false
|
||||
}, async (progress) => {
|
||||
const content = await model.getFileContent(entry.key);
|
||||
|
||||
if (content !== undefined) {
|
||||
// 创建虚拟文档,使用时间戳确保URI唯一以支持多标签页
|
||||
const timestamp = Date.now();
|
||||
const uri = vscode.Uri.parse(`squirrel:/${entry.key}?instance=${timestamp}`);
|
||||
const doc = await vscode.workspace.openTextDocument(uri);
|
||||
await vscode.window.showTextDocument(doc, { preview: false });
|
||||
provider.refresh();
|
||||
} else {
|
||||
vscode.window.showErrorMessage(`加载文件 ${entry.name} 失败`);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(`打开文件失败: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function registerCommands(context: vscode.ExtensionContext, model: FileModel, provider: FileProvider, functionExtractor: FunctionExtractor, output?: vscode.OutputChannel) {
|
||||
// 连接到 API
|
||||
console.log('注册 squirrel.connectToApi 命令...');
|
||||
@@ -63,34 +114,9 @@ export function registerCommands(context: vscode.ExtensionContext, model: FileMo
|
||||
}
|
||||
});
|
||||
|
||||
// 打开文件
|
||||
// 打开文件(单击或双击文件时调用)
|
||||
const openFileCommand = vscode.commands.registerCommand('squirrel.openFile', async (entry: FileEntry) => {
|
||||
if (!model.getIsConnected()) {
|
||||
vscode.window.showErrorMessage('请先连接到 pvfUtility API');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await vscode.window.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: `正在加载文件 ${entry.name}...`,
|
||||
cancellable: false
|
||||
}, async (progress) => {
|
||||
const content = await model.getFileContent(entry.key);
|
||||
|
||||
if (content !== undefined) {
|
||||
// 创建虚拟文档
|
||||
const uri = vscode.Uri.parse(`squirrel:/${entry.key}`);
|
||||
const doc = await vscode.workspace.openTextDocument(uri);
|
||||
await vscode.window.showTextDocument(doc);
|
||||
provider.refresh();
|
||||
} else {
|
||||
vscode.window.showErrorMessage(`加载文件 ${entry.name} 失败`);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(`打开文件失败: ${error}`);
|
||||
}
|
||||
await openFile(model, provider, entry);
|
||||
});
|
||||
|
||||
// 保存文件(通过 VS Code 的保存事件处理,这个命令主要用于显示)
|
||||
|
||||
@@ -116,6 +116,9 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
isCaseSensitive: true
|
||||
});
|
||||
|
||||
// 将 fileSystemProvider 添加到 context 以便在 commands 中使用
|
||||
(global as any).fileSystemProvider = fileSystemProvider;
|
||||
|
||||
// 注册所有命令
|
||||
console.log('正在注册命令...');
|
||||
registerCommands(context, model, provider, functionExtractor, output);
|
||||
@@ -147,7 +150,14 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
}
|
||||
});
|
||||
|
||||
context.subscriptions.push(configChangeListener, saveListener);
|
||||
// 注册文件关闭事件以清理缓存
|
||||
const closeListener = vscode.workspace.onDidCloseTextDocument((doc) => {
|
||||
if (doc.uri.scheme === 'squirrel') {
|
||||
fileSystemProvider.clearFileCache(doc.uri);
|
||||
}
|
||||
});
|
||||
|
||||
context.subscriptions.push(configChangeListener, saveListener, closeListener);
|
||||
|
||||
output.appendLine('[Squirrel] 扩展激活完成');
|
||||
output.show();
|
||||
|
||||
@@ -5,6 +5,8 @@ export class SquirrelFileSystemProvider implements vscode.FileSystemProvider {
|
||||
private model: FileModel;
|
||||
private _onDidChangeFile = new vscode.EventEmitter<vscode.FileChangeEvent[]>();
|
||||
onDidChangeFile = this._onDidChangeFile.event;
|
||||
// 存储文件实例内容,支持多标签页
|
||||
private fileContentCache = new Map<string, string>();
|
||||
|
||||
constructor(model: FileModel) {
|
||||
this.model = model;
|
||||
@@ -13,12 +15,24 @@ export class SquirrelFileSystemProvider implements vscode.FileSystemProvider {
|
||||
// 读取文件
|
||||
async readFile(uri: vscode.Uri): Promise<Uint8Array> {
|
||||
const filePath = this.getPathFromUri(uri);
|
||||
|
||||
// 检查是否有缓存的内容(用于多标签页支持)
|
||||
const cacheKey = uri.toString();
|
||||
if (this.fileContentCache.has(cacheKey)) {
|
||||
const content = this.fileContentCache.get(cacheKey)!;
|
||||
return new TextEncoder().encode(content);
|
||||
}
|
||||
|
||||
// 从模型获取内容
|
||||
const content = await this.model.getFileContent(filePath);
|
||||
|
||||
if (content === undefined) {
|
||||
throw vscode.FileSystemError.FileNotFound(uri);
|
||||
}
|
||||
|
||||
// 缓存内容以支持多标签页
|
||||
this.fileContentCache.set(cacheKey, content);
|
||||
|
||||
return new TextEncoder().encode(content);
|
||||
}
|
||||
|
||||
@@ -27,6 +41,10 @@ export class SquirrelFileSystemProvider implements vscode.FileSystemProvider {
|
||||
const filePath = this.getPathFromUri(uri);
|
||||
const textContent = new TextDecoder().decode(content);
|
||||
|
||||
// 更新缓存内容
|
||||
const cacheKey = uri.toString();
|
||||
this.fileContentCache.set(cacheKey, textContent);
|
||||
|
||||
const success = await this.model.saveFileContent(filePath, textContent);
|
||||
|
||||
if (!success) {
|
||||
@@ -36,11 +54,19 @@ export class SquirrelFileSystemProvider implements vscode.FileSystemProvider {
|
||||
|
||||
// 其他必须实现的方法(简化实现)
|
||||
stat(uri: vscode.Uri): vscode.FileStat {
|
||||
// 获取文件内容以确定大小
|
||||
const cacheKey = uri.toString();
|
||||
let content = '';
|
||||
|
||||
if (this.fileContentCache.has(cacheKey)) {
|
||||
content = this.fileContentCache.get(cacheKey)!;
|
||||
}
|
||||
|
||||
return {
|
||||
type: vscode.FileType.File,
|
||||
ctime: Date.now(),
|
||||
mtime: Date.now(),
|
||||
size: 0
|
||||
size: Buffer.byteLength(content, 'utf8')
|
||||
};
|
||||
}
|
||||
|
||||
@@ -64,11 +90,23 @@ export class SquirrelFileSystemProvider implements vscode.FileSystemProvider {
|
||||
return new vscode.Disposable(() => {});
|
||||
}
|
||||
|
||||
// 清理文件缓存
|
||||
clearFileCache(uri: vscode.Uri): void {
|
||||
const cacheKey = uri.toString();
|
||||
this.fileContentCache.delete(cacheKey);
|
||||
}
|
||||
|
||||
// 从 URI 解析文件路径
|
||||
private getPathFromUri(uri: vscode.Uri): string {
|
||||
if (uri.scheme !== 'squirrel') {
|
||||
throw vscode.FileSystemError.FileNotFound(uri);
|
||||
}
|
||||
// 移除查询参数,只返回路径部分
|
||||
return uri.path.substring(1); // 去掉开头的 '/'
|
||||
}
|
||||
|
||||
// 获取文件实例ID
|
||||
private getInstanceId(uri: vscode.Uri): string {
|
||||
return uri.query ? new URLSearchParams(uri.query).get('instance') || 'default' : 'default';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user