# 解析插件结构
上一节中,你已经能够自己创建一个基础的插件了,但是在面纱之下,它究竟是怎么运作的呢?
Hello World
插件包含了3个部分:
- 注册
onCommand
激活事件:onCommand:extension.helloWorld
,所以用户可以在输入Hello World
命令后激活插件。 - 使用
contributes.commands
发布内容配置,绑定一个命令IDextension.helloWorld
,然后Hello World
命令就可以在命令面板中使用了。 - 使用
commands.registerCommand
VS Code API 将一个函数绑定到你注册的命令IDextension.helloWorld
上。
理解下面三个关键概念你才能作出一个基本的插件:
- 激活事件: 插件激活的时机。
- 发布内容配置: VS Code扩展了
package.json
插件清单的字段以便于开发插件。 - VS Code API: 你的插件代码中需要调用的一系列JavaScript API。
大体上,你的插件就是通过组合发布内容配置和VS Code API扩展VS Code的功能。你能在插件功能概述主题中找到合适你插件的配置点和VS Code API。
好了,现在让我们自己瞧一瞧Hello World
示例的源码部分,以及我们上面提到的3个概念是如何应用其中的。
# 插件目录结构
.
├── .vscode
│ ├── launch.json // 插件加载和调试的配置
│ └── tasks.json // 配置TypeScript编译任务
├── .gitignore // 忽略构建输出和node_modules文件
├── README.md // 一个友好的插件文档
├── src
│ └── extension.ts // 插件源代码
├── package.json // 插件配置清单
├── tsconfig.json // TypeScript配置
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
下面的几个文件超出了本节讨论的范围,你可以自行前往相应的章节挖掘详细内容:
现在,让我们把精力集中在这个插件的关键部分——package.json
和extensions.ts
。
# 插件清单
每个VS Code插件都必须包含一个package.json
,它就是插件的配置清单。package.json
混合了Node.js字段,如:scripts
、dependencies
,还加入了一些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
: 激活事件 and 发布内容配置。engines.vscode
: 描述了这个插件依赖的最低VS Code API版本。postinstall
脚本: 如果你的engines.vscode
声明的是1.25版的VS Code API,那它就会按照这个声明去安装目标版本。一旦vscode.d.ts
文件存在于node_modules/vscode/vscode.d.ts
,IntelliSense就会开始运作,你就可以对所有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.25.0"
},
"categories": ["Other"],
"activationEvents": ["onCommand:extension.helloWorld"],
"main": "./out/extension.js",
"contributes": {
"commands": [
{
"command": "extension.helloWorld",
"title": "Hello World"
}
]
},
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./",
"postinstall": "node ./node_modules/vscode/bin/install"
},
"devDependencies": {
"@types/node": "^8.10.25",
"tslint": "^5.11.0",
"typescript": "^2.6.1",
"vscode": "^1.1.22"
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 插件入口文件
插件入口文件会导出两个函数,activate
和 deactivate
,你注册的激活事件被触发之时执行activate
,deactivate
则提供了插件关闭前执行清理工作的机会。
vscode
模块包含了一个位于node ./node_modules/vscode/bin/install
的脚本,这个脚本会拉取package.json
中engines.vscode
字段定义的VS Code API。这个脚本执行过后,你就得到了智能代码提示,定义跳转等TS特性了。
// 'vscode'模块包含了VS Code extensibility API
// 按下述方式导入这个模块
import * as vscode from 'vscode';
// 一旦你的插件激活,vscode会立刻调用下述方法
export function activate(context: vscode.ExtensionContext) {
// 用console输出诊断信息(console.log)和错误(console.error)
// 下面的代码只会在你的插件激活时执行一次
console.log('Congratulations, your extension "my-first-extension" is now active!');
// 入口命令已经在package.json文件中定义好了,现在调用registerCommand方法
// registerCommand中的参数必须与package.json中的command保持一致
let disposable = vscode.commands.registerCommand('extension.sayHello', () => {
// 把你的代码写在这里,每次命令执行时都会调用这里的代码
// ...
// 给用户显示一个消息提示
vscode.window.showInformationMessage('Hello World!');
});
context.subscriptions.push(disposable);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22