零基础入门vscode插件开发(以console.log加前缀为例)

3,471 阅读5分钟

前言

console.log是window上的一个常用方法,该函数可以把各种信息打印输出到浏览器控制台,以便开发者进行调试、定位问题。

在代码量很少的情况下,多次使用console.log,开发者还能勉强在控制台找到自己想要的信息。eg:

var student={
  name:"zhangsan",
  age:12
}
console.log(student.name)
var teacher={
  name:"zhangsan",
  age:21
}
console.log(teacher.name)
/**
*控制台输出
* zhangsan
* zhangsan
* 巧了,老师和学生同名了,没关系,控制台第一行输出的是学生姓名,第二行输出的是老师姓名,反正我能区分出来。
*/

在代码量比较多、团队合作的项目中,大量的consol.log被调用,控制台简直惨不忍睹,信息虽然很多,但很难找到自己输出的那个,为了解决这个问题,很多开发者都会在打印信息的前面加上前缀进行区分。eg:

// 还用上面的student和teacher举栗
console.log("student.name=======",student.name)
console.log("teacher.name=======",teacher.name)
...
/**
*控制台输出
* student.name======= zhangsan
* teacher.name======= zhangsan
* 简直就是一个字,"清爽"
*/

爽是爽了,可是还有一个问题,加前缀对于开发人员来说可是个体力活,写起来很累。于是就有了本次需求(实现这种加前缀打印的功能),因为现在大部分前端开发人员都使用vscode,所以就基于vscode编辑器开发这样一个插件,实现解决痛点并提高开发效率的小目标。

准备工作

  1. npm install yo generator-code -g
  2. yo code
  3. 根据提示完成命令行交互

ok,一个vscode插件项目的脚手架就生成了!

目录结构介绍

整个目录结构比较简单,重点关注package.jsonextension.js这两个文件。

目录
.
├── CHANGELOG.md 
├── README.md 
├── extension.js // 入口
├── jsconfig.json 
├── node_modules 
├── package-lock.json
├── package.json // 项目配置
├── test
└── vsc-extension-quickstart.md 
package.json
{
	...略
	"activationEvents": [ // 激活事件列表
		"onCommand:extension.helloWorld" // 表示extension.helloWorld这个插件只能通过命令的方式激活
	],
	"main": "./extension.js",  // 入口文件
	"contributes": { // 贡献点
		"commands": [{ // 命令列表
        "command": "extension.helloWorld", // 命令的名称,必须和入口文件中注册的名称保持一致
				 "title": "Hello World"  // 通过命令面板调用时的名称 
		}]
	},
	...略
}
extension.js
const vscode = require('vscode');

// 插件被激活时调用
// context是一个插件的上下文环境
function activate(context) {
  // 通过registerCommand API 注册命令 
  // 参数extension.helloWorld必须和package.json中的保持一致
  // 返回一个disposable对象
	let disposable = vscode.commands.registerCommand('extension.helloWorld', function () {
		// 通过showInformationMessage API 弹窗展示信息
    vscode.window.showInformationMessage('Hello World!');
	});
  // 把disposable对象加入上下文的订阅列表中
	context.subscriptions.push(disposable);
}
exports.activate = activate;

// 插件被停止时调用
function deactivate() {}

// 导出该模块
module.exports = {
	activate,
	deactivate
}

hello world跑起来

生成的项目自带一个hello world插件的demo,供开发人员借鉴。用vscode打开刚才生成的项目,按下键盘上的F5键进入调试模式,这时候会打开一个新窗口供插件运行,在新窗口中按下command+shift+p键打开命令面板,输入在package.json中定义命令时title对应的值,这时候编辑器右下角就会弹出一条内容为Hello World!的信息。试着把extension.js中的代码做一些修改,重启一下调试模式,就会看到相应的变化。

###站在巨人的肩膀上

通过上面的介绍,就可以进行插件的开发和调试了,直接在官方demo上进行扩展和修改。继续在package.jsonextension.js这两个文件上做文章。

package.json中主要修改项目的基本配置,比如名称、版本、命令等,增加一些额外的配置项,比如代码仓库、命令快捷键列表、发布者等,以下是package.json 中修改和新增的内容。

