这是VS Code官方文档的第二章节,主要内容是通过创建一个
Hello World
插件来作为插件编写入门
Hello World
建立框架
进行VS Code
插件开发的前提是安装了Node.js
和Git
,并且需要安装Yeoman
和VS Code Extension Generator
来生成插件框架
npm install -g yo generator-code
复制代码
然后可以通过执行yo code
创建一个插件框架
# ? What type of extension do you want to create? New Extension (TypeScript)
# ? What's the name of your extension? HelloWorld
### Press <Enter> to choose default for all options below ###
# ? What's the identifier of your extension? helloworld
# ? What's the description of your extension? LEAVE BLANK
# ? Initialize a git repository? Yes
# ? Bundle the source code with webpack? No
# ? Which package manager to use? npm
复制代码
该框架具备基本的功能,我们用VS Code
刚刚创建的项目,按下F5键(此时不要打开任何文件),会自动开启一个新的VS Code
界面,在这个界面中我们按下Ctrl+Shift+P
组合键唤醒Command Palette
,然后输入Hello Word
命令:
之后我们会在页面的右下角见到Hello World from HelloWord!
提示:
修改源码
我们可以试着尝试修改下上述的框架里的代码
定位到src/extension.ts
:
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
// Use the console to output diagnostic information (console.log) and errors (console.error)
// This line of code will only be executed once when your extension is activated
console.log('Congratulations, your extension "helloword" is now active!');
// The command has been defined in the package.json file
// Now provide the implementation of the command with registerCommand
// The commandId parameter must match the command field in package.json
let disposable = vscode.commands.registerCommand('helloword.helloWorld', () => {
// The code you place here will be executed every time your command is executed
// Display a message box to the user
vscode.window.showInformationMessage('Hello World from HelloWord!');
});
context.subscriptions.push(disposable);
}
// this method is called when your extension is deactivated
export function deactivate() {}
复制代码
我们可以将vscode.window.showInformationMessage('Hello World from HelloWord!');
做修改,改为vscode.window.showInformationMessage('这是第一个插件!');
,保存修改后,在调试窗口里执行Developer: Reload Window
命令:
再次执行Hello World
命令,可以看到提示信息发生了变化:
除此之外,我们还可以通过修改package.json
的contributes
字段信息,来修改命令的名称,如:
"contributes": {
"commands": [{
"command": "helloword.helloWorld",
+ "title": "Clock"
}]
},
复制代码
将命令名称改为Clock
,则执行命令时会看到Command Palette
里的名称已经发生改变
可以尝试一个练习,修改提示的内容,比如显示当前时间。还可以通过查阅vscode-api试着用一些新的api,看看执行效果。例如我在这里就试着运行了一下vscode.window.showErrorMessage
接口,这种尝试很有趣
调试
我们可以在源码上直接打断点,运行的时候会自动停止,而且我们可以将鼠标放在变量上,看到变量的具体取值。如果有过浏览器调试经验的话,应该不会感到困难
Hello World 进阶
我们在此继续对上面的hello world示例作进一步的分析
功能实现原理
细看起来上面的Hello World
插件干了三件事:
-
在
package.json
中注册onCommand活动事件(Activation Event),以便当用户运行Hello World
命令时唤醒(activated)插件"activationEvents": [ "onCommand:helloword.helloWorld" ] 复制代码
-
在
package.json
中注册contributes.commands
(Contribution Point),以便可以在Command Palette
中使用"contributes": { "commands": [{ "command": "helloword.helloWorld", "title": "Clock" }] } 复制代码
-
在
extension.ts
中用commands.registerCommand
(VS Code API)给Hello World
命令绑定一个具体的函数let disposable = vscode.commands.registerCommand('helloword.helloWorld', () => { // The code you place here will be executed every time your command is executed // Display a message box to the user vscode.window.showErrorMessage(new Date().toLocaleString()); }); 复制代码
通过上述分析可知,通常一个插件就是Contribution Points
、VS Code API
的组合。官方的Extensions Capabilities Overview文档可以帮助你寻找到适合你自己插件的Contribution Points
和VS Code API
项目结构
Hello World
插件是以如下结构组织起来的:
.
├── .vscode
│ ├── launch.json // Config for launching and debugging the extension
│ └── tasks.json // Config for build task that compiles TypeScript
├── .gitignore // Ignore build output and node_modules
├── README.md // Readable description of your extension's functionality
├── src
│ └── extension.ts // Extension source code
├── package.json // Extension manifest
├── tsconfig.json // TypeScript configuration
复制代码
这里我们要将目光集中在package.json
、extension.ts
,这里是理解Hello World
插件的关键
插件清单(Extension Manifest)
每个VS Code
插件都必须有一个package.json
作为它的 Extension Manifest,这个package.json
文件除了包含常见的Node.js用到的scripts
、devDependencies
等字段外,还有VS Code
插件所特有的contributes
、publisher
、activationEvents
等字段。你可以在官方的 Extension Manifest 文档中找到所有的VS Code
插件字段。
对于Hello World
插件来说,package.json
文件内容是这样的:
{
"name": "helloword",
"displayName": "HelloWord",
"description": "",
"version": "0.0.1",
"publisher": "vscode-lamengduo-samples",
"engines": {
"vscode": "^1.56.0"
},
"categories": [
"Other"
],
"activationEvents": [
"onCommand:helloword.helloWorld"
],
"main": "./dist/extension.js",
"contributes": {
"commands": [{
"command": "helloword.helloWorld",
"title": "Clock"
}]
},
"scripts": {
"vscode:prepublish": "yarn run package",
"compile": "webpack",
"watch": "webpack --watch",
"package": "webpack --mode production --devtool hidden-source-map",
"test-compile": "tsc -p ./",
"test-watch": "tsc -watch -p ./",
"pretest": "yarn run test-compile && yarn run lint",
"lint": "eslint src --ext ts",
"test": "node ./out/test/runTest.js"
},
"devDependencies": {
"@types/vscode": "^1.56.0",
"@types/glob": "^7.1.3",
"@types/mocha": "^8.0.4",
"@types/node": "14.x",
"eslint": "^7.19.0",
"@typescript-eslint/eslint-plugin": "^4.14.1",
"@typescript-eslint/parser": "^4.14.1",
"glob": "^7.1.6",
"mocha": "^8.2.1",
"typescript": "^4.1.3",
"vscode-test": "^1.5.0",
"ts-loader": "^8.0.14",
"webpack": "^5.19.0",
"webpack-cli": "^4.4.0"
}
}
复制代码
这些字段中有几个比较重要,这里单独说一说:
name
、publisher
:VS Code
会把<publisher>.<name>
作为插件的唯一ID,例如这个插件的ID就是vscode-lamengduo-samples.helloword
main
:指明了插件的入口activationEvents
、contributes
:对应 Activation Events 和 Contribution Pointsengines.vscode
:标记当前插件需要的VS Code
最低版本
入口文件
每个VS Code
插件都有一个入口文件(由package.json
中的main
字段指定),VS Code
规范要求插件的入口文件需要导出两个函数activate
、deactivate
。当开发者注册的Activation Event
被触发时,将会执行activate
函数。deactivate
函数则主要是给插件开发者一个在插件停止工作之前一个执行清理的机会。对很多应用来说,deactivate
其实不是必须的,可以删掉。不过如果你希望当VS Code
关闭、插件不可用、插件卸载时做点什么的话,这个方法就有用了。
VS Code的插件API在 @types/vscode 包中做了类型声明,这个文件将会根据package.json
文件中的engines.vscode
提供智能提示等服务(如果插件框架是通过yo命令生成的,则@types/vscode会默认安装好)