从0到1实现一个属于自己的VScode插件

从0到1实现一个属于自己的VScode插件

VScode是微软推出的一款轻量级代码编辑器,也是前端开发中常用的编辑器,其设计思想就是拓展性,VScode的大部分功能都可以自定义实现,通过 Extension API扩展实现,很多VScode的核心功能就是这样实现的,我们自然也可以利用VScode开放API进行扩展功能的开发,从而解决我们日常开发中的一些问题,提高开发效率。 通过本文讲解,我们可以快速了解如何开发一个VS Code插件,实际操作起来还是挺简单的,遇到不熟悉或者疑问之处可以查看官方文档,文档内容写的十分全面。

文章内容若有不足,欢迎指正。

1. VScode插件是什么?

VScode是微软推出的一款轻量级代码编辑器,免费、开源而且功能强大,也是前端开发中常用的编辑器,我们作为一个前端开发者,对于此编辑器自然不陌生。在使用时我们经常会安装一些插件来协助我们进行开发,这些插件就是利用VScode给我们提供的一些开放的API的基础上进行扩展功能的开发,从而解决我们日常开发中的一些问题,提高开发效率。VScode 插件其实就是类似于一个npm包的vsix文件。

vscode插件开发的官方文档为:code.visualstudio.com/api

2. VScode插件可以做什么?

VScode插件几乎可以自定义我们的VScode编辑器的任意功能,例如:

  • 自定义命令、快捷键、菜单;
  • 自定义跳转、自动补全、悬浮提示
  • 自定义颜色、图标主题
  • 代码高亮、语法高亮、检查、格式化等
  • 扩展工作台
  • 编辑器相关(修改编辑器语言、通知、状态栏等)
  • git 功能页面可视化
  • 。。。。。。

3. 如何创建一个属于自己的插件

上文已经简单阐述了 VScode插件是什么以及可以做什么,下面我们就来实际操作一下,做一个行动上巨人。

3.1 环境搭建

微软官方给我们提供了脚手架,通过这个脚手架我们可以快速的搭建一个简单的VScode插件。

因为npm官网安装依赖可能会有点慢,也可能安装失败,所以推荐使用阿里或腾讯镜像源仓库,具体配置命令如下:

arduino 复制代码
// 设置依赖安装镜像源为淘宝镜像源(使用者较多,推荐)
npm config set registry https://registry.npmmirror.com/


// 设置依赖安装镜像源为腾讯内部镜像源(不需要腾讯内网也能正常访问)
npm config set registry https://mirrors.tencent.com/npm/

通过执行下方命令安装微软官方脚手架:

css 复制代码
npm i -g yo generator-code

上述命令其实安装了两个包(yo和generator-code),这两个包用途如下:

  • yo模块全局安装后就安装了Yeoman,Yeoman是通用型项目脚手架工具,可以根据一套模板,生成一个对应的项目结构

  • generator-code模块是VS Code扩展生成器,与yo配合使用才能构建项目。

上述命令执行后出现如下页面表示安装成功,可以继续执行后续操作

3.2 使用脚手架搭建一个基础的VScode插件模版

在本地的工作目录中执行下方命令使用脚手架创建插件模版项目

css 复制代码
yo code

创建项目会开启一个交互命令行,需要先选择插件类型,控制键盘的方向键的上下来决定选择什么类型,按 Enter 键确认

根据自己的实际需求来选择你想创建的插件类型,目前支持以下几种类型:

  1. New Extension (TypeScript) :ts 语法的项目,基础版,内置了hello world的命令

  2. New Extension (JavaScript) : js 语法的项目,基础版,内置了hello world的命令

  3. New Color Theme :主题项目,内置了主题,可用来自定义主题

  4. New Language Support:语言支持项目,内置了语法支持配置,可用来支持特殊语言

  5. New Code Snippets:代码片段项目,内置了代码片段配置,可用来配置代码片段,输入触发字符,快速生成代码片段

  6. New Keymap:快捷键项目,内置了快捷键配置,可用来自定义快捷键行为

  7. New Extension Pack:插件集合项目,内置了插件集合配置,可用于定制插件集,达到快速安装一组插件

  8. New Language Pack (Localization):目前官方文档暂未查到localizations贡献的场景点

  9. New Web Extension (TypeScript) : ts语法的项目, 在 VS Code for Web (包括vscode.dev和github.dev) 以及桌面和GitHub Codespaces等服务将支持该扩展

  10. New Web Extension (JavaScript) : js 语法的项目,在 VS Code for Web (包括vscode.dev和github.dev) 以及桌面和GitHub Codespaces等服务将支持该扩展