{
    "name": "vscode-prefix-log", // 插件的名称
    "displayName": "vscode-prefix-log", // 在扩展市场中插件的名字
    "description": "console with prefix", // 对插件的描述
    "version": "0.0.1", // 版本
    "repository": { // 关联的代码管理库 repository最好配置上,否则在插件发布的时候会警告
        "type": "git",
        "url": "https://github.com/xxx/vscode-prefix-log"
    },
    "activationEvents": [
        "onCommand:console.with.prefix"
    ],
    "main": "./extension.js",
    "contributes": {
        "commands": [
            {
                "command": "console.with.prefix",
                "title": "prefix.log"
            }
        ],
        "keybindings": [ // 命令快捷键列表 除了在命令面板输入title,也可以使用快捷键触发命令
            { 
                "command": "console.with.prefix",
                "key": "shift+d", // 快捷键
                "when": "editorTextFocus" // 当编辑器的文本在聚焦的时候快捷键才起作用
            }
        ]
    },
  	"publisher": "xxx" // 发布者
  	...略
}

extension.js 保持代码结构不变,重写activate方法,因为要开发的插件是跟编辑器文本相关,所以主要用到了vscode中跟文本编辑相关的API,比如onDidChangeActiveTextEditorgetWordRangeAtPosition等。

function activate(context) {
    console.log('Congratulations, your extension "vscode-prefix-log" is now active!');
    // 获取当前编辑器对象
    let currentEditor = vscode.window.activeTextEditor;
    // 当编辑器文本变化时,重置编辑器对象
    vscode.window.onDidChangeActiveTextEditor(editor => (currentEditor = editor));
		// 注册命令
    const disposable = vscode.commands.registerTextEditorCommand('console.with.prefix', () => {
        new Promise((resolve, reject) => {
            let sel = currentEditor.selection; // 获取选中区域
            const reg = /[\S]+\.(log)$/; // 规定匹配log的正则
            // 通过getWordRangeAtPosition方法得到单词范围对象
            let ran = currentEditor.document.getWordRangeAtPosition(sel.anchor, reg);
            if (ran == undefined) {
                reject('please use this statements:xxx.log');
            } else {
                let doc = currentEditor.document; // 获取当前文档对象
                let line = ran.start.line; // 获取行数
                let item = doc.getText(ran); // 通过getText方法获取文本
                let prefix = item.replace('.log', '');
                // 获取当前行的第一个非空字符的偏移量
                let idx = doc.lineAt(line).firstNonWhitespaceCharacterIndex; 
                let wrapData = {
                    idx,
                    ran,
                    line,
                    txt: `console.log('${prefix}========',${prefix});`
                };
                resolve(wrapData);
            }
        }).then(wrap => {
                currentEditor
                .edit(e => {
                    // 将旧文本替换成新文本 主要的功能就是靠这行代码实现
                    e.replace(wrap.ran, wrap.txt);
                }).then(() => {
                    // 把光标定位到末尾
                    currentEditor.selection = new vscode.Selection(
                        new vscode.Position(wrap.line, wrap.txt.length + wrap.idx),
                        new vscode.Position(wrap.line, wrap.txt.length + wrap.idx)
                    );
               });
          }).catch(message => {
          		console.log('REJECTED_PROMISE:' + message);
          });
    });
    context.subscriptions.push(disposable);
}

接下来,保存代码,按下F5键进行调试,结果如下图。

插件发布及使用

插件开发好了,小伙伴们怎么才能使用呢,简单的方法就是直接将项目copy到vscode的扩展目录中,重启下vscode就可以使用了(只能小范围使用)。比较推荐的做法是将开发好的插件通过vsce这个工具发布到vscode的应用市场,类似于把node包发布到npm上,首次发布稍微会有点繁琐,具体流程可以参考网上的一篇博文。当在控制台看到如下提示就表明发布成功了。

DONE  Published xxx.vscode-prefix-log@0.0.7
Your extension will live at https://marketplace.visualstudio.com/items?itemName=zhangleilei.vscode-prefix-log 
(might take a few seconds for it to show up).

发布成功后,就可以在vscode的应用市场通过名字找到插件了,只要是vscode用户都可以愉快的安装并使用了。

后语

有兴趣的同学可以基于此插件进一步扩展,比如打印的时候输出文件名、行号等信息,这样就可以精准定位了。本文最多算一篇入门科普,如果想要把事情搞大,那就去多看看vscodeAPI和别人家开发的插件代码。

代码地址 github.com/qinhangong/…