背景
经常在掘金公司团队发文章,而所在公司前端发文存在自己的固定格式,主要包含:
- ([\u4e00-\u9fa5]+)([\da-zA-Z]+)替换为$1 $2:中文和英文要有一个空格;
- ([\da-zA-Z]+)([\u4e00-\u9fa5]+)替换为$1 $2:中文和英文要有一个空格;
- !\[.+\]替换为![]:处理图片描述;
- 头部插入主题,内容如下:
---
theme: cyanosis
highlight: atom-one-dark
---
> 自我介绍
这些动作每次需要人为处理,费时费力且易出错,固化流程尝试改用 vscode 插件自动实现,遂有 edit-article 插件出现;
相关链接
贴下相关链接,可以直接down下来看看,如有类似需求可以留言提需求我来完成。(也求 star)
- github:https://github.com/Sympath/edit-article-plugin
- vscode 市场:edit-article
当前实现效果
本文目标
实现一款自己的 vscode 插件并发布在应用市场,所有人可以在 vscode 扩展中搜索并下载;由于文章目标是实现效果,所以不打算用自己实现的 edit-article 插件作为案例。
- 思路:vscode 插件是个node应用,那我们只需要找到对应的脚手架创建基础,再实现我们插件特定的功能即可。
- 本文 demo 插件功能:快捷键反转选中的字符串。
- 实现效果:
实战系列文章专注产出,看一个东西出现的满足感是会上瘾的,让我们抛弃文档式的学习,开始吧!
脚手架创建基础模板
安装及使用
首先你需要的是 yeoman,一个脚手架工具。通过 yeoman 你可以快速创建代码模板,如下所示:
npm install -g yo
然后你需要安装 VS Code 的模板:
npm install -g generator-code
有了脚手架,你就可以创建一个 VS Code 的插件模板了。接下来运行:
yo code myextension
请注意,第三个参数将是你新创建的插件的文件夹名字。
VS Code 插件脚手架介绍
由上图,你可以看到有七个插件模板:
- 前两个是通过编程来提供插件功能,你可以选择 TypeScript 或者 JavaScript,结果都是类似的,因为 TypeScript 最后也需要被编译成 JavaScript 再发布;
- 第三个是主题插件,你可以将你自己创建的主题分享给其他人;
- 第四个是语言支持,也就是语法高亮、语言定义等;
- 第五个是代码片段的分享;
- 第六个则是分享快捷键;
- 第七个就是对多个插件进行组合分享。
先实现最基础的New Extension (JavaScript),即javascript版模板。
接下来,你会依次被提示输入插件的名字、介绍、想要用哪个账号发布、是否要打开 type check 以及是否要使用 git 等。你可以暂时按照我的样例进行输入,之后也可以再根据需要修改。
项目基础信息介绍
切换到项目根目录;
cd myextension
项目目录结构及对应信息;’
├── .vscode
│ ├── launch.json // 插件加载和调试的配置
│ └── tasks.json // 配置 TypeScript 编译任务
├── .gitignore // 忽略构建输出和 node_modules 文件
├── README.md // 插件文档
├── CHANGELOG.md // 插件更新日志
├── extension.ts // 插件源代码
├── package.json // 插件配置清单
├── jsconfig.json //
查看效果
启动默认项目,按下F5启动调试,如果打开了一个vscode新窗口,试试打开命令面板执行hello world,如果执行出现了弹窗,就说明我们创建 vscode 插件项目成功啦。
命令面板唤起快捷键
- mac:cmd + shift + p
- win:ctrl + shift + p
关于面板的更多信息可以阅读:你不知道的 vscode 之空间控制。
实现业务 -- 反转字符串
我们在之前已经知道了怎么用脚手架创建 vscode 插件项目,接下来就是实现我们自己的业务逻辑了。本章目标只有两个。
功能:实现命令【选中文字反转字符串】
- package.json 中注册命令和对应的描述;
- extension.js 中完成命令的实现。
优化:绑定快捷键
注意:建议在 launch.json 中的“args”中添加"--disable-extensions",阻止其他插件加载,不然要调试的插件加载很慢。
命令的注册:package.json
我们先了解下【命令的注册】,先说流程
- package.json 中注册命令和对应的描述
- extension.js 中完成命令的实现
package.json 中注册命令和对应的描述
在package.json中存在contributes对象,有属性commands对应着命令数组,每个命令是一个对象有如下属性
- command:命令的 key,在命令的实现中会被用到
- title:命令描述,会出现在命令面板中
配置如下:
"commands": [
{
"command": "edit-article.reserve",
"title": "Hello reserve"
}
],
配置完成!
命令的实现:extension.js
前置总结
- package.json中通过配置activationEvents,定义插件的激活时机。
- 项目根路径的extension.js文件中通过active钩子注册命令和对应的实现。
激活时机:activationEvents
我们的业务逻辑实现在项目根路径的extension.js文件中,默认导出两个钩子方法。
- activate:插件激活时
- deactivate:插件关闭时
module.exports = {
activate,
deactivate,
};
这里的激活时机并不是一打开 vscode 就执行,而是需要在package.json中存在一个属性activationEvents,值是一个数组,存储着所有会触发插件激活的时机;改为打开 js 文件时才会激活,配置如下:
"activationEvents": [
"onLanguage:javascript"
],
业务逻辑实现
extension.js文件中还引入了一个vscode对象,这是 vscode 提供能力的载体,我们在后面单独分析。
const vscode = require("vscode");
这里的 active 函数实现的逻辑很清晰。首先,我们要读取的信息就是当前的文档信息和主光标的信息。
let document = editor.document;
let selection = editor.selection;
有了这两个信息,读取光标选中的内容就简单了。
let text = document.getText(selection);
document 一共哪些 API 这里我就不介绍了,相信你可以自己探索,这里我们使用就是 getText,以获取某段代码。
接下来就是将这段文本进行反转了,我们可以写一个非常简单的版本,将字符串分割成字母数组,然后反转,最后重新组合成字符串。
let result = text.split('').reverse().join('');
最后一步操作就是将原来编辑器内的文本进行替换了。此时我们就要用到 edit 这个 API 函数 了。值得注意的是,这个 API 的第一参数,是一个 callback,callback 的参数是 editBuilder,也就是真正用于修改代码的对象。
editBuilder 有以下几个 API:
- delete
- insert
- replace
- setEndOfLine
这里我们要使用的当然就是 replace 了。
editBuilder.replace(selection, result);
我们只需将原先的 selection 里的内容,替换成新的 result 即可。
完整代码如下:
on, result);
});
}
);
context.subscriptions.push(reserve);
}
function deactivate() {}
module.exports = {
activate,
deactivate,
};
至此,如何注册一个命令我们也就了解到了,当我们要实现其他功能,自然重点就成了vscode这个对象,在文末【扩展】模块分享。
优化:绑定快捷键
实现绑定
支持我们完成了命令的设定、命令的实现,但每次都要自己找命令面板去执行;如果我们能用一个快捷键绑定命令,按下快捷键就执行,会不会方便很多?说干就干!
在package.json的contributes中还存在keybindings属性,就是用于实现绑定快捷键的,这是一个对象数组,存储的对象结构如下:
- key:快捷键
- command:命令
- when:何时触发
假定我们将反转命令绑定在ctrl+shift+r上,就可以添加如下内容:
"keybindings": [
{
"key": "ctrl+shift+r",
"command": "edit-article.reserve"
}
]
實現效果
发布插件
终于,到了最激动人心的时刻!还记得第一次在浏览器上看到我们页面时的激动吗?再一次,让我们回到那个瞬间。按后文一步步走,遇到过按别人文章走结果遇问题卡一半的痛苦,所以详细(啰嗦)了点,大家多担待,无论如何,结果亲测有效!
要发布,先创建账号
Visual Studio Code 的应用市场基于微软自己的Azure DevOps;所以需要在两个平台都注册好账号。有账号后,根据 Azure DevOps 平台生成PAT(Personal Access Token,个人访问令牌);根据应用市场创建发布者账号,有了这两者就能发布了。
整理如下:
- 注册账号;
- 根据 Azure DevOps 平台生成PAT(Personal Access Token,个人访问令牌);
- 根据应用市场创建发布者账号;
- 根据 vsce 在本地发布。
根据 Azure DevOps 平台生成 token
登录 Microsoft
首先访问Microsoft 官网登录你的Microsoft账号,没有的先注册一个:
中间会要求输入邮箱,没有也可以直接通过手机号获取一个;
一路 next,直到创建成功。
登录 Azure
然后访问:Azure 官网 ,如果你从来没有使用过 Azure,那么会看到如下提示:
点击继续,默认会创建一个以邮箱前缀为名的组织。(只需要填写验证码即可)
创建令牌
默认进入组织的主页后,点击右上角的Security:
点击创建新的个人访问令牌,这里特别要注意
- Organization要选择`all accessible organizations``
- ``Scopes要选择Full access
否则后面发布会失败。
创建令牌成功后你需要本地记下来,因为网站是不会帮你保存的。
根据应用市场创建发布者账号
访问应用市场,填完名称,滑到最后保存即可。
至此,我们就有了如下内容:
- PAT:Personal Access Token,个人访问令牌
- publisher:发布者账号
就可以执行在本地发布的动作啦!
根据 vsce 在本地发布
进入自己的插件,如果没有,可以阅读【插件脚手架:如何创建一个插件】了解创建。
配置插件信息
在发布前,我们需要配置一些项目信息在 package.json 中,下面是必备信息
- publisher:发布者 id;
- activationEvents:扩展的激活事件,建议先填指定文件类型激活(如 js 文件,onLanguage:javascript)配置项可见官网文档;
- repository:仓库地址。
其他还有很多配置,我们慢慢了解,文末放置 package.json 配置总览。
安装命令包
利用发布工具发布插件
vsce是一个用于将插件发布到市场上的命令行工具。
请确认本机已经安装了Node.js,然后运行:
npm install -g vsce
然后你就可以在命令行里直接使用vsce了。下面是一个快速发布的示例:
- 登陆
vsce login [publisherName]
# 然后输入之前获取到的 token
- 执行发布(这里的 patch 是指自动更新版本后发布,不带也可以,就得手动修改package.json文件了)。
$ vsce publish patch
Publishing uuid@0.0.1...
Successfully published uuid@0.0.1!
完成后过几分钟就可以去 vscode 的扩展区看自己的插件啦!
查看结果
一图胜千言,静静体会成就感的美妙吧!
尾声
至此,阅读本文的小伙伴应该已经在插件市场上可以找到自己的插件啦。
老规矩,分享一个感悟:重视你的、甚至是别人的每一个吐槽,尝试解决它,这就是成长。
扩展知识:package.json 配置总览
// package.json
{
"name": "vscode-demo",
"displayName": "vscode-demo",
"description": "",
"version": "0.0.1",
"repository":"",// 仓库地址
"publisher": "", //发布者 id,后面会讲怎么发布到插件市场
"engines": { //vscode 最低版本
"vscode": "^1.57.0"
},
"categories": [ //插件市场的分类 可以设置成语言主题等其他类型
"Other"
],
"activationEvents": [ //扩展的激活事件
"onCommand:vscode-demo.helloWorld", //调用命令时激活
"onLanguage:python", //py 时激活插件
"workspaceContains:**/.editorconfig",// 文件夹打开时激活
"onDebug",//调试前激活
...
"*" //启动时候激活,使用这个不需要设置其他的
],
"main": "./extension.js", //指定插件入口文件
"icon": "", //插件图标
"contributes": { //大部分的配置都要在这里配置
"commands":[], //配置命令,如果需要暴露给用户使用的需要在这里配置
"menus":[], //配置菜单
"submenus":[], //配置子菜单会用到
"languages": [], //配置语言
"grammars":[], //为语言配置 TextMate 语法
"keybindings":[], //配置快捷键
"snippets":[], //配置代码片段
"themes":[], //配置主题
"views":[], //配置活动栏视图
"viewsWelcome":[], //配置左侧视图欢迎页
"viewsContainers":[], //配置视图容器
"configuration":{}, //配置插件配置
"configurationDefaults":{}, //配置插件默认配置
"colors":{},
"problemMatchers":{},
"taskDefinitions":{},
"typescriptServerPlugins":{}
},
}
扩展知识:vscode 发布相关
发布钩子
预发布步骤
可以在清单文件中添加预发布步骤,下面的命令会在插件每次打包时执行:
{
"name": "uuid",
"version": "0.0.1",
"publisher": "joaomoreno",
"engines": {
"vscode": "0.10.x"
},
"scripts": {
"vscode:prepublish": "tsc"
}
}
上面的示例会在每次插件打包时调用 Typescript 编译器。
增量更新插件版本
用 SemVer 语义标识符:major(最大位加一),minor(次位加一),patch(最小位加一)增量更新插件版本号。
例如,你想把插件从 1.0.0 更新到 1.1.0,那么加上minor:
vsce publish minor
插件package.json的 version 会先更新,然后才发布插件。
你也可以通过命令行指定版本号:
sce publish 2.0.1
更多可用的命令参数,请使用vsce --help
扩展知识:vscode 提供能力
获取编辑器对象
既然是编辑器相关的命令,那么我们肯定需要能够访问到编辑器,以及其中的内容。首先我们要获取的就是:当前工作区内,用户正在使用的编辑器。
const vscode = require('vscode');
let editor = vscode.window.activeTextEditor;
我们重点关注的也是这个对象。
有了这个编辑器,我们就能获取非常多的信息了。不过先别急,editor 这个变量并非一定总是有效的值,比如用户现在并没有打开任何文件,编辑器是空的,那么此时 editor 的值就是 undefined。所以, 在正式使用 editor 之前,我们要判断一下,editor 是否为 undefined,是的话就结束命令的运行。
if (!editor) {
return;
}
接下来,我们可以输入 editor.,自动补全立刻给我们提示了不少的属性。
编辑器对象能力
- document,也就是当前编辑器中的文档内容;
- edit,用于修改编辑器中的内容;
- revealRange,用于将某段代码滚动到当前窗口中;
- selection,当前编辑器内的主光标;
- selections,当前编辑器中的所有光标,第一个光标就是主光标,后面的则是用户创建出来的多光标;
- setDecorations,设置编辑器装饰器(我会在后面的章节专门介绍这个 API 的使用)。