web扩展可参考官方文档链接 code.visualstudio.com/api/extensi...

使用脚手架创建模版项目步骤详解如下图所示:

注意:插件名必须全小写,且不能有空格

选择不同的插件类型时,下方交互命令行选择填写的条例不同,此处仅以创建一个ts模版项目和创建一个快捷键项目为例,其他的插件类型的大同小异,都是一些前端开发中使用到的配置,看一下就知道要怎么选择了。

  • 使用脚手架创建一个ts的模版项目
  • 使用脚手架创建一个插件类型为快捷键模版项目

3.3 package.json文件详解

字段名 说明
name 插件名(要求全小写,无空格)
displayName 发布到 VS Code 应用市场名称
version 插件版本
publisher 发布者
engines vscode或其他环境依赖版本的要求
categories 扩展类别
contributes 插件贡献点,比如命令、快捷键、菜单等
activationEvents 插件触发动作,如在打开某种语言的文件时、当某个命令被触发时

执行命令后生成的模板项目的package.json文件如下:

json 复制代码
{
  "name": "ggg-test",
  "displayName": "ggg-test",
  "description": "哈哈哈哈,一个小demo",
  "version": "0.0.1",
  "engines": {
    "vscode": "^1.85.0"
  },
  "categories": [
    "Other"
  ],
  "activationEvents": [],
  "main": "./dist/extension.js",
  "contributes": {
    "commands": [
      {
        "command": "ggg-test.helloWorld",
        "title": "Hello World"  
      }
    ]
  }
}

3.3.1 activationEvents 配置项详解

activationEvents 配置项配置插件的激活数组,即在什么情况下插件会被激活,目前支持以下8种配置:

  • onLanguage: 当打开解析为某种语言的文件时触发

  • onCommand: 当调用对应命令时触发

  • onDebug: 在 debug 调试会话开始前,将发出此激活事件并激活感兴趣的扩展

  • onDebugInitialConfigurations: 在 debug 初始化配置之前触发

  • onDebugResolve: 在 debug 设置处理完之前触发

  • workspaceContains: 当打开文件夹并且该文件夹至少包含一个与glob 模式匹配的文件时触发

  • onFileSystem:当读取特定类型或协议中的文件或文件夹时触发

  • onView: 每当 VS Code 侧边栏中展开指定 id 的视图时触发,并激活感兴趣的扩展(扩展或源代码管理是内置视图的示例)

  • onUri: 在基于 vscode 或 vscode-insiders 协议的 url 打开时触发

  • onWebviewPanel: 每当 VS Code 需要恢复具有匹配的webview时触发,并且将激活感兴趣的扩展 viewType

  • onCustomEditor: 需要创建具有匹配的自定义编辑器时触发

  • onAuthenticationRequest: 当扩展请求具有匹配的身份验证会话(通过 API)时触发。注意:从 VS Code 1.74.0 开始,您的扩展提供的身份验证提供程序不需要相应的onAuthenticationRequest激活事件声明来激活您的扩展。

  • onStartupFinished: 在VS Code 启动后一段时间触发,类似于 * ,但不会减慢 VS Code 的启动速度,

  • *: 在启动 VS Code 时触发,为了保证良好的用户体验,非必须情况下不建议使用此配置

注意:一个扩展可以监听多个激活事件

