第一次vscode插件开发记录
1.开发文档地址
中文地址:liiked.github.io/VS-Code-Ext…
英文地址:code.visualstudio.com/api
2.vscode插件可以实现:
- 自定义命令
- 快捷键
- 自定义菜单项
- 自定义跳转
- 自动补全
- 悬浮提示
- 新增语言支持
- 语法检查
- 语法高亮
- 代码格式化 ····
3.如何创建插件
(1)首先安装脚手架
npm install -g yo generator-code
然后进入工作目录,使用脚手架
yo code
(2)脚手架生成目录结构
(3)结合react开发,改造项目
webpack相关修改,配置不同target
//@ts-check
'use strict';
const path = require('path');
const webpack = require('webpack');
//@ts-check
/** @typedef {import('webpack').Configuration} WebpackConfig **/
/** @type WebpackConfig */
const extensionConfig = {
target: 'node',
mode: 'none',
entry: './src/extension.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'extension.js',
libraryTarget: 'commonjs2'
},
externals: {
vscode: 'commonjs vscode'
},
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader'
}
]
}
]
},
devtool: 'nosources-source-map',
infrastructureLogging: {
level: "log", // enables logging required for problem matchers
},
};
const webConfig = {
target: 'web',
mode: 'none',
entry: {
app: './app/index.tsx',
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
},
externals: {
vscode: 'commonjs vscode'
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx', '.css']
},
module: {
rules: [
{
test: /\.(tsx|ts)$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader'
}
]
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
}
]
},
devtool: 'nosources-source-map',
infrastructureLogging: {
level: "log", // enables logging required for problem matchers
},
plugins: [
new webpack.DefinePlugin({
// webpack自带该插件,无需单独安装
'process.env': {
NODE_ENV: process.env.NODE_ENV, // 将属性转化为全局变量,让代码中可以正常访问
},
}),
],
};
module.exports = [ extensionConfig,webConfig ];
tsconfig相关修改
{
"compilerOptions": {
"module": "commonjs",
"target": "ES2020",
"sourceMap": true,
// "rootDir": "src",
"jsx": "react",
"experimentalDecorators": true,
"lib": ["dom", "ES2015"], // react dom相关
"allowSyntheticDefaultImports": true, // import引入
"strict": true /* enable all strict type-checking options */
/* Additional Checks */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
},
"exclude": ["node_modules"]
}
4.package.json详解
activationEvents
配置项配置插件的激活数组,即在什么情况下插件会被激活,目前支持以下8种配置:
onLanguage: 在打开对应语言文件时
onCommand: 在执行对应命令时
onDebug: 在 debug 会话开始前
onDebugInitialConfigurations: 在初始化 debug 设置前
onDebugResolve: 在 debug 设置处理完之前
workspaceContains: 在打开一个文件夹后,如果文件夹内包含设置的文件名模式时
onFileSystem: 打开的文件或文件夹,是来自于设置的类型或协议时
onView: 侧边栏中设置的 id 项目展开时
onUri: 在基于 vscode 或 vscode-insiders 协议的 url 打开时
onWebviewPanel: 在打开设置的 webview 时
*: 在打开 vscode 的时候,如果不是必须一般不建议这么设置
contributes
配置相关功能
commands:命令,通过cmd+shift+p进行输入来实现的。
menus:通过这个选项我们可以设置右键的菜单
keybindings:可以设置快捷键
languages:设置语言特点,包括语言的后缀等
grammars:可以在这个配置项里设置描述语言的语法文件的路径,vscode可以根据这个语法文件来自动实现语法高亮功能
snippets:设置语法片段相关的路径 . . . . .
5.调试(注意:本地vscode版本必须高于插件设定的版本)
(1)按 F5 产生一个新的 扩展开发宿主 的 vscode 调试台,在帮助里打开开发者模式(或者输入Developer: Toggle Developer Tools)
(2)在新的 vscode 调试台,打开 命令面板
- win: ctrl + shift + p
- mac: command + shift + p
输入package注册的命令:例如 Hello World
(3) 每次修改都要点击刷新按钮才能有效果
6.vscode功能举例
(1)快捷键
"keybindings": [
{
"command": "plugin-demo.helloWorld",
"key": "ctrl+e",
"mac": "cmd+e",
"when": "editorTextFocus" // 编辑器内的文本聚焦时(光标闪动)
}
]
command:快捷键关联的命令key:Windows平台对应的快捷键mac:mac平台对应的快捷键when:什么时候快捷键有效
当插件被激活后,并且满足快捷键有效的时间,按快捷键就可以找到extension.js中与快捷键关联的command所不绑定的事件并执行。
(2)菜单
"menus": {
"editor/context": [{ //editor/context 编辑器上下文 editor/title 编辑器标题栏
"when": "editorFocus", // 编辑器聚焦时,不管是聚焦到文本还是小部件
"command": "m.quickPage",
"alt": "dadadada",
"group": "navigation"
}]
},
(3)代码片段
"snippets": [
{
"language": "typescriptreact", // react ts中
"path": "media/snippets.json" // 存放路径
}
]
7.使用webview
(1)webview API为开发者提供了完全自定义视图的能力,例如内置的Markdown插件使用了webview渲染Markdown预览文件。Webview也能用于构建比VS Code原生API支持构建的更加复杂的用户交互界面。
可以把webview看成是VS Code中的iframe,它可以渲染几乎全部的HTML内容,它通过消息机制和插件通信。这样的自由度令我们的webview非常强劲并将插件的潜力提升到了新的高度。
(2)创建WebView
context.subscriptions.push(vscode.commands.registerCommand('extension.demo.openWebview', function (uri) {
// 创建webview
const panel = vscode.window.createWebviewPanel(
'testWebview', // viewType
"WebView演示", // 视图标题
vscode.ViewColumn.One, // 显示在编辑器的哪个部位
{
enableScripts: true, // 启用JS,默认禁用
retainContextWhenHidden: true, // webview被隐藏时保持状态,避免被重置
localResourceRoots: [vscode.Uri.file(path.join(this.context.extensionPath, 'dist'))], // 加载本地资源路径
}
);
panel.webview.html = `<html><body>你好,我是Webview</body></html>`
}
几点说明:
- 默认情况下,在Web视图中禁用
JavaScript,但可以通过传入enableScripts: true选项轻松启用; - 默认情况下当webview被隐藏时资源会被销毁,通过
retainContextWhenHidden: true会一直保存,但会占用较大内存开销,仅在需要时开启;
(3)生命周期
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.commands.registerCommand('catCoding.start', () => {
const panel = vscode.window.createWebviewPanel(
'catCoding',
'Cat Coding',
vscode.ViewColumn.One,
{}
);
let iteration = 0;
const updateWebview = () => {
const cat = iteration++ % 2 ? 'Compiling Cat' : 'Coding Cat';
panel.title = cat;
panel.webview.html = getWebviewContent(cat);
};
updateWebview();
const interval = setInterval(updateWebview, 1000);
// 手动销毁 panel.dispose()
panel.onDidDispose(
() => {
// 当面板关闭时,取消webview内容之后的更新
clearInterval(interval);
},
null,
context.subscriptions
);
})
);
}
(4)加载本地内容:这两种都可以
const bundleScriptPath = this.panel.webview.asWebviewUri(
vscode.Uri.file(path.join(this.context.extensionPath, 'dist', 'app.js'))
);
// 获取磁盘上的资源路径
const onDiskPath = vscode.Uri.file(
path.join(this.context.extensionPath, 'dist', 'app.js')
);
// 获取在webview中使用的特殊URI
const catGifSrc = onDiskPath.with({ scheme: 'vscode-resource' });
(5)信息传递
插件可以用webview.postMessage()将数据发送到它的webview中。这个方法能发送任何序列化的JSON数据到webview中,在webview中则通过message事件接受信息。
// 插件发送消息
panel.webview.postMessage({ command: 'refactor' });
// webview接收消息
window.addEventListener('message',handleMessage, false);
webview也可以把信息传递回对应的插件中,用VS Code API 为webview提供的postMessage函数我们就可以完成这个目标。调用webview中的acquireVsCodeApi获取VS Code API对象。这个函数在一个会话中只能调用一次,你必须保持住这个方法返回的VS Code API实例,然后再转交到需要调用这个实例的地方。
// webview发送消息
const vscode = acquireVsCodeApi();
vscode.postMessage({
type: 'submit',
data: values
});
// 插件接受webview信息
panel.webview.onDidReceiveMessage(message => {
switch (message.command) {
case 'alert':
vscode.window.showErrorMessage(message.text);
return;
}
}, undefined, context.subscriptions);
8.发布流程
(1)打包:
先安装 npm install -g vsce
执行 vsce package 命令,得到一个 vsix 结尾的文件
(2)发版:
- 创建组织:先在这个网站里 Azure DevOps 登录自己的账号,然后创建组织
- 创建token:选择 个人访问令牌 后,点击 New Token ,填写相关信息后,将会得到 Token,复制token
- 创建发布者:vsce create-publisher (publisher name) 或者 创建发布者 ,填写自己的 Name 即可
- 注意:需要在我们的 package.json 中添加 publisher 字段
- 执行 vsce login ,输入复制的token,登录成功
- 执行发布 vsce publish