插件开发
一个demo流程举例:
- 通过官方脚手架创建插件项目
- extension.ts入口中通过vscode.window.registerTreeDataProvider注册vscode树形数据提供者,创建侧边栏,创建一个类实现vscode.TreeDataProvider<vscode.TreeItem>给registerTreeDataProvider,完成包含树形结构数据的侧边栏创建。
- 在TreeDataProvider实例中,通过vscode.TreeItem的contextValue属性,为树视图中的每个项(即节点)提供一个上下文值。在package.json中的menus下配置view/item/context相关菜单事件内容,实现树节点显示不同的上下文菜单(右键菜单)。
- 创建一个类,完成webview相关初始化和交互逻辑,实现一个窗口创建方法并暴露出去给命令调用,通过vscode.window.createWebviewPanel创建webview
- 在view/item/context中配置一个打开webview的菜单项
- 在extension.ts中注册一个打开webview的命令context.subscriptions.push->vscode.commands.registerCommand
官方文档:code.visualstudio.com/api/get-sta…
安装脚手架
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
# ? Enable stricter TypeScript checking in 'tsconfig.json'? Yes
# ? Setup linting using 'tslint'? Yes
# ? Initialize a git repository? Yes
# ? Which package manager to use? npm
code ./helloworld
完成一个基本的插件需要理解下面三个关键概念
- 激活事件: 插件激活的时机。
- 发布内容配置: VS Code扩展了
package.json。 - VS Code API: 你的插件代码中需要调用的一系列JavaScript API。
激活事件
激活事件是在package.json中的activationEvents字段声明的一个JSON对象
- onLanguage: 打开特定语言时激活
- onCommand:调用没那个了时激活
- onDebug:调试会话启动前激活
- workspaceContains:文件夹打开后,且文件夹中至少包含一个符合glob模式的文件时触发.
- onFileSystem:以协议(scheme)打开文件或文件夹时触发,通常是
file-协议,也可以用自定义的文件供应器函数替换掉,比如ftp、ssh. - onView:指定id的视图展开时触发:
- onUri:插件的系统级URI打开时触发
- onWebviewPanel:VS Code需要恢复匹配到
viewType的webview视图时触发. - *:当VS Code启动时触发
"activationEvents": [
"onLanguage:typescript"
"onCommand:extension.sayHello"
// ...
]
发布内容配置
-
contributes.configuration :在configuration中配置的内容会暴露给用户,用户可以从“用户设置”和“工作区设置”中修改你暴露的选项。
-
contributes.configurationDefaults:为特定的语言配置编辑器的默认值,修改这个配置会覆盖编辑器已经为语言提供的默认配置。
-
contributes.commands:设置命令标题和命令体,随后这个命令会显示在命令面板中。你也可以加上
category前缀,在命令面板中会以分类显示 -
contributes.menus : 为编辑器或者文件管理器设置命令的菜单项
- 全局命令面板 -
commandPalette - 资源管理器上下文菜单 -
explorer/context - 编辑器上下文菜单 -
editor/context - 编辑器标题栏 -
editor/title - 编辑器标题上下文菜单 -
editor/title/context - 调试栈视图的上下文菜单 -
debug/callstack/context - SCM 标题菜单 -
scm/title - SCM 资源组 -
scm/resourceGroup/context - SCM 资源 -
scm/resource/context - SCM 改变标题 -
scm/change/title - 视图的标题菜单 -
view/title - 视图项的菜单 -
view/item/context
- 全局命令面板 -
-
contributes.keybindings:这个配置确定了用户输入按键组合时的触发规则
-
contributes.views:为VS Code 添加视图。需要为视图指定唯一标识和名称
-
contributes.viewsWelcome:给自定义视图配置欢迎内容。欢迎内容只能应用到空的树视图中
-
contributes.viewsContainers:配置自定义视图的视图容器。你需要为视图指定唯一标识和标题和图标。目前你只可以配置活动栏(activitybar)
VS Code API
插件目录结构
.
├── .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 任务
package.json
{
"name": "test",
"description": "test",
"version": "0.0.1",
"publisher": "test", // 发行方
"engines": {
"vscode": "^1.47.0" // 描述插件依赖的最低 VSCode API版本
},
"categories": [
"Other"
],
"activationEvents": [ // 激活事件
"*"
],
"repository": {
"type": "git",
"url": ""
},
"main": "./dist/extension.js",//插件入口文件
"contributes": { // 发布内容配置
"commands": [
{
"command": "test.debug",
"title": "查看"
},
{
"command": "test.showWebview",
"title": "打开webview"
},
],
"views": {
"testView": [
{
"id": "test",
"name": "test"
}
]
},
"viewsContainers": {
"activitybar": [
{
"icon": "resources/test.svg",
"id": "testView",
"title": "test"
}
]
},
"viewsWelcome": [
{
"view": "test",
"contents": "[test]"
}
],
"menus": {
"view/item/context": [
{
"command": "test.debug",
"group": "inline"
},
{
"command": "test.showWebview",
"title": "打开webview"
},
]
}
},
"scripts": {
"clean": "rimraf dist/",
"compile": "yarn run clean && webpack --mode production",
"watch": "yarn run clean && webpack --mode none --watch"
},
"dependencies": {
"@microsoft/vscode-azext-utils": "^0.3.15",
"axios": "^0.27.2",
"react": "^18.2.0",
"react-vsc-treeview": "^0.2.3"
},
"devDependencies": {
"@types/node": "^18.7.18",
"@types/react": "^18.0.20",
"@types/vscode": "^1.71.0",
"@types/vscode-webview": "^1.57.0",
"@typescript-eslint/eslint-plugin": "^4.16.0",
"@typescript-eslint/parser": "^4.16.0",
"eslint": "^7.21.0",
"ts-loader": "^9.4.0",
"typescript": "^4.2.2",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0"
}
}
extension.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);
}
调试插件
直接运行 Run Extension 可以开启断点调试
打包插件
安装vsce
npm install -g vsce
使用vsce打包,生成vsce文件
vsce package
vsce只能用Personal Access Tokens发布插件,所以至少要创建一个 Token 以便发布插件。
- 获取 Personal Access Token
首先,你得有一个Azure DevOps 组织。
选择 Personal Access Token,点击New Token创建一个新的 Personal Access Token
给 Personal Access Token 添加描述,过期时间等等,你最好把过期时间设置为 1 年,这样你接下就能方便很多,选择custom defined(用户自定义)范围,然后点击Show all scopes(显示全部)
最后,在这个列表中找到Marketplace,并勾选Acquire和Manage
保存好该token(7k2ikehuuihpbdubnclq3ota2ht3yaiewfyyperswjp3eempbqfa)
- 创建发行方
发行方是 VS Code 市场有权发布插件的唯一标识,每个插件的package.json文件都包含着publisher字段。在市场的发行方管理页中创建发行方,然后用这个账号登录vsce。
- 发行方登录
vsce login (publisher name)
和create-publisher命令类似地,vsce会要求输入你的 Personal Access Token。
你也可以用命令参数-p <token>直接登录然后立即发布插件:
vsce publish -p <token>
VS Code Extension API
VS Code内置了扩展能力,在插件API加持之下,VS Code几乎每一个部分都可以自定义或者加强。而且,VS Code中的很多核心功能已编译为插件,它们都共用了一套插件API。
使用 Extension API 能够做到
改变VS Code的颜色和图标主题
VS Code中的主题分为两类:
-
色彩主题:UI组件ID和文本符号ID到色彩间的映射。通过色彩主题你可以修改VS Code UI组和编辑器中的文本。
-
图标主题:文件类型/名称到图片之间的映射。文件图标显示于VS Code的资源管理侧边栏、快速打开列表和编辑器Tab等UI中。
插件灵感
- 改变你的代码颜色
- 改变VS Code UI颜色
- 将现有的TextMate主题应用到VS Code中
- 添加自定义图标
在UI中添加自定义组件和视图
“工作台”是指整个VS Code UI和其中包含的下列UI 组件:
- 标题栏
- 活动栏
- 侧边栏
- 面板
- 编辑器群
- 状态栏
- 活动栏:Azure App Service extension添加了一个视图容器
- 侧边栏:内置的NPM 插件 添加了一个 Tree View 到资源管理器视图
- 编辑器群:内置的Markdown 插件 添加了一个Webview 到编辑器的旁边
- 状态栏:VSCodeVim 插件 添加了一个状态栏项目
插件灵感
- 自定义资源管理侧边栏的菜单行为
- 在侧边栏中创建新的、交互式的TreeView
- 定义新的活动栏视图
- 在状态栏显示新的信息
- 使用
WebViewAPI显示自定义内容 - 配置源控制(git/svn等) 来源
创建Webview,使用HTML/CSS/JS显示自定义网页
当VS Code原生API不够用时,可以选择webview插件,Webview重度依赖资源,所以它脱离插件的进程而单独运行在其他环境中
在使用webview之前,请作以下考虑:
- 这个功能真的需要VS Code来提供吗?分离成一个应用或者网站会不会更好?
- webview是实现这个特性的最后方案吗?VS Code原生API是否能达到同样的目的呢?
- 你的webview所牺牲的高资源占用是否能换得同样的用户价值?
支持新的编程语言
VS Code通过语言插件可以为各式各样的编程语言提供智能的编辑体验。VS Code并不含内置语言支持,不过提供了一整套支持富文本特性的API。
语言特性大致可以分为下面两种:
声明式语言特性
- 语法高亮
- 代码片段补全
- 括号匹配
- 自动闭合括号
- 括号识别
- 启动、关闭注释
- 自动缩进
- 代码折叠
插件灵感
- 将常用的JS代码片段打包到插件中
- 为VS Code添加新的语言支持
- 为一门语言添加或替换语法
- 通过注入的方式,扩展一门语法
- 将现有的 TextMate 语法迁移到VS Code中
编程式语言特性
- 悬停信息
- 自动补全
- 转跳到定义
- 错误检查
- 格式化
- 重构
- 代码折叠
插件灵感
- 鼠标悬停于API上时, 出现用法示例
- 使用诊断,报告代码风格错误
- 注册新的HTML代码格式化
- 提供丰富的IntelliSense中间件
- 为一门语言添加代码折叠、面包屑、轮廓支持
支持特定运行时的调试
VS Code基于抽象协议,实现了一个原生(非语言相关的)的调试器UI,它可以和任意后台调试程序通信
调试适配器(Debug Adapter):连接真正的调试程序(或运行时)和调试界面的插件称之为调试适配器。VSCode没有原生调试程序,而是依赖【调试器插件】调用通信协议(调试适配器协议)和VSCode的调试器界面实现。
VS Code提供了一个配置点debuggers,调试适配器在这里可以配置特定的调试类型(例如:Node.js调试器使用node)。用户只要启动了这个类型的调试适配器会话,VS Code就能加载注册好的调试适配器
因此调试适配器的最小形式就是声明一个配置,对应调试适配器的实现,这个插件就是调试适配器的装载容器,不需要多余代码
一个更贴近现实的调试器插件往往会添加很多配置,如下面的:
- 调试器支持的语言。VS Code会为这些语言启用UI界面的断点功能
- 由调试器引入的JSON格式的调试配置属性。VS Code会使用这个格式校验launch.json中的配置,并提供补全功能
- 首次加载调试时,VS Code自动生成初始launch.json文件
- 用户可以给launch.json添加的调试配置片段
- 声明调试配置中可以使用的变量
插件灵感
- 通过调试适配器将VS Code的调试UI连接到真实的调试器或者运行时上
- 通过调试器插件添加语言支持
- 为调试配置文件添加丰富的智能提示或者悬停信息
- 为调试配置文件添加代码片段