注意:扩展 必须 activate()从其主模块导出一个函数,并且当发出任何指定的激活事件时,VS Code 仅会调用该函数一次。此外,扩展应该 deactivate()从其主模块导出一个函数,以便在 VS Code 关闭时执行清理任务。如果清理过程是异步的,则扩展必须返回 Promise 。如果清理同步运行,则 deactivate()扩展可能会返回 undefineddeactivate()

3.3.2 contributes(贡献点)配置详解

contributes 配置项是整个插件的贡献点,表明这个插件有什么功能。

  • breakpoints: 断点

  • colors: 主题颜色

  • commands: 命令,通过 control + shift + p 打开命令窗口进行输入来实现的。

  • configuration: 通过这个配置项我们可以设置一个属性,这个属性可以在vscode的settings.json中设置,然后在插件工程中可以读取用户设置的这个值,进行相应的逻辑。

  • configurationDefaults: 配置可以在 setting.json 文件中配置的字段

  • customEditors: 自定义编辑器

  • debuggers: 提供一个调试器

  • grammars: 可以在这个配置项里设置描述语言的语法文件的路径,vscode可以根据这个语法文件来自动实现语法高亮功能

  • icons: 按 ID 提供新图标以及默认图标

  • iconThemes: icon主题色

  • jsonValidation: 为特定类型的 json 文件提供验证架构

  • keybindings: 快捷键绑定

  • languages: 设置语言特点,包括语言的后缀等

  • menus: 自定义编辑器菜单,包括右键菜单、头部菜单等

  • problemMatchers: 问题匹配器模式

  • problemPatterns: 问题匹配器中使用的命名问题模式

  • productIconThemes: 产品图标主题

  • resourceLabelFormatters: 资源标签格式化程序,指定如何在工作台中的任何位置显示 URI

  • semanticTokenModifiers: 新的语义标记修饰符,可以通过主题规则突出显示

  • semanticTokenScopes: 语义标记类型和修饰符以及范围之间的映射,作为后备或支持特定于语言的主题

  • semanticTokenTypes: 可以通过主题规则突出显示的新语义标记类型

  • snippets 特定语言的片段,设置语法片段相关的路径

  • submenus: 子菜单作为可以贡献菜单项的占位符,子菜单要求在父菜单中显示 label

  • taskDefinitions: 定义一个对象文字结构,该结构允许唯一地标识系统中的贡献任务

  • terminal: 终端

  • themes 颜色主题

  • typescriptServerPlugins: 提供 TypeScript 服务器插件,增强 VS Code 的 JavaScript 和 TypeScript 支持

  • views: 配置活动栏对应的view视图

  • viewsContainers: 可以贡献自定义视图的视图容器

  • viewsWelcome: 引导页,向自定义视图贡献欢迎内容

  • walkthroughs: 演练由标题、描述、ID 和一系列步骤组成。此外,还可以设置 when 条件来根据上下文键隐藏或显示演练。

3.4 extension.js文件详解

extension.js是插件工程的入口文件,即 package.jsonmain字段对应的文件(文件名可根据自己需要更改,只需要保证和package.json中main字段对应即可),当插件被激活,即触发package.json中的activationEvents配置项时,extension.js文件开始执行。

extension.js文件将导出两个方法:activatedeactivate,其执行时机如下所示:

  • activate: 插件被激活时执行的函数

  • deactivate: 插件被销毁时调用的方法,比如释放内存等

extension.js中对需要的功能进行注册,主要使用vscode.commands.register...相关的api,来为package.json中的contributes配置项中的事件绑定方法或者监听器。 vscode.commands.register...相关的api主要有:

  • vscode.commands.registerCommand() 注册命令

  • vscode.languages.registerCompletionItemProvider() 代码补全

  • vscode.languages.registerCodeActionsProvider() 注册一个代码操作提供者

  • vscode.languages.registerCodeLensProvider()

  • vscode.languages.registerHoverProvider() 代码悬浮提示

vscode.commands.registerCommand用于注册命令,ggg-test.helloWorld为命令ID,需要与 package.json文件中的 contributes.commands数组中的 command后的配置一致,第二个参数为一个回调函数,当触发该命令时,弹出提示框。

