原文链接:写一个VSCode插件

自从使用过 VSCode 后就再也离不开 VSCode,其轻量的代码编辑器与诸多插件让多数开发者爱不释手。同样我也不例外,一年前的我甚至还特意买本《Visual Studio Code 权威指南》的书籍,来更进一步了解与使用。

在购买这本书时就想写一个 vscode 插件(扩展),奈何当时事务繁忙加之不知做何功能,就迟迟未能动手。如今有时间了,就顺带体验下 vscode 插件开发,并记录整个开发过程。

插件地址:VSCode-extension

开源地址:kuizuo/vscode-extension (github.com)

Vscode 相关

vscode 应用商店

vscode 插件官方文档

vscode 官方插件例子

关于 Vscode 及其插件就不过多介绍,相信这篇文章 VSCode 插件开发全攻略(一)概览 - 我是小茗同学 - 博客园 能告诉你 Vscode 插件的作用。

工具准备

:::tip

在开发前,建议关闭所有功能性扩展,以防止部分日志输出与调试效率

:::

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 ThemeNew Language SupportNew Code SnippetsNew KeymapNew Extension PackNew Language Pack (Localization)New Web Extension (TypeScript)New Notebook Renderer (TypeScript)

根据指示一步步选择,这里省略勾选过程,最终生成的项目结果如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nRDc3Le8-1657644399870)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f2930db8192c4854996baf4da13d223b~tplv-k3u1fbpfcp-zoom-1.image)]

运行 vscode 插件

既然创建好了工程,那必然是要运行的。由于我这里选择的 ts + webpack 进行开发,所以是需要打包,同时脚手架已经生成好了对应.vscode 的设置。只需要按下 F5 即可开始调试,这时会打开一个新的 vscode 窗口,Ctrl+Shift+P打开命令行,输入Hello World,右下角弹出提示框Hello World from kuizuo-plugin!

:::danger

注意: 由于是 webpack 开发,在调用堆栈中可以看到有两个进程,一个是 webpack,另一个是新开的插件窗口的,同时在该调试窗口也能查看调试输出信息。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7cvOpabv-1657644399880)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e9554510d419439eb29c15b4e8f18a34~tplv-k3u1fbpfcp-zoom-1.image)]

切记一定要等到第二个调试进程加载完毕(时间根据电脑性能而定),再打开命令行输入 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.helloWorldkuizuo-plugin是插件 ID 要与 extension.ts 中的注册命令匹配,helloWorld则是命令标识,而 onCommand 则是监听的类型,此外还有onViewonUrionLanguage等等。

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

:::danger

这里也要注意,如果重启后并无生效,请查看 package.json 是否配置正确(多一个逗号都不行),或者尝试重新调试。如果还不行,那么很有可能就是代码报错,但日志输出并没有,那么在弹出的新窗口中打开开发人员工具(Ctrl+Alt+I 或帮助 → 切换开发人员工具),这里有报错相关的提示信息。

建议查看VSCode 插件开发全攻略(六)开发调试技巧

:::

功能

首次启动弹窗与配置项

先说首次启动弹窗的实现,要实现该功能,肯定要保证插件在 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 === '不再提示') {// 其他操作 后文会说}})
}

此时重启窗口,就会有如下弹窗显示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pYFyjM60-1657644399882)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/85b2741822ea4af28f90984529baac94~tplv-k3u1fbpfcp-zoom-1.image)]

但如果你是 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 来修改

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6LzeGndg-1657644399884)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/813669faa6b546eda203abe9fdd214ec~tplv-k3u1fbpfcp-zoom-1.image)]

然后读取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)}}
}

即便是调试状态下,重启也不会影响全局参数。最终封装完整代码查看源码,这里不再做展示了。

右键资源管理器(快捷键)新建测试文件

我日常开发中写的最多的文件就是 js/ts 了,有时候就会在目录下创建 demo.js 来简单测试编写 js 代码,那么我就要点击资源管理器,然后右键新建文件,输入 demo.js。于是我想的是将该功能封装成快捷键的方式,当然右键也有新建测试文件这一选项。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lmRxWWy0-1657644399885)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/eded811fae67413783b0a63572c4ccab~tplv-k3u1fbpfcp-zoom-1.image)]

功能其实挺鸡肋的,也挺高不了多少效率,这里可以说为了演示和测试这个功能而实现

总之前面这么多废话相当于铺垫了,具体还是看功能实现吧。

首先就是注册命令,具体就不解读代码了,其逻辑就是获取调用vscode.window.showQuickPick弹出选择框选择 js 还是 ts 文件(自定义),接着获取到其目录,判断文件是否存在,创建文件等操作。

