从零实现一个vscode插件

2,260 阅读6分钟

从零实现一个vscode插件

[toc]

vscode插件是什么

vscode作为一个微软推出的轻量级代码编辑器,为了在保证轻量的基础上又能够满足开发者日益复杂的开发要求,vscode开放了一些API提供给开发者进行扩展功能的开发,这种插件化的思想使编辑器更加轻量,另一面能充分利用社区的力量,提供给更多多元化的插件。

vscode插件能做什么

通用功能

可以在任何拓展中使用的核心功能:

  1. 能够添加命令、配置项、快捷键、菜单项、右键菜单
  2. 存储工作区或者全局数据
  3. 展示通知消息
  4. 使用快速选择收集用户输入
  5. 打开文件选择器让用户去选择文件或文件夹

主题化

可以控制vscode外观,包括编辑器代码颜色和vscode UI颜色,主要包括三种主题颜色:

  1. 颜色主题:其允许修改vscode 组件以及文本的颜色
  2. 文件图标主题:可修改文件在vscode中显示的图标
  3. 产品图片主题:在整个UI中使用的一组图标

声明性语言特性

声明性语言功能为编程语言添加了基本的文本编辑支持,例如括号匹配、自动缩进和语法突出显示

程序语言特性

编程语言功能添加了丰富的编程语言支持,例如悬停、转到定义、诊断错误、IntelliSense 和 CodeLens。

扩展工作台

工作台是指包含标题栏、活动栏、侧边栏、控制板、编辑组、状态栏等UI组件的整体Visual Studio Code UI。VS Code提供了各种API,允许将自己的组件添加到工作台。

调试

可以通过编写将 VS Code 的调试 UI 连接到特定调试器或运行时的调试器扩展来利用 VS Code 的调试功能。

项目实战

初始化

官方为了方便开发人员进行vscode插件的开发,提供了对yo应的脚手架来生成对应的项目。

// 安装需要的包
npm install -g yo generator-code
// 运行
yo code

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

  1. yo模块全局安装后就安装了Yeoman,Yeoman是通用型项目脚手架工具,可以根据一套模板,生成一个对应的项目结构
  2. generator-code模块是VS Code扩展生成器,与yo配合使用才能构建项目。

项目文件目录

image 其中最重要的是入口文件extension.tspackage.json依赖文件

package.json

package.json文件是vscode的扩展清单文件,里面有许多官方定义的字段:

{
    {
	"name": "vscodeplugin",     // 插件名称
	"displayName": "VscodePlugin",  //插件市场上的名称
	"description": "",      //具体描述
	"version": "0.0.1",     // 版本号
	"engines": {
		"vscode": "^1.54.0"     //最低支持的vscode版本号
	},
	"categories": [
		"Other"                 //拓展类别
	],
	"activationEvents": [
		"*"                     // 激活事件组,在那些事件下激活插件
	],
	"main": "./out/extension.js", // 入口文件
	"contributes": {                // 贡献点
		"commands": [                  // 命令
			{
				"command": "select.translation",
				"title": "File State"
			}
		],
		"menus": {                      // 菜单栏
			"editor/context": [             // 编辑器上下文
				{
					"when": "editorFocus",    // 什么时候可以触发
					"command": "select.translation",  // 触发的命令
					"group": "navigation"           // 菜单的位置
				}
			],
			"explorer/context": [               // 左侧文件上下文
				{
					"command": "getFileState",
					"group": "navigation"
				}
			]
		}
	},
	"scripts": {
		...
	},
	"devDependencies": {
		...
	},
	"dependencies": {
		...
	}
}

}

上述清单文件中最重要的三个属性mian,activationEvents,contributes:

1 .main

项目主入口文件。

2. activationEvents

指明该插件在何时会被激活,只有激活的插件才能使用,下面是官网的部分激活时机:

  • onLanguage: 打开解析为特定语言文件时被激活,例如"onLanguage:javascript"
  • onCommand: 在调用命令时触发
  • onDebug: 在启用调试器前激活
  • onDebugInitialConfigurations:
  • onDebugResolve
  • workspaceContains: 每当一个文件夹被打开且该文件夹包含至少一个匹配glob模式的文件时,就会触发此激活事件。
  • onFileSystem: 每当读取来自特定方案的文件或文件夹时
  • onView: 每当在 VS Code 侧栏中展开指定 id 的视图
  • onUri: 每当打开该扩展的系统范围的 Uri 时
  • onWebviewPanel
  • onCustomEditor: 每当VS Code需要创建一个带有匹配viewType的自定义编辑器时,这个激活事件就会触发
  • onAuthenticationRequest
  • onStartupFinished: 这个激活事件被触发,感兴趣的扩展将在VS Code启动一段时间后被激活
  • * 只要一启动vscode,插件就会被激活
