你的第一个扩展
在本主题中,我们将教你构建扩展的基本概念。确保你已安装 Node.js 和 Git。
首先,使用 Yeoman 和 VS Code 扩展生成器搭建一个准备好进行开发的 TypeScript 或 JavaScript 项目。
- 如果你不想为以后使用安装 Yeoman,请运行以下命令:
npx --package yo --package generator-code -- yo code
- 如果你想全局安装 Yeoman 以便于重复运行,请运行以下命令:
npm install --global yo generator-code yo code
对于 TypeScript 项目,填写以下字段:
_-----_ ╭──────────────────────────╮ | | │ Welcome to the Visual │ |--(o)--| │ Studio Code Extension │ `---------´ │ generator! │ ( _´U`_ ) ╰──────────────────────────╯ /___A___\ / | ~ | __'.___.'__ ´ ` |° ´ Y ` ? What type of extension do you want to create? New Extension (TypeScript) ? What's the name of your extension? HelloWorld ? What's the identifier of your extension? helloworld ? What's the description of your extension? ? Initialize a git repository? Yes ? Which bundler to use? unbundled ? Which package manager to use? pnpm
在编辑器中,打开 src/extension.ts 并按 F5 或从命令面板运行 Debug: Start Debugging 命令(⇧⌘P (Windows, Linux Ctrl+Shift+P))。这将编译扩展并在新的 扩展开发宿主 窗口中运行它。
在新窗口中从命令面板(⇧⌘P (Windows, Linux Ctrl+Shift+P))运行 Hello World 命令:
你应该会看到 Hello World from HelloWorld! 通知显示出来。成功!
如果你在调试窗口中看不到 Hello World 命令,请检查 package.json 文件并确保 engines.vscode 版本与已安装的 VS Code 版本兼容。
开发扩展
让我们对消息进行修改:
- 在
extension.ts中将消息从 “Hello World from HelloWorld!” 更改为 “Hello VS Code”。 - 在新窗口中运行 Developer: Reload Window。
- 再次运行 Hello World 命令。
你应该会看到更新后的消息显示出来。
以下是一些你可以尝试的想法:
- 在命令面板中为 Hello World 命令提供一个新名称。
- 贡献另一个在信息消息中显示当前时间的命令。贡献点是你在
package.json扩展清单中做出的静态声明,用于扩展 VS Code,例如向你的扩展添加命令、菜单或键绑定。 - 用另一个 VS Code API 调用替换
vscode.window.showInformationMessage以显示警告消息。
调试扩展
VS Code 的内置调试功能使调试扩展变得容易。通过点击行旁边的装订线设置断点,VS Code 将命中断点。你可以在编辑器中悬停在变量上或使用左侧的 运行和调试 视图来检查变量的值。调试控制台允许你评估表达式。
你可以在 Node.js 调试主题中了解更多关于在 VS Code 中调试 Node.js 应用的信息。
下一步
在下一个主题”扩展剖析”中,我们将仔细查看 Hello World 示例的源代码并解释关键概念。
你可以在以下位置找到本教程的源代码:helloworld-sample。扩展指南主题包含其他示例,每个示例都展示了不同的 VS Code API 或贡献点,并遵循我们的 UX 指南中的建议。
使用 JavaScript
在本指南中,我们主要描述如何使用 TypeScript 开发 VS Code 扩展,因为我们认为 TypeScript 为开发 VS Code 扩展提供了最佳体验。然而,如果你更喜欢 JavaScript,你仍然可以使用 helloworld-minimal-sample 跟随学习。
UX 指南
现在也是查看我们的 UX 指南的好时机,这样你就可以开始设计你的扩展用户界面,遵循 VS Code 最佳实践。
扩展剖析
在上一个主题中,你已经能够运行一个基本的扩展。它在底层是如何工作的呢?
Hello World 扩展做了3件事:
- 注册 onCommand 激活事件:
onCommand:helloworld.helloWorld,这样当用户运行Hello World命令时扩展就会被激活。
注意: 从 VS Code 1.74.0 开始,在
package.json的commands部分声明的命令会在调用时自动激活扩展,而不需要在activationEvents中显式添加onCommand条目。
- 使用 contributes.commands 贡献点 使
Hello World命令在命令面板中可用,并将其绑定到命令IDhelloworld.helloWorld。 - 使用 commands.registerCommand VS Code API 将一个函数绑定到已注册的命令ID
helloworld.helloWorld。
理解这三个概念对于在 VS Code 中编写扩展至关重要:
- 激活事件:使你的扩展变为活动状态的事件。
- 贡献点:你在
package.json扩展清单中声明的静态声明,用于扩展 VS Code。 - VS Code API:一组你可以在扩展代码中调用的 JavaScript API。
一般来说,你的扩展会使用贡献点和 VS Code API 的组合来扩展 VS Code 的功能。扩展功能概述主题可以帮助你为扩展找到合适的贡献点和 VS Code API。
让我们仔细看看 Hello World 示例的源代码,看看这些概念如何应用于它。
扩展文件结构
. ├── .vscode │ ├── launch.json // 启动和调试扩展的配置 │ └── tasks.json // 编译 TypeScript 的构建任务配置 ├── .gitignore // 忽略构建输出和 node_modules ├── README.md // 扩展功能的可读描述 ├── src │ └── extension.ts // 扩展源代码 ├── package.json // 扩展清单 ├── tsconfig.json // TypeScript 配置
你可以阅读更多关于配置文件的信息:
launch.json用于配置 VS Code 调试tasks.json用于定义 VS Code 任务tsconfig.json请参考 TypeScript 手册
然而,让我们专注于 package.json 和 extension.ts,它们对理解 Hello World 扩展至关重要。
扩展清单
每个 VS Code 扩展都必须有一个 package.json 作为其扩展清单。package.json 包含 Node.js 字段如 scripts 和 devDependencies,以及 VS Code 特定字段如 publisher、activationEvents 和 contributes。你可以在扩展清单参考中找到所有 VS Code 特定字段的描述。以下是一些最重要的字段:
name和publisher:VS Code 使用<publisher>.<name>作为扩展的唯一 ID。例如,Hello World 示例的 ID 是vscode-samples.helloworld-sample。VS Code 使用 ID 唯一标识你的扩展。main:扩展入口点。activationEvents和contributes:激活事件和贡献点。engines.vscode:这指定了扩展所依赖的 VS Code API 的最低版本。
{ "name": "helloworld-sample", "displayName": "helloworld-sample", "description": "HelloWorld example for VS Code", "version": "0.0.1", "publisher": "vscode-samples", "repository": "https://github.com/microsoft/vscode-extension-samples/helloworld-sample", "engines": { "vscode": "^1.51.0" }, "categories": ["Other"], "activationEvents": [], "main": "./out/extension.js", "contributes": { "commands": [ { "command": "helloworld.helloWorld", "title": "Hello World" } ] }, "scripts": { "vscode:prepublish": "npm run compile", "compile": "tsc -p ./", "watch": "tsc -watch -p ./" }, "devDependencies": { "@types/node": "^8.10.25", "@types/vscode": "^1.51.0", "tslint": "^5.16.0", "typescript": "^3.4.5" } }
注意:如果你的扩展针对 1.74 之前的 VS Code 版本,则必须在
activationEvents中明确列出onCommand:helloworld.helloWorld。
扩展入口文件
扩展入口文件导出两个函数,activate 和 deactivate。activate 在你注册的激活事件发生时执行。deactivate 给你一个机会在扩展被停用前进行清理。对于许多扩展,可能不需要明确的清理,可以删除 deactivate 方法。但是,如果扩展在 VS Code 关闭或扩展被禁用或卸载时需要执行操作,这是执行该操作的方法。
VS Code 扩展 API 在 @types/vscode 类型定义中声明。vscode 类型定义的版本由 package.json 中 engines.vscode 字段的值控制。vscode 类型为你的代码提供 IntelliSense、转到定义和其他 TypeScript 语言功能。
// 模块 'vscode' 包含 VS Code 扩展 API // 导入模块并在下面的代码中使用别名 vscode 引用它 import * as vscode from 'vscode'; // 当你的扩展被激活时调用此方法 // 你的扩展在第一次执行命令时被激活 export function activate(context: vscode.ExtensionContext) { // 使用控制台输出诊断信息(console.log)和错误(console.error) // 这行代码只会在你的扩展被激活时执行一次 console.log('恭喜,你的扩展 "helloworld-sample" 现在已激活!'); // 命令已在 package.json 文件中定义 // 现在使用 registerCommand 提供命令的实现 // commandId 参数必须与 package.json 中的 command 字段匹配 let disposable = vscode.commands.registerCommand('helloworld.helloWorld', () => { // 你在这里放置的代码将在每次执行命令时执行 // 向用户显示消息框 vscode.window.showInformationMessage('Hello World!'); }); context.subscriptions.push(disposable); } // 当你的扩展被停用时调用此方法 export function deactivate() {}