VSCode插件开发
VSCode Overview
Hello world
开发第一个VSCode插件
- 安装环境
- 创建项目
- 项目结构
- 编译、运行、调试
- 打包、安装
1. 安装环境
# 1. Install Nodejs 正常安装流程既可
# 2. install Yeoman and VS Code Extension Generator (全局安装)
# 用来生成项目模板代码
$ npm install -g yo generator-code
# 3. 用来打包发布插件
$ npm install -g @vscode/vsce
2. 创建项目
$ yo code
_-----_ ╭──────────────────────────╮
| | │ 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? Hello world
? What's the identifier of your extension? HelloWorldID
? What's the description of your extension?
? Initialize a git repository? Yes
? Bundle the source code with webpack? No
? Which package manager to use? npm
# 下载项目的依赖
$ cd ${project_dir}
$ npm install
3. 项目结构
$ tree .
├── .vscode
│ ├── launch.json // 调试配置
│ └── tasks.json // task任务配置
├── src
│ └── extension.ts // 程序代码
├── package.json // 项目配置
├── tsconfig.json // TypeScript配置
package.json
:项目核心的配置文件src/extension.ts
:程序代码文件(入口)tsconfig.json
:TypeScript配置文件(TypeScript会被编译成JavaScript来运行)
package.json
文件
{
"name": "HelloWorldID", // 插件ID
"displayName": "Hello world", // 插件名称
"description": "",
"version": "0.0.1",
"engines": {
// 插件支持的VSCode版本
"vscode": "^1.80.0" // 1.80.0及以上
},
"categories": [
// 插件分类: 用来在插件市场分类
"Other"
],
"activationEvents": [], // 插件激活事件
"main": "./out/extension.js", // 程序入口
"contributes": {
// 插件核心配置
"commands": [
// 插件命令: 用来注册命令(ctrl + shift + p)
{
"command": "runner.helloWorld", // 命令ID (代码中使用)
"title": "Hello World" // 命令名称(用户使用)
}
]
},
"scripts": {
// npm脚本
"vscode:prepublish": "npm run compile",
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./",
"pretest": "npm run compile && npm run lint",
"lint": "eslint src --ext ts",
"test": "node ./out/test/runTest.js"
},
"devDependencies": {
// 开发依赖
"@types/vscode": "^1.80.0",
"@types/glob": "^8.1.0",
"@types/mocha": "^10.0.1",
"@types/node": "20.2.5",
"@typescript-eslint/eslint-plugin": "^5.59.8",
"@typescript-eslint/parser": "^5.59.8",
"eslint": "^8.41.0",
"glob": "^8.1.0",
"mocha": "^10.2.0",
"typescript": "^5.1.3",
"@vscode/test-electron": "^2.3.2"
}
}
Note:一些属性是正常的npm项目属性,有些属性是配置给VSCode插件用的
main
属性:项目程序入口contributes
属性:VSCode插件核心配置节点(相对于VSCode插件来说)activationEvents
属性:激活插件的事件(方式)
src/extension.ts
文件
// 导入vscode模块
import * as vscode from 'vscode';
// 插件激活时调用
export function activate(context: vscode.ExtensionContext) {
console.log('Congratulations, your extension "runner" is now active!');
// 注册命令: runner.helloWorld
let disposable = vscode.commands.registerCommand('runner.helloWorld', () => {
// 显示一个信息框: Hello World from demo1!
vscode.window.showInformationMessage('Hello World from demo1!');
});
context.subscriptions.push(disposable);
}
// 插件停用时调用
export function deactivate() {}
activate
函数:插件激活时调用deactivate
函数:插件停用时调用
4. 编译、运行、调试
前面yo code
命令已经生成了相应运行调试的配置,直接按 F5
键或VSCode的调试既可;配置文件列表:
.vscode/launch.json
:调试配置Run Extension
:运行插件Extension Tests
:插件测试
.vscode/tasks.json
:任务task配置
5. 打包、安装
$ cd ${project_dir}
# 打包,会生成后缀为vsix的插件文件
$ vsce package
# 发布(我们自已用,不用公开发布)
$ vsce publish
安装:把生成的vsix文件拖拽到VSCode的插件列表中,安装既可
VSCode能力
大白话说:VSCode暴露了哪些接口(能力),让我们/开发者去利用(发挥):
- Common Capabilities:通用能力
- Theming:主题
- Declarative Language Features:声明性语言特性(后面详细讲)
- Programmatic Language Features:编程语言特性(后面详细讲)
- Workbench Extensions:工作台UI
- UX Guidelines:交互设计指南
- Debugging:调试
Common Capabilities
通用能力列表:
- Command:添加命令
- Configuration:自定义配置
- Keybinding:添加快捷键
- Context Menu:上下文菜单
- Data Storage:数据存储
ExtensionContext.workspaceState
: 项目级别ExtensionContext.globalState
: 全局(多个项目可用)
- Display Notifications:通知
window.showInformationMessage
:显示普通信息通知window.showWarningMessage
:显示警告Warning信息通知window.showErrorMessage
:显示错误Error信息通知
- Quick Pick:获取用户输入、让用户选择
- Output Channel:用于输出日志之类
- Progress API:进度相关API,用来显示进度(比如:下载进度)
Theming主题
分类:
- Color Theme:颜色主题
- File Icon Theme:文件类型图标主题
- Product Icon Theme:VSCode产品图标主题
Color Theme:颜色主题
File Icon Theme:文件类型图标主题
Product Icon Theme:VSCode产品图标主题
![image-20230721095503809](/assets/image-20230721095503809.aQqZdefk.webp)
Declarative Language Features && Programmatic Language Features
这两个后面讲
Workbench Extensions
开发者角度:
- Views Containers:视图容器
- Tree View:树视图
- Webview:Web视图
- Status Bar Item:状态栏
- etc
![image-20230724145859144](/assets/image-20230724145859144.OSESF016.webp)
Debugging调试
// TODO: 暂时用不上
插件开发指南
- Command:增加命令
- Tree View API:显示布局Layout.json 控件大纲
- Webview API:布局Layout.json 效果实时预览
- Custom Editor API:通过UI编辑布局Layout.json文件(xml, json)
- Task Provider:编译、运行、烧录程序等待
UX交互设计指南
- Activity Bar:活动栏
- Panel:面板
- Status Bar:状态栏
- Views:视图
- Editor Actions:编辑器动作,编译运行
- Context Menus:上下文菜单
- Walkthroughs:步骤、流程性的操作(比如:环境配置、图片添加处理、字体添加处理...)
![](/assets/image-20230721112430003.D9sQu-kU.webp)
Panel
- 串口连接:日志输出
- 设备日志输出:级别过滤、正则过滤
![image-20230721110609993](/assets/image-20230721110609993.Bex9GbFk.webp)
Status Bar
- 和设备的链接状态
![image-20230721112137524](/assets/image-20230721112137524.CSwklH5U.webp)
View视图
- 显示布局Layout.json 控件大纲(格式:控件类型-ID-src/text)
![image-20230721110136943](/assets/image-20230721110136943.CXCcoGZw.webp)
Editor Actions
- 固件编译、固件烧录
- 程序编译运行、调试
![image-20230721110010945](/assets/image-20230721110010945.CA2nfn6X.webp)
Context Menus
- UI预览模式打开
- UI编辑模式打开
![image-20230721105708022](/assets/image-20230721105708022.D6QgrpHn.webp)
Walkthroughs
一步步跟着步骤走来去熟悉一个流程或概念;适合用于步骤、流程性的操作:
- 环境配置
- 图片添加处理
- 字体添加处理
- 用于排错,可以一步步去检查确认
- etc
![image-20230721105551780](/assets/image-20230721105551780.C4nks-tn.webp)
语言拓展
Declarative language features:声明性语言特性(基础),通过写配置文件就实现了
Programmatic language features:编程语言特性(高级)(自动补全、错误检查、转跳到定义、查看引用),通过语言服务进程去实现
Language Server Protocol:语言服务协议(jsonRPC),可以用不同的语言来去实现这个服务进程,其它编辑器、IDE可以复用
Declarative language features
对编程语言提供基础的功能;能过写配置文件就能实现
- Syntax highlighting:语法高亮
- Snippet completion:代码片段补全
- Bracket matching:括号匹配
- Bracket autoclosing:括号补全
- Bracket autosurrounding:
- Comment toggling:注释
- Auto indentation:自动缩进对齐
- Folding (by markers):代码折叠
Snippet completion代码片段补全
示例:snippet-sample
- 用
Snippets: Configure User Snippets
去测试Snippets
代码快 - 上一卡测试能用了,把文件拷贝到插件项目代码中,的json文件中,比如命名
snippets.json
- 在
package.json
中添加snippets
属性配置,如下
{
"contributes": {
"snippets": [
{
"language": "javascript",
"path": "./snippets.json"
}
]
}
}
Language Configuration配置
示例:language-configuration-sample
package.json
文件:languages
下面的configuration
属性
{
// ...
"categories": ["Programming Languages"],
"contributes": {
"languages": [
{
"id": "javascript",
"extensions": [".js"],
"aliases": ["js", "JavaScript"],
"configuration": "./language-configuration.json"
}
]
}
}
language-configuration.json文件:
{
"comments": {
"lineComment": "//",
"blockComment": ["/*", "*/"]
},
"brackets": [
["{", "}"],
["[", "]"],
["(", ")"]
],
"autoClosingPairs": [
{ "open": "{", "close": "}" },
{ "open": "[", "close": "]" },
{ "open": "(", "close": ")" },
{ "open": "'", "close": "'", "notIn": ["string", "comment"] },
{ "open": "\"", "close": "\"", "notIn": ["string"] },
{ "open": "`", "close": "`", "notIn": ["string", "comment"] },
{ "open": "/**", "close": " */", "notIn": ["string"] }
],
"autoCloseBefore": ";:.,=}])>` \n\t",
"surroundingPairs": [
["{", "}"],
["[", "]"],
["(", ")"],
["'", "'"],
["\"", "\""],
["`", "`"]
],
"folding": {
"markers": {
"start": "^\\s*//\\s*#?region\\b",
"end": "^\\s*//\\s*#?endregion\\b"
}
},
"wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)",
"indentationRules": {
"increaseIndentPattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$",
"decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\)\\}\\]].*$"
}
}
属性下面一个个解释:
Comment toggling注释
{
"comments": {
"lineComment": "//",
"blockComment": ["/*", "*/"]
}
}
lineComment
:行注释blockComment
:块注释
Brackets definition
- VSCode语法高亮:括号高亮匹配
- VSCode动作:转跳到括号**
Go to Bracket
** - VSCode动作:选择到括号**
Select to Bracket
**
{
"brackets": [
["{", "}"],
["[", "]"],
["(", ")"]
]
}
Autoclosing
当输入open
的字符,自动补全close
的字符;notIn
表示在某些场景下不生效,如字符串string
、注释comment
{
"autoClosingPairs": [
{ "open": "{", "close": "}" },
{ "open": "[", "close": "]" },
{ "open": "(", "close": ")" },
{ "open": "'", "close": "'", "notIn": ["string", "comment"] },
{ "open": "\"", "close": "\"", "notIn": ["string"] },
{ "open": "`", "close": "`", "notIn": ["string", "comment"] },
{ "open": "/**", "close": " */", "notIn": ["string"] }
]
}
Autoclosing before
正常情况下,输入光标后面有字符,自动结束标志就不会生效;autoCloseBefore
属性,表示配置光标后面是这些符号也能生效
{
"autoCloseBefore": ";:.,=}])>` \n\t"
}
Autosurrounding
当你选中一段代码,按下开始括号,会自动的在选中代码结束的地方加上结束括号
{
"surroundingPairs": [
["{", "}"],
["[", "]"],
["(", ")"],
["'", "'"],
["\"", "\""],
["`", "`"]
]
}
Folding代码折叠
通过标记marker匹配规则
{
"folding": {
"markers": {
"start": "^\\s*//\\s*#?region\\b",
"end": "^\\s*//\\s*#?endregion\\b"
}
}
}
start
:开始的匹配规则;匹配//#region
end
:结束的匹配规则;匹配//#endregion
示例代码:
console.log('foo');
// #region 折叠开始标记
console.log('bar');
console.log('foobar');
// #endregion 折叠结束标记
console.log('foobar');
Indentation Rules代码缩进规则
{
"indentationRules": {
"increaseIndentPattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$",
"decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\)\\}\\]].*$"
}
}
increaseIndentPattern
:增加缩进的匹配规则decreaseIndentPattern
:减少缩进的匹配规则
示例:if (true) {
匹配到increaseIndentPattern
规则,当按下回车Enter
键之后,就会增加缩进
if (true) {
console.log();
Programmatic language features
VSCode和插件充当一个客户端Client,VSCode的语言的功能通过专门的语言服务进程对其提供
- Hover information:鼠标悬停显示相关信息
- Auto completion:自动补全
- Jump to definition:光标转跳到定义
- Error checking:错误检查
- Formatting:格式化
- Refactoring:重构:修改symbols符号(函数、变量),使用到该symbols的都会被修改
- Folding:代码折叠
![image-20230721152435610](/assets/image-20230721152435610.D_dTfQlz.webp)
看文档:
举例:
Show Hovers:鼠标悬停,显示相应文档信息
Provide Diagnostics: 错误诊断
Language Server Protocol
- 标准化客户端与服务端交互流程,就制订了这个语言服务协议
- 服务进程可以用不同的语言去实现
- 复用:不同的编辑器、IDE可以利用通过语言服务协议来复用这些基础设施
https://microsoft.github.io/language-server-protocol/specification
通过Clangd简单认识下协议、交互流程:
c
代码示例:
#include <stdio.h>
/**
* @brief foo 函数
*
*/
void foo(void) {
printf("foo\n");
}
int main(int argc, char* argv[]) {
for (int idx = 0; idx < 10; idx++) {
printf("hello world:[%d] \n", idx);
}
foo();
return 0;
}
- clangd启动
- vscode和clangd的交互流程
- 演示几个语言特性:
- Go to definition:转跳到定义
- Formating:格式化代码
- hover:鼠标悬停,会显示相应的信息文档
- rename:变量、函数重命名
高级主题
// TODO
References详细文档
- VSCode API文档:https://code.visualstudio.com/api/references/vscode-api
- Contribution配置属性文档:https://code.visualstudio.com/api/references/contribution-points
- Activation Events插件激活事件:https://code.visualstudio.com/api/references/activation-events
- Extension Manifest(package.json)配置文档:https://code.visualstudio.com/api/references/extension-manifest
- Built-in Commands VSCode内置命令:https://code.visualstudio.com/api/references/commands
- Product Icon 内置Icon图标:https://code.visualstudio.com/api/references/icons-in-labels