3.contributes
  • commands 命令
  • configuration 配置
  • menus 编辑器或资源管理器命令菜单项
  • ...

extension.js文件

该文件会导出两个方法activatedeactivate:

  1. activate: 插件被激活时执行。
  2. deactivate: 插件被销毁时执行。

实战

现在开始打造一个自己的vscode 插件,功能如下:

  1. 选择文本,点击右键选择菜单选项中英互译。
  2. 选择文本,快捷键中英互译。

修改package.json

{
    "activationEvents": [
		"*"
	],
	"main": "./out/extension.js",
	"contributes": {
		"commands": [
			{
				"command": "select.translation",
				"title": "翻译"
			}
		],
		"menus": {
			"editor/context": [
				{
					"when": "editorHasSelection",
					"command": "select.translation",
					"alt": "select.translation",
					"group": "navigation"
				}
			]
		},
		"keybindings": [
			{
				"command": "select.translation",
				"key": "ctrl+m",
				"mac": "ctrl+m"
			}
		]
	},
}

入口文件主要代码

// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
import { provideCompletionItems, provideHover, SelectTranslation } from './provideCompletionItems';

export function activate(context: vscode.ExtensionContext) {
	
	console.log('插件已经被激活');
	// 选择文本翻译
	const opt = vscode.commands.registerTextEditorCommand("select.translation", SelectTranslation)

    // 悬浮翻译提示
	context.subscriptions.push(vscode.languages.registerHoverProvider('*', {
		provideHover
	}));
	context.subscriptions.push(vscode.languages.registerCompletionItemProvider('javascript', {
		provideCompletionItems: provideCompletionItems,
		resolveCompletionItem: () => null
	}, '.'));
	context.subscriptions.push(opt);


}

// this method is called when your extension is deactivated
export function deactivate() {}

上面代码中分别向vscode实例中增加了对应命令指令函数SelectTranslationprovideHover;

// 悬浮翻译
export async function provideHover(document:vscode.TextDocument, position:vscode.Position) {
  const word = document.getText(document.getWordRangeAtPosition(position));
  const res = await FormCnToEn(word);
  const content = JSON.parse(res.content);
  const txt = CapitalizeAndRemoveSpaces(content?.trans_result[0]?.dst);
  return new vscode.Hover(`* **中文:**:${word}\n* **英文:**:${txt}\n`);
}


// 首字母大写并且去除空格
function CapitalizeAndRemoveSpaces(str: string):string {
  let result = str?.split(" ").reduce((pre, cur) => pre + cur[0].toUpperCase() + cur.substring(1), '');
  return result;
}

// 选择翻译中文
export async function SelectTranslation(textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit) {
  const text = textEditor.document.getText(textEditor.selection);
  const res = await FormCnToEn(text);
  const content = JSON.parse(res.content);
  const txt = CapitalizeAndRemoveSpaces(content?.trans_result[0]?.dst);
  const value = new vscode.SnippetString(txt);
  const line = textEditor.document.lineCount;
  console.log(textEditor.document.lineAt(line - 1).range);
  // 插入文本
  textEditor.insertSnippet(value, textEditor.document.lineAt(line).range);
}
  1. 悬浮指令函数中会传入2个参数document文档元素实例和position悬浮定位,可以通过参数获取文档内容word,然后通过封装的翻译函数FormCnToEn将获取的文档内容转换翻译。
  2. 选择文本指令会传入2个参数textEditor编辑控件实例和edit文本编辑器,通过编辑控件获取选中的文本然后通过封装的翻译函数FormCnToEn将获取的文档内容转换翻译,然后通过new vscode.SnippetString(txt)创建新的代码片段,并将其插入。

发布

插件开发完成以后我们需要把开发的插件分享给其他人使用,目前有3种方法:

  1. 直接把文件夹发给别人,让别人找到vscode的插件存放目录并放进去,然后重启vscode。
  2. 将插件打包成vsix插件,发给别人安装使用。
  3. 注册开发者账号,将插件发布到官方应用市场。

这里我们使用第二种方式打包插件

  1. 安装对应的打包模块:
npm i vsce -g
  1. 使用vsce进行打包,生成vsix文件
vsce package

image

然后扩展插件选择从vsix安装:

image

安装完成后就可以直接使用了:

image

总结

在开发过程中合理的利用工具能更好的提高我们的开发效率,vscode自定义插件能让我们根据自身的开发环境开发合适的插件,从而提高我们的效率。 最后附上插件地址