执行命令后生成的模板项目的extension.js文件如下:

javascript 复制代码
// 引入 vscode 核心库,提供了开发插件所需的大部分 api
import * as vscode from 'vscode';

// 当插件被激活触发
export async function activate(context: vscode.ExtensionContext) {

	console.log('Congratulations, your extension "ggg-test" is now active!');

	// 调用vscode注册命令API,注册了一个名(命令唯一标识)为 ggg-test.helloWorld的命令
  // 注意,此处注册的命令必须和 package.json文件中的 contributes.commands数组中的 command 命令配置的一致
	let disposable = vscode.commands.registerCommand('ggg-test.helloWorld', () => {
		// 执行命令,会在右下角展示提示信息
		vscode.window.showInformationMessage('Hello World from ggg-test!');
	});
    // 事件入栈
	context.subscriptions.push(disposable);
}

// 当插件停用时触发
export function deactivate() {}

3.4.1 写一个简单的小弹窗提示

extension.js文件如下:

javascript 复制代码
// 引入 vscode 核心库,提供了开发插件所需的大部分 api
import * as vscode from 'vscode';
// 引入  node 中的 os 模块,下面使用 platform 方法获取系统
import * as os from 'os';

import { exec } from 'child_process';

// 当插件被激活触发
export async function activate(context: vscode.ExtensionContext) {

	console.log('Congratulations, your extension "ggg-test" is now active!');
	const key = 'sweetheartPlugin.showTip';
	const showTip = vscode.workspace.getConfiguration().get(key);
	if (showTip) {
		const result = await vscode.window.showInformationMessage('是否要打开作者个人网页?', '是', '否', '不再提示');
		if (result === '是') {
			const commandOperation = os.platform() === 'win32' ? `start https://sweetheartjq.cn/` : `open https://sweetheartjq.cn/`;
			exec(commandOperation);
		} else if (result === '不再提示') {
			//最后一个参数,为true时表示写入全局配置,为false或不传时则只写入工作区配置
			await vscode.workspace.getConfiguration().update(key, false, true);
		}
		
	}

	// 调用vscode注册命令API,注册了一个名(命令唯一标识)为 ggg-test.helloWorld的命令
    // 注意,此处注册的命令必须和 package.json文件中的 contributes.commands数组中的 command 命令配置的一致
	let disposable = vscode.commands.registerCommand('ggg-test.helloWorld', () => {
		// 执行命令,会在右下角展示提示信息
		vscode.window.showInformationMessage('Hello World from ggg-test!');
	});
    // 事件入栈
	context.subscriptions.push(disposable);
}

// 当插件停用时触发
export function deactivate() {}

package.json文件如下:

json 复制代码
{
  "name": "ggg-test",
  "displayName": "ggg-test",
  "description": "哈哈哈哈,一个小demo",
  "version": "0.0.1",
  "engines": {
    "vscode": "^1.85.0"
  },
  "categories": [
    "Other"
  ],
  "activationEvents": [],
  "main": "./dist/extension.js",
  "contributes": {
    "commands": [
      {
        "command": "ggg-test.helloWorld",
        "title": "Hello World"  
      }
    ],
    "configuration": {
    "title": "sweetheart-plugin",
        "properties": {
            "sweetheartPlugin.showTip": {
                "type": "boolean",
                "default": true,
                "description": "是否在每次启动时显示提示?"
            }
        }
    }
  }
}

3.5 VScode插件生命周期

