从零实现一个vscode插件
[toc]
vscode插件是什么
vscode作为一个微软推出的轻量级代码编辑器,为了在保证轻量的基础上又能够满足开发者日益复杂的开发要求,vscode开放了一些API提供给开发者进行扩展功能的开发,这种插件化的思想使编辑器更加轻量,另一面能充分利用社区的力量,提供给更多多元化的插件。
vscode插件能做什么
通用功能
可以在任何拓展中使用的核心功能:
- 能够添加命令、配置项、快捷键、菜单项、右键菜单
- 存储工作区或者全局数据
- 展示通知消息
- 使用快速选择收集用户输入
- 打开文件选择器让用户去选择文件或文件夹
主题化
可以控制vscode外观,包括编辑器代码颜色和vscode UI颜色,主要包括三种主题颜色:
- 颜色主题:其允许修改vscode 组件以及文本的颜色
- 文件图标主题:可修改文件在vscode中显示的图标
- 产品图片主题:在整个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),这两个包用途如下:
- yo模块全局安装后就安装了Yeoman,Yeoman是通用型项目脚手架工具,可以根据一套模板,生成一个对应的项目结构
- generator-code模块是VS Code扩展生成器,与yo配合使用才能构建项目。
项目文件目录
其中最重要的是入口文件
extension.ts和package.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文件
该文件会导出两个方法
activate,deactivate:
activate: 插件被激活时执行。deactivate: 插件被销毁时执行。
实战
现在开始打造一个自己的vscode 插件,功能如下:
- 选择文本,点击右键选择菜单选项中英互译。
- 选择文本,快捷键中英互译。
修改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实例中增加了对应命令指令函数SelectTranslation和provideHover;
// 悬浮翻译
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);
}
- 悬浮指令函数中会传入2个参数
document文档元素实例和position悬浮定位,可以通过参数获取文档内容word,然后通过封装的翻译函数FormCnToEn将获取的文档内容转换翻译。 - 选择文本指令会传入2个参数
textEditor编辑控件实例和edit文本编辑器,通过编辑控件获取选中的文本然后通过封装的翻译函数FormCnToEn将获取的文档内容转换翻译,然后通过new vscode.SnippetString(txt)创建新的代码片段,并将其插入。
发布
插件开发完成以后我们需要把开发的插件分享给其他人使用,目前有3种方法:
- 直接把文件夹发给别人,让别人找到vscode的插件存放目录并放进去,然后重启vscode。
- 将插件打包成vsix插件,发给别人安装使用。
- 注册开发者账号,将插件发布到官方应用市场。
这里我们使用第二种方式打包插件
- 安装对应的打包模块:
npm i vsce -g
- 使用vsce进行打包,生成vsix文件
vsce package
然后扩展插件选择从vsix安装:
安装完成后就可以直接使用了:
总结
在开发过程中合理的利用工具能更好的提高我们的开发效率,vscode自定义插件能让我们根据自身的开发环境开发合适的插件,从而提高我们的效率。 最后附上插件地址