Vscode插件开发

737 阅读6分钟

一. 关于VS Code插件

VS Code插件简介

vscode是微软出的一款轻量级代码编辑器,IDE只提供了基本功能和框架,有很多功能都是由插件丰富和扩展的。

VS Code插件功能

1.不受限的本地磁盘访问

2.自定义命令、快捷键、菜单

3.自定义跳转、自动补全、悬浮提示

4.自定义插件设置、自定义插件欢迎页

5.自定义WebView

6.自定义左侧功能面板

7.自定义颜色、图标主题

8.新增语言支持(代码高亮、语法解析、折叠、跳转、补全等)

9.Markdown增强

10.其他(比如状态栏修改、通知提示、编辑器控制、git源代码控制、任务定义、Language Server、Debug Adapter等等)

二 . 搭建VS Code项目

安装脚手架

  1. 确保已安装Node.jsGit
  2. 使用npm install -g yo generator-code命令安装YeomanVS Code Extension Generator

创建项目

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
// 是否初始化git仓库
# ? Initialize a git repository? Yes
// 是否需要webpack打包
# ? Bundle the source code with webpack? No
// 使用哪个包管理器
# ? Which package manager to use? npm
// 是否要使用Visual Studio代码打开新文件夹?
# ? Do you want to open the new folder with Visual Studio Code? Open with `code`

三 . 项目结构

扩展文件结构

**以JavaScript类型讲解一下项目架构**
├── .vscode // vscode调试配置
|  ├── launch.json // 用于启动和调试扩展的配置
|  └── tasks.json // 编译生成任务的配置
├── .gitignore // 发布忽略内容
├── CHANGELOG.md // 修改日志
├── README.md // 插件发布后,插件主页内容
├── package-lock.json
├── package.json // vscode从这里识别插件贡献点
├── src // 核心源码内容
|  ├── extension.ts // 入口文件
|  └── test //测试文件
├── jsconfig.json // 配置文件
├── vsc-extension-quickstart.md 
└── webpack.config.js // wepack配置

核心内容讲解

  1. package.json
字段名称含义
name插件名称(应全部小写,不能有空格)
version插件版本号
publisher发布者,(该名称应与发布到应用市场名称一致)
engines表示插件最低支持的vscode版本
main插件的主入口
activationEvents插件触发动作,如在打开某种语言的文件时、当某个命令被触发时
contributes插件贡献点,大部分新增功能点都再次声明
commands插件命令
keybindings快捷键绑定
snippets代码片段
scripts同npm scripts
devDependencies开发依赖
  1. extension.js
const vscode = require('vscode');
/**
 * @param {vscode.ExtensionContext} context
 * 插件被激活时触发,所有代码总入口
 */
function activate(context) {
	// 使用控制台输出诊断信息(console.log)和错误(console.error);
        // 扩展激活时,这行代码只执行一次
	console.log('Congratulations, your extension "hello" is now active!');

	// vscode.commands.registerCommand是注册命令的API,执行后会返回一个Disposable对象,所有注册类的API执行后都需要将返回结果放到context.subscriptions中去。
	let disposable = vscode.commands.registerCommand('JavaScript.helloWorld', function () {
		// 每次执行命令时,您在此处放置的代码都将被执行,向用户显示消息框
		vscode.window.showInformationMessage('Hello World from hello!');
	});
	context.subscriptions.push(disposable);
}

// 插件被停用之前进行清理
function deactivate() {}

module.exports = {
	activate,
	deactivate
}

四 . 开发与调试

插件开发(以webview插件开发为例)

创建webview(window.createWebviewPanel)

  • extension.js中引入webview主页面