VSCode的插件都运行在一个独立的进程里, 被称为 Extension Host, 它加载并运行插件, 让插件感觉自己好像在主进程里一样, 同时又严格限制插件的响应时间, 避免插件影响主界面进程。

  • 1.activationEvents:在package.jsonactivationEvents配置项中设置插件激活时机,这里设置的是onCommand:ggg-test.helloWorld,即输入命令onCommand:ggg-test.helloWorld时激活。

  • 2.contributespackage.json中的contributes配置项表示这个插件增加了哪些功能,这里设置了commands,表示增加的命令,在这一项中声明了一个命令ggg-test.helloWorld

  • 3.Register:在 extension.js 文件中的 activate(context)方法中,使用vscode.commands.registerCommand()这一API为命令ggg-test.helloWorld绑定事件,绑定的事件为vscode.window.showInformationMessage('Hello World from ggg-test!'),即弹出弹框,显示 Hello World from ggg-test!

  • 4.在命令框中输入 ggg-test.helloWorld,此时插件被激活,进入extension.js中执行activate()方法,由于已经在contributes配置项中声明了命令ggg-test.helloWorld,所以在activate()方法中为该命令绑定一个事件,由于在命令框中输入了这个命令,所以命令绑定的事件立即被触发执行,所以在vscode的右下角弹出了弹出框。

3.6 发布插件到 VS Code 拓展商店

    1. 在本地安装 vsce(Visual Studio Code Extension)依赖
css 复制代码
npm i -g vsce
    1. VS Code 使用 Azure DevOps 作为其 Marketplace 服务。所以需要登录一下 Azure。登录后,如果之前没用过的话会要求创建一个组织,默认为邮箱前缀, Azure 网址,在 Azure上获取一个 access token ,在下面创建发布者时需要用到
    1. 创建一个发布者
scss 复制代码
vsce create-publisher (publisher name)
// publisher name 为 package.json 中的 publisher字段的值
// 执行后,会让输入 Personal Access Tokens
// 将上面创建好的 Personal Access Tokens 输入
    1. 登录刚才创建的发布者
java 复制代码
vsce login (publisher name)
    1. 打包
go 复制代码
vsce package
    1. 发布

    vsce publish

4. 实现一个格式化 git Commit message 的插件

在我们的日常开发中,git相关操作是每天都要接触的,属于一个高频操作,我们或许会使用以下方式来提交我们的代码

  • git 原生命令

  • WebStorm 或 VS code 自带git工具

  • 类似于 sourceTree之类的第三方工具

  • ......

但根据不同公司的不同业务场景,代码提交格式也有不同的规范,我们手动操作不可避免的会出现问题,此时一个可以帮助我们搞定git 提交信息的插件就显得尤为重要了。

4.1 效果展示

4.2 插件获取

  • 插件目前已发布到 VS Code 插件应用市场,可通过在扩展商店中直接搜索 devops-commitizen 获取
  • 可在 VS Code官方应用市场下载安装

marketplace.visualstudio.com/items?itemN...

  • 可通过github仓库下载打包之后的 vsix 文件,目前最新版本为 V1.1.1,但 vsix 文件不能直接拖入安装,只能从扩展的右上角选择 Install from VSIX 来安装,github地址可在下方获取

4.3 代码获取

格式化 git Commit message 插件devops-commitizen代码已在github开源,有需要源码参考的可下载查看,若有不足之处,欢迎指正。

5. 参考资料

相关推荐
小彭努力中9 分钟前
7.Three.js 中 CubeCamera详解与实战示例
开发语言·前端·javascript·vue.js·ecmascript
浪裡遊1 小时前
跨域问题(Cross-Origin Problem)
linux·前端·vue.js·后端·https·sprint
LinDaiuuj1 小时前
判断符号??,?. ,! ,!! ,|| ,&&,?: 意思以及举例
开发语言·前端·javascript
敲厉害的燕宝1 小时前
Pinia——Vue的Store状态管理库
前端·javascript·vue.js
Aphasia3111 小时前
react必备JavaScript知识点(二)——类
前端·javascript
玖玖passion1 小时前
数组转树:数据结构中的经典问题
前端
呼Lu噜2 小时前
WPF-遵循MVVM框架创建图表的显示【保姆级】
前端·后端·wpf
珠峰下的沙砾2 小时前
Vue3 里 CSS 深度作用选择器 :global
前端·javascript·css
航Hang*2 小时前
WEBSTORM前端 —— 第2章:CSS —— 第3节:背景属性与显示模式
前端·css·css3·html5·webstorm
wuhen_n2 小时前
CSS元素动画篇:基于当前位置的变换动画(一)
前端·css·html·css3·html5