自从使用过 VSCode 后就再也离不开 VSCode,其轻量的代码编辑器与诸多插件让多数开发者爱不释手。同样我也不例外,一年前的我甚至还特意买本《Visual Studio Code 权威指南》的书籍,来更进一步了解与使用。
在购买这本书时就想写一个 vscode 插件(扩展),奈何当时事务繁忙加之不知做何功能,就迟迟未能动手。如今有时间了,就顺带体验下 vscode 扩展开发,并记录整个开发过程。
扩展地址:VSCode-extension
开源地址:kuizuo/vscode-extension (github.com)
Vscode 相关
关于 Vscode 及其插件就不过多介绍,相信这篇文章 VSCode 插件开发全攻略(一)概览 - 我是小茗同学 - 博客园能告诉你 Vscode 插件的作用。
工具准备
在开发前,建议关闭所有功能性扩展,以防止部分日志输出与调试效率。
vscode 插件脚手架
vscode 提供插件开发的脚手架 vscode-generator-code 来生成项目 结构,选择要生成的类型
? ==========================================================================
We're constantly looking for ways to make yo better!
May we anonymously report usage statistics to improve the tool over time?
More info: https://github.com/yeoman/insight & http://yeoman.io
========================================================================== Yes
_-----_ ╭──────────────────────────╮
| | │ Welcome to the Visual │
|--(o)--| │ Studio Code Extension │
`---------´ │ generator! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `
? What type of extension do you want to create? (Use arrow keys)
> New Extension (TypeScript)
New Extension (JavaScript)
New Color Theme
New Language Support
New Code Snippets
New Keymap
New Extension Pack
New Language Pack (Localization)
New Web Extension (TypeScript)
New Notebook Renderer (TypeScript)
根据指示一步步选择,这里省略勾选过程,最终生成的项目结果如下
运行 vscode 插件
既然创建好了工程,那必然是要运行的。由于我这里选择的 ts + webpack 进行开发(视情况勾选 webpack),所以是需要打包,同时脚手架已经生成好了对应.vscode 的设置。只需要按下 F5 即可开始调试,这时会打开一个新的 vscode 窗口,Ctrl+Shift+P
打开命令行,输入Hello World
,右下角弹出提示框Hello World from kuizuo-plugin!
注意: 由于是 webpack 开发,在调用堆栈中可以看到有两个进程,一个是 webpack,另一个是新开的插件窗口的,同时在该调试窗口也能查看调试输出信息。
切记一定要等到第二个调试进程加载完毕(时间根据电脑性能而定),再打开命令行输入 Hello World 才会有命令,否则会提示 没有匹配命令。
至此,一个 vscode 的开发环境就已经搭建完毕,接下来就是了解项目结构,以及 vscode 插件的 api 了。
代码解读
import * as vscode from 'vscode'
export function activate(context: vscode.ExtensionContext) {
let disposable = vscode.commands.registerCommand('kuizuo-plugin.helloWorld', () => {
vscode.window.showInformationMessage('Hello World from kuizuo-plugin!')
})
context.subscriptions.push(disposable)
}
export function deactivate() {}
vscode.commands.registerCommand
用于注册命令,kuizuo-plugin.helloWorld
为命令 ID,在后续package.json
中要与之匹配。第二个参数为一个回调函数,当触发该命令时,弹出提示框。
在 package.json 中关注 activationEvents 与 contributes
{
"activationEvents": ["onCommand:kuizuo-plugin.helloWorld"],
"contributes": {
"commands": [
{
"command": "kuizuo-plugin.helloWorld",
"title": "Hello World"
}
]
}
}
activationEvents 激活事件,onCommand:kuizuo-plugin.helloWorld
中kuizuo-plugin
是插件 ID 要与 extension.ts 中的注册命令匹配,helloWorld
则是命令标识,而 onCommand 则是监听的类型,此外还有onView
、onUri
、onLanguage
等等。
contributes 则是配置那些地方来显示命令,像官方的例子中,就是在 Ctrl + Shift + P 命令行中输入 Hello World 来调用kuizuo-plugin.helloWorld
命令。此外还可以设置按键与菜单
"keybindings": [
{
"command": "kuizuo-plugin.helloWorld",
"key": "ctrl+f10",
"mac": "cmd+f10",
"when": "editorTextFocus"
}
],
"menus": {
"editor/context": [
{
"when": "editorFocus",
"command": "kuizuo-plugin.helloWorld",
"group": "navigation"
}
]
}
设置完毕后,可以按 Ctrl + Alt + O 或者命令行中键入 reload 来重启 vscode
这里也要注意,如果重启后并无生效,请查看 package.json 是否配置正确(多一个逗号都不行),或者尝试重新调试。如果还不行,那么很有可能就是代码报错,但日志输出并没有,那 么在弹出的新窗口中打开开发人员工具(Ctrl+Alt+I 或帮助 → 切换开发人员工具),这里有报错相关的提示信息。
功能
首次启动弹窗与配置项
先说首次启动弹窗的实现,要实现该功能,肯定要保证插件在 VSCode 一打开就运行,而这取决于 vscode 触发插件的时机,也就是 activationEvents,所以activationEvents
需要设置成onStartupFinished
。想要更高的优先级,可以选择 *
(但官方不建议,除非其他事件无法实现的前提下),这里为了演示就使用*
。
其实现代码主要调用 vscode.window.showInformationMessage
函数如下
import * as vscode from 'vscode'
import { exec } from 'child_process'
export function activate(context: vscode.ExtensionContext) {
vscode.window
.showInformationMessage('是否要打开愧怍的小站?', '是', '否', '不再提示')
.then(result => {
if (result === '是') {
exec(`start 'https://kuizuo.cn'`)
} else if (result === '不再提示') {
// 其他操作 后文会说
}
})
}
此时重启窗口,就会有如下弹窗显示
但如果你是 mac 用户的话,你会发现无法打开,其原因是 window 下打开链接的指令是 start,而 mac 则是 open,所以需要区分不同的系统。要区分系统就可以使用 node 中的 os 模块的 platform 方法获取系统,如下(省略部分代码)
import * as os from 'os'
const commandLine = os.platform() === 'win32' ? `start https://kuizuo.cn` : `open https://kuizuo.cn`
exec(commandLine)
当然了,当用户选择不再提示的时候,下次再打开 vscode 就别提示了,不然大概率就是卸载插件了。这里就需要设置全局参数了,在 package.json 中 contributes 设置 configuration,具体如下,注意kuizuoPlugin.showTip
为全局参数之一
"contributes": {
"configuration": {
"title": "kuizuo-plugin",
"properties": {
"kuizuoPlugin.showTip": {
"type": "boolean",
"default": true,
"description": "是否在每次启动时显示欢迎提示!"
}
}
}
}
该参数可以在设置 → 扩展中找到kuizuo-plugin
插件来手动选择,也可以是通过 api 来修改
然后读取vscode.workspace.getConfiguration().get(key)
和 设置该参数vscode.workspace.getConfiguration().update(key, value)
export async function activate(context: vscode.ExtensionContext) {
const key = 'kuizuoPlugin.showTip'
const showTip = vscode.workspace.getConfiguration().get(key)
if (showTip) {
const result = await vscode.window.showInformationMessage(
'是否要打开愧怍的小站?',
'是',
'否',
'不再提示',
)
if (result === '是') {
const commandLine =
os.platform() === 'win32' ? `start https://kuizuo.cn` : `open https://kuizuo.cn`
exec(commandLine)
} else if (result === '不再提示') {
//最后一个参数,为true时表示写入全局配置,为false或不传时则只写入工作区配置
await vscode.workspace.getConfiguration().update(key, false, true)
}
}
}