const vscode = require('vscode');
/*
* 插件被激活时,所有代码总入口
*/
function activate(context) {
    require('./index)(context) // 主页面
}
// 插件停用之前进行清理
function deactivate() {
    console.log('扩展已被释放')
}
module.exports = {
    activate,
    deactivate
}
  • index主页面中创建webview
module.exports = (context) => {

    context.subscriptions.push(vscode.commands.registerCommand('vscode-plugin.helloWorld', () => {
        const panel = vscode.window.createWebviewPanel(
            'VScode-Plugin', //viewType
            'VScode Plugin', //视图标题
            vscode.ViewColumn.One, // 显示在编辑器的哪个部位
            {
                enableScripts: true, // 启用JS,默认禁用
                retainContextWhenHidden: true, // webview被隐藏时保持状态,避免被重置
            }
        );

        // 获取磁盘上资源的路径
        panel.webview.html = util.getWebViewContent(context, 'src/pages/index.html');
    }))

}

加载页面资源

出于安全考虑,webview无法直接访问本地资源,想要加载本地js、css、等资源必须通过特殊的vscode-resource协议。这种协议类似于file协议他只允许访问特定的本地文件并从磁盘上加载绝对路径的资源(可参考vscode插件开发全攻略提供的Git demo)

image.png

页面通信

  1. 消息从扩展传递到webview 扩展可以使用webview.postMessage(),此方法将任何JSON可序列化数据发送到webview,消息通过标准message事件在webview内部接收。 具体使用方法参考官方案例(code.visualstudio.com/api/extensi…
  • 消息从webview传递到扩展 webview将消息传递回扩展也是通过postMessage(),但要在webview内调用acquireVsCodeApi来访问 VS Code API 对象,每个会话只能调用此函数一次且必须挂在此方法返回的 VS Code API 的实例上,并将其分发给需要使用它的任何其他函数。
// webview页面
<body>
    <div @click="updateHtml">详情</div>
</body>

// js
const vscode = acquireVsCodeApi();
new Vue({
    el: '#app',
    data: {},
    methods: {
        updateHtml() {
            vscode.postMessage({
                command: 'update', // 向扩展传递参数
            })
        }
    }
})
// 扩展中接收参数
panel.webview.onDidReceiveMessage// onDidReceiveMessage: 从渲染器接收到消息时触发的事件
  message => { 
    switch (message.command) {
      case 'update':
        // 页面更新
        panel.webview.html = util.getWebViewContent(context, 'src/pages/update.html');
        break;
    }
  },
  undefined,
  context.subscriptions
);

生命周期 & webview状态

用户关闭webview面板后,webview自动销毁

  1. panel.webview.onDidReceiveMessage() 当 webview 内容发布消息时触发。 Webview 内容可以将字符串或 json 可序列化对象发布回扩展。他们不能发布Blob,File,ImageData和其他
  2. panel.dispose():扩展程序还可以通过调用dispose()它们以编程方式关闭 webviews (参考官方demo)

可能遇到的edit

  1. editor属性
  • document:当前编辑器中的文档内容
  • edit:用于修改编辑器中的内容
  • revealRange:用于将某段代码滚动到当前窗口中
  • selection: 当前编辑器内的主光标
  • selections:当前编辑器中的所有光标,第一个光标就是主光标,后面的则是用户创建出来的多个光标
  • setDecorations: 设置编辑器装饰器
  1. edit的API
  • delete
  • insert
  • replace
  • setEndOfLine

插件调试

启动webview插件

  • step1:编辑器中按F5(或使用vsocde中运行和调试),在新窗口中编译和运行扩展
  • step2:在新窗口命令面板中运行shift+command+p image.png
  • step3:点击自定义命令(如Hello World),打开webview页面 image.png

断点调试

  • 点击要打断点的某行代码 image.png
  • 启动插件 image.png

检查webview

option+command+i 打开webview调试台 image.png

五 . VS Code发布更新

打包

// 确保已安装node.js后运行
npm install -g vsce
// 依次运行如下命令
cd 项目
vsce package
vsce publish

发布扩展

获取个人访问令牌

  • 登录Microsoft(无账号先到Microsoft官方注册账号)

  • 创建组织(按照文档创建流程创建组织)

  • 设置中选择个人访问令牌 image.png

  • 创建新的 Personal Access Token

image.png

  • 复制令牌创建发布者

创建发布者

发布扩展

  • 发布扩展 vsce publish //处于安全考虑vsce不会发布包含用户提供的 SVG 图像的扩展
  • 自动增值扩展
//如果将扩展的版本从 1.0.0 更新到 1.1.0,您可以指定minor:
vsce publish minor
//还可以在命令行上指定完整的 SemVer 兼容版本
vsce publish 2.0.1

取消发布

vsce unpublish (publisher name).(extension name) //注意:此操作是直接删除插件

用户更新

vscode插件更新是热更新的模式,安装后有更新会自动检测新版本,用户只需搜索插件后重启开插件即可

六 . 参考资料