import * as vscode from 'vscode'
import * as fs from 'fs'export async function activate(context: vscode.ExtensionContext) {let disposable = vscode.commands.registerCommand('kuizuo-plugin.newFile', (uri: vscode.Uri) => {vscode.window.showQuickPick(['js', 'ts'], {}).then(async (item) => {if (!uri?.fsPath) {return}const filename = `${uri.fsPath}/demo.${item}`if (fs.existsSync(filename)) {vscode.window.showErrorMessage(`文件${filename}已存在`)return}fs.writeFile(filename, '', () => {vscode.window.showInformationMessage(`demo.${item}已创建`)vscode.window.showTextDocument(vscode.Uri.file(filename), {viewColumn: vscode.ViewColumn.Two, // 显示在第二个编辑器窗口})})})})context.subscriptions.push(disposable)
}export function deactivate() {}

然后再 keybindins 中添加一条

"keybindings": [{"command": "kuizuo-plugin.newFile","key": "shift+alt+n",}
],

然后就当我实现完功能的时候,我在想自带的新建文件是不是就是个 command?只是没有绑定快捷键? 于是我到键盘快捷方式中找到答案

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xwhqLr9G-1657644399885)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/416e33d36f34427d8731eb525dfe0aa8~tplv-k3u1fbpfcp-zoom-1.image)]

图中的explorer.newFile就是资源管理器右键新建文件的命令,只是没有键绑定。所以我只需要简单的加上shift + alt + n即可实现我一开始想要的快捷键功能,此时再次右键资源管理器新建文件右侧就有对应的快捷键。

此时的我不知该哭该笑,折腾半天的功能其实只是设置个快捷键的事情。

:::note

这些命令在 vscode 中作为内置命令Built-in Commands。要查看 vscode 所有命令的话,也可以通过vscode.commands.getCommands 来获取所有命令 ID,要在插件中执行也只需要调用vscode.commands.executeCommand(id)

:::

键盘快捷键(光标移动)

接着我就在想,既然很多 vscode 功能都是命令的形式,那是不是在插件级别就能做键盘映射,而不用让用户在 vscode 设置,很显然是可以的。只需要在 package.json 中 contributes 的 keybindings 中设置,就可以实现组合键来进行光标的移动。下面是我给出的答案

"keybindings": [{"command": "cursorUp","key": "shift+alt+i","when": "textInputFocus"},{"command": "cursorDown","key": "shift+alt+k","when": "textInputFocus"},{"command": "cursorLeft","key": "shift+alt+j","when": "textInputFocus"},{"command": "cursorRight","key": "shift+alt+l","when": "textInputFocus"},{"command": "cursorHome","key": "shift+alt+h","when": "textInputFocus"},{"command": "cursorEnd","key": "shift+alt+;","when": "textInputFocus"}]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cx7BFh5a-1657644399886)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6674f9018ec94ecdadf2fd11326768eb~tplv-k3u1fbpfcp-zoom-1.image)]

仔细看右侧来源就可以知道是没问题的,第一个为我之前设置的,而扩展则是通过上面的方法。

自定义扩展工作台

在 vscode 中有几个地方可以用于扩展,具体可看Extending Workbench | Visual Studio Code Extension API

  • 左侧图标(活动栏):主要有资源管理器、搜索、调试、源代码管理、插件

  • 编辑器右上角:代码分栏、code runner 的运行图标

  • 底部(状态栏):git、消息、编码等等

在 contributes 添加 viewsContainers 与 views,注意,views 的属性要与 viewsContainers 的 id 对应。

"viewsContainers": {"activitybar": [{"id": "demo","title": "愧怍","icon": "public/lollipop.svg"}]
},
"views": {"demo": [{"id": "view1","name": "视图1"},{"id": "view2","name": "视图2"}]
}

编辑器右上角是在 menus 中设置 editor/title,图标则是对应命令下设置,不然就是显示文字

"commands": [{"command": "kuizuo-plugin.helloWorld","title": "Hello World","icon": {"light": "public/lollipop.svg","dark": "public/lollipop.svg"}}
],
"menus": {"editor/title": [{"when": "resourceLangId == javascript","command": "kuizuo-plugin.helloWorld","group": "navigation"}],
}

至于底部状态栏,这里借用官方例子vscode-extension-samples/statusbar-sample at main · microsoft/vscode-extension-samples (github.com),最终效果如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HuPeeiRP-1657644399888)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9655a221920742009e4a7a082a4edab5~tplv-k3u1fbpfcp-zoom-1.image)]

那个

