我不知道的 VSCode 扩展:高级 API 技巧
引言
🌟 在前面的系列文章中,我们已经学习了 VSCode 扩展开发的基础知识、用户界面、常用 API、生命周期、调试、发布和 CI/CD。现在,我们将深入探索 VSCode 扩展开发中的高级 API 技巧,学习如何利用更强大、更灵活的 API 来构建更复杂、更智能、更用户友好的 VSCode 扩展。掌握这些高级 API 技巧,将使你的扩展开发能力更上一层楼,让你能够创造出真正令人惊艳的 VSCode 扩展!现在,就让我们一起开启 VSCode 高级 API 的探索之旅!
高级 API 技巧
🚀 VSCode 提供了非常丰富的 API,除了我们之前介绍的常用 API 外,还有许多高级 API 可以帮助我们实现更复杂的功能。本节将介绍一些常用的高级 API 技巧,包括:
1. Workspace API:多工作区支持
📂 Workspace API 允许扩展与 VSCode 的工作区进行交互,包括获取工作区信息、监听工作区事件、管理工作区文件夹等。多工作区 (Multi-root Workspace) 是 VSCode 的一个重要特性,允许用户在同一个 VSCode 窗口中打开多个项目文件夹。如果你的扩展需要支持多工作区,或者需要根据不同的工作区文件夹执行不同的操作,Workspace API 将非常有用。
vscode.workspace.workspaceFolders
: 获取当前工作区的所有文件夹。返回一个WorkspaceFolder[]
数组,每个WorkspaceFolder
对象包含文件夹的uri
(URI 对象) 和name
(文件夹名称)。vscode.workspace.onDidChangeWorkspaceFolders
: 监听工作区文件夹变化事件。当用户添加、移除或移动工作区文件夹时,该事件会触发。vscode.workspace.getWorkspaceFolder(uri)
: 根据给定的 URI,获取该 URI 所属的工作区文件夹。vscode.workspace.findFiles(globPattern, ignoreGlobPattern?, maxResults?, token?)
: 在工作区中查找文件。可以使用 Glob 模式匹配文件路径,支持排除模式、最大结果数和取消令牌。vscode.workspace.createFileSystemWatcher(globPattern, ignoreGlobPattern?, ignoreChangeEvents?, ignoreCreateEvents?, ignoreDeleteEvents?)
: 创建文件系统监视器,监听文件变化事件。可以监听文件创建、修改、删除事件,并使用 Glob 模式过滤文件。
示例:根据不同的工作区文件夹显示不同的视图
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
vscode.window.registerTreeDataProvider('myWorkspaceView', {
getChildren: (element?: vscode.WorkspaceFolder) => {
if (!vscode.workspace.workspaceFolders) {
return Promise.resolve([]);
}
if (!element) {
// 根节点,显示工作区文件夹
return Promise.resolve(vscode.workspace.workspaceFolders);
} else {
// 子节点,显示文件夹下的文件 (这里只是示例,实际应用中可以根据需要显示不同的内容)
return vscode.workspace.findFiles(`**/*`, undefined, undefined).then(files => {
return files.filter(file => vscode.workspace.getWorkspaceFolder(file) === element);
});
}
},
getTreeItem: (element: vscode.WorkspaceFolder | vscode.Uri) => {
if (element instanceof vscode.WorkspaceFolder) {
// 工作区文件夹节点
return new vscode.TreeItem(element.name, vscode.TreeItemCollapsibleState.Collapsed);
} else {
// 文件节点
return new vscode.TreeItem(vscode.workspace.asRelativePath(element));
}
}
});
}
2. Document API:深入文本编辑
📝 Document API 允许扩展深入控制文本编辑器,包括获取和修改文档内容、管理文本选择、插入和删除文本、应用文本装饰器 (Decorations) 等。如果你需要开发代码编辑器增强功能、代码格式化工具、代码片段扩展等,Document API 将是你的利器。
vscode.window.activeTextEditor
: 获取当前激活的文本编辑器。vscode.window.visibleTextEditors
: 获取当前所有可见的文本编辑器。vscode.TextEditor.document
: 获取文本编辑器关联的TextDocument
对象,表示文档内容。vscode.TextDocument.getText(range?)
: 获取文档的文本内容,可以指定范围。vscode.TextDocument.lineCount
: 获取文档的行数。vscode.TextDocument.lineAt(lineNumber)
: 获取指定行的TextLine
对象,包含行的文本内容、行号、Range 等信息。vscode.TextEditor.selection
: 获取和设置文本编辑器的当前选择区域 (Selection
对象)。vscode.TextEditor.selections
: 获取和设置文本编辑器的多光标选择区域 (Selection[]
数组)。vscode.TextEditor.edit(editBuilder)
: 应用文本编辑操作。使用TextEditorEdit
对象构建编辑操作,例如插入文本、替换文本、删除文本等。vscode.TextEditor.setDecorations(decorationType, rangesOrOptions)
: 应用文本装饰器。可以使用DecorationOptions
或Range
数组指定装饰范围和样式,例如高亮显示、添加下划线、添加边框等。vscode.TextEditor.revealRange(range, revealType?)
: 滚动编辑器,使指定的 Range 可见。
示例:实现一个简单的代码高亮扩展
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
let activeEditor = vscode.window.activeTextEditor;
let decorationType = vscode.window.createTextEditorDecorationType({
backgroundColor: 'rgba(255, 255, 0, 0.2)',
border: '1px solid yellow'
});
function updateDecorations() {
if (!activeEditor) {
return;
}
const text = activeEditor.document.getText();
const decorations: vscode.DecorationOptions[] = [];
let match;
const regEx = /vscode/gi; // 匹配 "vscode" 关键词 (忽略大小写)
while ((match = regEx.exec(text))) {
const startPos = activeEditor.document.positionAt(match.index);
const endPos = activeEditor.document.positionAt(match.index + match[0].length);
const decoration = { range: new vscode.Range(startPos, endPos), hoverMessage: '关键词 **vscode**' };
decorations.push(decoration);
}
activeEditor.setDecorations(decorationType, decorations);
}
function triggerUpdateDecorations(throttle = false) {
if (throttle) {
clearTimeout(timeout);
timeout = setTimeout(updateDecorations, 500);
} else {
updateDecorations();
}
}
let timeout: NodeJS.Timer | undefined;
vscode.window.onDidChangeActiveTextEditor(editor => {
activeEditor = editor;
if (editor) {
triggerUpdateDecorations();
}
}, null, context.subscriptions);
vscode.workspace.onDidChangeTextDocument(event => {
if (activeEditor && event.document === activeEditor.document) {
triggerUpdateDecorations(true);
}
}, null, context.subscriptions);
if (activeEditor) {
triggerUpdateDecorations();
}
}
3. Language Server Protocol (LSP) 客户端 API
🗣️ Language Server Protocol (LSP) 是一种标准化的协议,用于在代码编辑器和语言服务器之间进行通信,实现代码智能功能,例如自动补全、代码导航、错误检查、代码格式化等。VSCode 内置了 LSP 客户端,并提供了 LSP 客户端 API,允许扩展与语言服务器进行交互,或者实现自定义的语言客户端。如果你需要开发语言支持扩展,或者需要与现有的语言服务器集成,LSP 客户端 API 将非常有用。
vscode.languages.registerLanguageClient(clientOptions)
: 注册语言客户端。clientOptions
是一个LanguageClientOptions
对象,用于配置语言客户端的各种选项,例如语言 ID、服务器选项、客户端能力等。vscode.languages.getLanguageClient(languageId)
: 根据语言 ID 获取已注册的语言客户端。vscode.LanguageClient
: 语言客户端类,提供了与语言服务器通信的方法,例如发送请求、发送通知、监听事件等。
示例:注册一个简单的语言客户端 (假设已经有一个运行中的语言服务器)
import * as vscode from 'vscode';
import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient/node';
let client: LanguageClient;
export function activate(context: vscode.ExtensionContext) {
// 语言服务器模块的路径
const serverModule = context.asAbsolutePath('server/server.js');
// 调试模式下,使用 TCP 传输
const debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] };
// 服务器选项
const serverOptions: ServerOptions = {
run: { module: serverModule, transport: TransportKind.ipc },
debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions }
};
// 客户端选项
const clientOptions: LanguageClientOptions = {
documentSelector: [{ scheme: 'file', language: 'plaintext' }], // 关联的文档类型
synchronize: {
configurationSection: 'plaintextLanguageServer', // 同步配置
fileEvents: vscode.workspace.createFileSystemWatcher('**/.clientrc') // 监听文件变化
}
};
// 创建语言客户端
client = new LanguageClient('plaintextLanguageServer', 'Plain Text Language Server', serverOptions, clientOptions);
// 启动语言客户端
client.start();
}
export function deactivate(): Thenable<void> | undefined {
if (!client) {
return undefined;
}
return client.stop();
}
4. Debug API:程序化控制调试器
🐞 Debug API 允许扩展程序化地控制 VSCode 的调试器,包括启动调试会话、设置断点、控制调试执行、获取调试状态等。如果你需要开发自定义的调试器扩展、或者需要在扩展中集成调试功能,Debug API 将非常有用。
vscode.debug.startDebugging(folder, nameOrConfiguration, parentSession)
: 启动调试会话。可以指定工作区文件夹、调试配置名称或配置对象、父调试会话。vscode.debug.activeDebugSession
: 获取当前激活的调试会话。vscode.debug.activeDebugSessions
: 获取当前所有激活的调试会话。vscode.debug.onDidStartDebugSession
: 监听调试会话启动事件.vscode.debug.onDidTerminateDebugSession
: 监听调试会话结束事件。vscode.debug.onDidReceiveDebugSessionCustomEvent
: 监听调试会话自定义事件。vscode.debug.breakpoints
: 获取和设置全局断点 (Breakpoint[]
数组)。vscode.debug.addBreakpoints(breakpoints)
: 添加断点。vscode.debug.removeBreakpoints(breakpoints)
: 移除断点。
示例:扩展中启动调试会话
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
let disposable = vscode.commands.registerCommand('extension.startDebugger', () => {
vscode.debug.startDebugging(undefined, 'node-configuration'); // 启动名为 "node-configuration" 的调试配置
});
context.subscriptions.push(disposable);
}
5. Task API:集成任务系统
🚀 Task API 允许扩展与 VSCode 的任务系统集成,创建和管理任务,例如构建任务、测试任务、部署任务等。VSCode 的任务系统允许用户在 VSCode 中运行外部命令和脚本,并与编辑器集成,例如在 "终端" 面板中显示任务输出、在 "问题" 面板中显示任务错误和警告等。如果你需要扩展提供自定义的任务,或者需要与现有的构建工具或任务运行器集成,Task API 将非常有用。
vscode.tasks.registerTaskProvider(taskDefinition, provider)
: 注册任务提供器。任务提供器负责提供任务。vscode.tasks.fetchTasks(filter?)
: 获取所有可用的任务,可以根据任务类型、任务定义等条件进行过滤。vscode.tasks.executeTask(task)
: 执行任务。vscode.tasks.onDidStartTask
: 监听任务启动事件。vscode.tasks.onDidEndTask
: 监听任务结束事件。vscode.tasks.onDidStartTaskProcess
: 监听任务进程启动事件。vscode.tasks.onDidEndTaskProcess
: 监听任务进程结束事件。
示例:注册一个简单的任务提供器
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
vscode.tasks.registerTaskProvider('myTaskType', {
provideTasks(token?: vscode.CancellationToken): vscode.ProviderResult<vscode.Task[]> {
const taskDefinition: vscode.TaskDefinition = { type: 'myTaskType' };
const task = new vscode.Task(taskDefinition, vscode.TaskScope.Workspace, 'My Task', 'my-extension');
task.execution = new vscode.ShellExecution('echo Hello from My Task'); // 任务执行的命令
task.problemMatchers = ["$jshint"]; // 问题匹配器 (可选)
return [task];
},
resolveTask(task: vscode.Task, token?: vscode.CancellationToken): vscode.ProviderResult<vscode.Task> {
return task;
}
});
}
6. Terminal API:集成终端
💻 Terminal API 允许扩展与 VSCode 的集成终端进行交互,包括创建和管理终端、发送命令到终端、接收终端输出、监听终端事件等。如果你需要扩展提供与终端交互的功能,例如运行命令、监控进程、自动化终端操作等,Terminal API 将非常有用。
vscode.window.createTerminal(options?)
: 创建终端。可以指定终端名称、shell 路径、环境变量、工作目录等选项。vscode.window.terminals
: 获取当前所有已创建的终端 (Terminal[]
数组)。vscode.window.activeTerminal
: 获取当前激活的终端。vscode.window.onDidOpenTerminal
: 监听终端打开事件。vscode.window.onDidCloseTerminal
: 监听终端关闭事件。vscode.Terminal.show(preserveFocus?)
: 显示终端。vscode.Terminal.hide()
: 隐藏终端。vscode.Terminal.sendText(text, addNewLine?)
: 发送文本到终端。vscode.Terminal.dispose()
: 销毁终端。
示例:扩展中创建并发送命令到终端
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
let disposable = vscode.commands.registerCommand('extension.runCommandInTerminal', () => {
const terminal = vscode.window.createTerminal('My Terminal'); // 创建名为 "My Terminal" 的终端
terminal.show(); // 显示终端
terminal.sendText('echo Hello from VSCode Extension'); // 发送命令到终端
});
context.subscriptions.push(disposable);
}
7. Webview API (高级):更强大的 Webview 功能
🌐 Webview API 除了之前介绍的基本功能外,还提供了更高级的功能,例如:
WebviewPanel.reveal(viewColumn?, preserveFocus?)
: 显示 Webview 面板,并可以控制是否保留焦点。WebviewPanel.webview.asWebviewUri(localResource)
: 将本地资源 (例如 HTML 文件、CSS 文件、JS 文件、图片文件) 转换为 Webview 可访问的 URI。在 Webview 中加载本地资源时,必须使用asWebviewUri
转换 URI,以确保 Webview 能够正确加载资源,并防止安全问题。WebviewPanel.webview.cspSource
: 获取 Webview 的内容安全策略 (CSP) 源。在 Webview 中使用内联 JavaScript 或 CSS 时,需要配置 CSP,以确保安全。WebviewPanel.onDidChangeViewState
: 监听 Webview 面板的视图状态变化事件,例如 Webview 是否可见、是否激活等。Webview.postMessage(message)
: 从扩展代码向 Webview 发送消息。Webview.onDidReceiveMessage
: 监听从 Webview 发送的消息。
示例:在 Webview 中加载本地 HTML 文件并使用 asWebviewUri
转换 URI
import * as vscode from 'vscode';
import * as path from 'path';
export function activate(context: vscode.ExtensionContext) {
let disposable = vscode.commands.registerCommand('extension.openWebview', () => {
const panel = vscode.window.createWebviewPanel(
'myWebview', // Webview ID
'My Webview', // Webview 标题
vscode.ViewColumn.One, // 在编辑器的哪个列中显示 Webview
{
enableScripts: true, // 启用 JavaScript
localResourceRoots: [context.extensionUri] // 允许加载本地资源的根路径
}
);
// 加载本地 HTML 文件
const htmlPath = path.join(context.extensionPath, 'webview', 'index.html');
const htmlUri = vscode.Uri.file(htmlPath);
const webviewUri = panel.webview.asWebviewUri(htmlUri); // 转换为 Webview URI
panel.webview.html = `<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Webview</title>
</head>
<body>
<h1>Hello from Webview!</h1>
<img src="${webviewUri}" /> // 使用转换后的 Webview URI
</body>
</html>`;
});
context.subscriptions.push(disposable);
}
总结
🎉 恭喜你,完成了 VSCode 扩展高级 API 技巧的学习!本文介绍了 Workspace API、Document API、LSP 客户端 API、Debug API、Task API、Terminal API 和 Webview API 等高级 API 技巧,并提供了丰富的示例代码。掌握这些高级 API 技巧,将使你能够开发出更强大、更智能、更用户友好的 VSCode 扩展,满足更复杂的需求。在实际开发中,不断探索和实践这些高级 API,结合你的创意和需求,相信你一定能够创造出令人惊艳的 VSCode 扩展,为 VSCode 社区贡献更多优秀的作品!