写一个VSCode插件相关推荐

  1. 如何写一个vscode插件

    1.运行yo code创建项目 2.选择使用yarn或者npm 3.运行 官网这个例子需要我们 ctrl + shirt + p 调出输入框, 然后在里面输入hello w 就可以如图所示 activ ...

  2. 编写一个VSCode插件

    原文链接: 编写一个VSCode插件 - 愧怍的小站 自从使用过 VSCode 后就再也离不开 VSCode,其轻量的代码编辑器与诸多插件让多数开发者爱不释手.同样我也不例外,一年前的我甚至还特意买本 ...

  3. 动手自己写一个 xcode 插件(Xcode Source Editor Extensions)附源码

    2019独角兽企业重金招聘Python工程师标准>>> 动手自己写一个 xcode插件  (暂时需要注释功能,所以简单的写一个注释插件) -----Xcode Source Edit ...

  4. [vue-cli]vue-cli3插件有写过吗?怎么写一个代码生成插件?

    [vue-cli]vue-cli3插件有写过吗?怎么写一个代码生成插件? MyPlugin.install = function (Vue, options) { // 1. 添加全局方法或属性 Vu ...

  5. 手把手写一个vscode翻译插件

    1. 背景 写这篇文章的初衷是看到vscode市场上的中英翻译插件都是将翻译结果以弹窗的形式做的,体验感非常不好.如果有像有道字典那种打开一个弹窗或者新tab的翻译面板来进行使用就好了.但是找了很久都 ...

  6. 软妹音程序员鼓励师24小时在线,只需一个VSCode插件,还能帮忙吐槽产品经理...

    Python实战社群 Java实战社群 长按识别下方二维码,按需求添加 扫码关注添加客服 进Python社群▲ 扫码关注添加客服 进Java社群▲ 鱼羊 郭一璞 发自 凹非寺 量子位 报道 | 公众号 ...

  7. 插件制作教程 php,typecho插件编写教程(二):写一个新插件

    第一节我们了解了一个插件的基本构成,下面我们需要一个实例练习巩固. 真赶巧,老高最近正在改版百度sitemap提交插件for typecho,下面和老高一起改版吧! 准备 不知道大家用过WP版的百度结 ...

  8. 一行代码写一个谷歌插件 —— Javascript

    回顾  前期   [提高代码可读性]-- 手握多个代码优化技巧.细数哪些惊艳一时的策略_0.活在风浪里的博客-CSDN博客代码优化对象策略https://blog.csdn.net/m0_579046 ...

  9. ROS nodelet-----编写一个nodelet插件

    1 nodelet插件编写和使用流程介绍 ROS nodelet插件和ROS中普通插件编写流程一样,因为它们都是借助plubinlib来实现插件动态加载,都必须follow pluginlib使用规则 ...

  10. 自己动手写一个JQuery插件(第二篇)(转)

    1.Hold住,我们要开始动真格了! 是的,看到这个标题,你一定也和我一样迫不及待了,因为我们不像之前那篇教程一样小打小闹了,我们现在要动真格了,这次我们要写的插件是上个插件的增强版本.而这个插件包含 ...

最新文章

  1. CRC原理及其逆向分析方法
  2. mysql忘记密码如何修改
  3. 对线程与进程的区别以及对多线程并发的理解
  4. Codeforces 786B Legacy (线段树优化建图)
  5. js mztreeview 双击事件_Mac下的Node.js安装教程
  6. C++ 初始化与赋值
  7. 华为Mate 40新功能上线,抬手即可付款!
  8. 卸载MySql详细步骤
  9. HDU 6127 Hard challenge (极角排序)
  10. 黑马程序员2022年最新软件测试学习路线
  11. RESTful 接口设计规范
  12. 震撼您心灵的四川雪山
  13. input 时分秒输入_JavaScript实现input框获取系统默认年月日时分秒
  14. C++程序设计(实践)_老师有话说 S1| 如何学好计算机程序设计(c语言)
  15. 案例:自动复制黏贴bat
  16. 打印********的平行四边形
  17. 国产CPU整体性能和发展情况一览表
  18. 用python建立两个Y轴的XY曲线图
  19. 狂神说Java全栈学习路线
  20. 相控阵雷达阵列天线仿真计算

热门文章

  1. css相对单位和绝对单位
  2. 从内存池到连接池 老码农眼中的资源池
  3. 已解决-Windows10没有windows照片查看器-Windows10打开照片是黑底的
  4. 工作频率对系统功率、穿透能力、设备体积、系统性能的影响
  5. 什么是全国大学生电子设计大赛?如何备战?
  6. samba 指定的网络名不再可用
  7. 学习A-level课程能申请哪些国家
  8. tf SavedModel 保存模型的新方式
  9. 华为手机像素密度排行_「屏幕像素密度」(全解析)屏幕尺寸,分辨率,像素,PPI之间到底什么关系? - seo实验室...
  10. 计算机内存的存储单位换算,电脑内存换算(电脑内存单位及换算)