为vscode编写扩展

栏目: 编程工具 · 发布时间: 7年前

内容简介:为vscode编写扩展

vscode 是个超级好用的开发工具,谁用谁知道。

背景故事

一个项目开发、维护的时间久了之后,总会多多少少碰到一段不是你写的,而现在你要维护,但你却看不明白的那是什么鬼的代码;当然有时候也可能是多人在同一个项目里协作开发时,对于bug最终责任人的确诊问题(找到最终责任人不是要“修理他”。帮助他认识问题,提高自身能力,加深团队协作意识才是重点)。

大多数人都用 git ,也知道git里诸如: git loggit blame 等命令都可以帮我们做到以上需求,可每次看到一段代码之后,先从 IDE 里切换到 Terminal 下,然后敲打命令,并且要记好事故代码的行号,以及准确的文件路径,敲来敲去还是挺烦人的。

于是,能在不来回切换工作环境的情况下,迅速找到某一段代码的作者、写作时间、写作目的就显的还是有点用了。

一个扩展的诞生

写作思路

为了更直观表达这个扩展的设计思路,我用了一个图:

为vscode编写扩展

后面我们就根据图里描述的思路来开展工作。

获取信息

要得到一段指定行号(行区间)代码的信息,大家都知道用 git blame ,展示结果如下:

»git blame -L 10,11 js/index.js

297cb0df (Howard.Zuo 2017-03-08 21:58:03 +0800 10)     render(h) {
297cb0df (Howard.Zuo 2017-03-08 21:58:03 +0800 11)         return h(Game);

少了,"写作目的",也就是说,这个命令的结果无法告诉我们作者提交这段代码时的 commit message 写了什么。于是我得翻翻 git blame --help ,可喜的是被我找到了 --line-porcelain 选项,在她的描述里看到了这么一句: but output commit information for each line 。好像有戏,来试试看:

»git blame -L 10,11 js/index.js --line-porcelain

297cb0df8ab1fe06ee935798d1a2dd4e712a070d 10 10 2
author Howard.Zuo
author-mail <leftstick@qq.com>
author-time 1488981483
author-tz +0800
committer Howard.Zuo
committer-mail <leftstick@qq.com>
committer-time 1488981503
committer-tz +0800
summary fix duplicate key issue
previous 43966e5cc4c70998c265781fe8acf02946c28f6e js/index.js
filename js/index.js
        render(h) {
297cb0df8ab1fe06ee935798d1a2dd4e712a070d 11 11
author Howard.Zuo
author-mail <leftstick@qq.com>
author-time 1488981483
author-tz +0800
committer Howard.Zuo
committer-mail <leftstick@qq.com>
committer-time 1488981503
committer-tz +0800
summary fix duplicate key issue
previous 43966e5cc4c70998c265781fe8acf02946c28f6e js/index.js
filename js/index.js
            return h(Game);

不错,这明显是个可以被解析的数据结构。所以获取信息就靠她了 git blame -L <start,end> <filePath> --line-porcelain

因为 vscode 是一个基于 electron 开发的 IDE ,所以 node.js 的API对我们是可用的,于是可以通过如下代码执行上面的命令,并且拿到结果数据:

//vscode api,获取当前正在操作的编辑页面
const editor = vscode.window.activeTextEditor;
if (!editor) {
    vscode.window.showWarningMessage('You have to active a file first');
    return;
}

//拿到鼠标选择的内容
const selection = editor.selection;

//合成git命令
const cmd = `git blame -L ${selection.start.line + 1},${selection.end.line + 1} ${editor.document.fileName} --line-porcelain`;

//通过child_press执行该命令,
child_process.exec(cmd, {
    cwd: vscode.workspace.rootPath
}, (error, stdout, stderr) => {
    //这里的stdout就是上面我们看到的输出内容了
});

解析信息

看了上面的输出内容,我们需要一个model来描述一个这样一个 条目 :

export interface Item {
    hash: string;
    shortHash: string;
    author: string;
    authorEmail: string;
    authorTime: number;
    authorTz: string;
    committer: string;
    committerEmail: string;
    committerTime: number;
    committerTz: string;
    commitMessage: string;
    previousCommit?: string;
    fileName: string;
    change: string;
}

接下来就是如何解析 git 命令的输出结果了,一个大大的循环来搞定:

export function parse(output: string): Array<Item> {
    const lines = output.replace(/\r\n/mg, '\n').split('\n');

    const commits: Array<Item> = [];

    let commit;

    for (let i = 0; i < lines.length - 1; i++) {
        const line = lines[i];
        
        //一个item的开始标志就是commit的hash
        if (/^[a-z0-9]{15,}/.test(line)) {
            commit = {};
            commits.push(commit);
            commit.hash = line.split(' ')[0];
            commit.shortHash = commit.hash.substring(0, 8);

        } else if (/^author\s/.test(line)) {
            commit.author = line.split(' ')[1];
        } else if (/^author-mail\s/.test(line)) {
            commit.authorEmail = line.split(' ')[1];
        } else if (/^author-time\s/.test(line)) {
            commit.authorTime = +line.split(' ')[1];
        } else if (/^author-tz\s/.test(line)) {
            commit.authorTz = line.split(' ')[1];
        } else if (/^committer\s/.test(line)) {
            commit.committer = line.split(' ')[1];
        } else if (/^committer-mail\s/.test(line)) {
            commit.committerEmail = line.split(' ')[1];
        } else if (/^committer-time\s/.test(line)) {
            commit.committerTime = +line.split(' ')[1];
        } else if (/^committer-tz\s/.test(line)) {
            commit.committerTz = line.split(' ')[1];
        } else if (/^previous\s/.test(line)) {
            commit.previousCommit = line.split(' ')[1];
        } else if (/^filename\s/.test(line)) {
            commit.fileName = line.split(' ')[1];
        } else if (!commit.fileName) {
            commit.commitMessage = line;
        } else {
            commit.change = line;
        }
    }

    return commits;
}

展示

有了上面解析完毕的 Array<Item> ,简单转换一下字符串,对任何人都是没什么难度的:

export function pretty(commits: Array<Item>): string {
    return commits.map(c => {
        return `${c.shortHash} ${c.author} ${formatDate(c.authorTime * 1000)} "${c.commitMessage}" ${c.change}`;
    })
        .join('\n');
}

解决了所有核心问题,剩下的就是按照 vscode-docs ,动手补充一个扩展需要的额外因素了。

安装代码骨架生成器

npm install -g yo generator-code

生成插件项目

yo code

在提问中,依次回答所有问题,最后项目骨架生成。

生成右键菜单

修改 package.json ,增加/修改 contributes 字段:

"contributes": {
    "menus": {
        "editor/context": [{
            "command": "extension.gitblame",
            "group": "sourcecontrol",
            "when": "config.git.enabled && scmProvider == git && gitState == idle"
        }]
    },
    "commands": [{
        "command": "extension.gitblame",
        "title": "Git blame",
        "key": "ctrl+b"
    }],
    "keybindings": [{
        "command": "extension.gitblame",
        "key": "alt+b"
    }]
}

于是乎,一个右键选项 Git blame 就会出现在你选择一段代码后的右键菜单里

懒加载扩展

一个扩展根据需求,并不一定要随 vscode 的启动而启动,那样影响 vscode 的整体性能,而且没什么特别的好处。所以我们要懒加载。修改 package.json ,增加/修改 activationEvents 字段:

"activationEvents": [
    "onCommand:extension.gitblame"
]

只有当用户使用 extension.gitblame 这个命令时(也就是在右键菜单里选择了 Git blame 时),该扩展才正式激活。

到此为止,这个扩展就基本完成了。效果如下:

为vscode编写扩展

扩展下载地址: vscode-git-blamer

项目源码地址: vscode-git-blamer


以上所述就是小编给大家介绍的《为vscode编写扩展》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

程序员实用算法

程序员实用算法

Andrew Binstock、John Rex / 陈宗斌 / 机械工业出版社 / 2009-9 / 65.00元

《程序员实用算法》重点关注的是实用、立即可用的代码,并且广泛讨论了可移植性和特定于实现的细节。《程序员实用算法》作者介绍了一些有用但很少被讨论的算法,它们可用于语音查找、日期和时间例程(直到公元1年)、B树和索引文件、数据压缩、任意精度的算术、校验和与数据验证,并且还最全面地介绍了查找例程、排序算法和数据结构。 《程序员实用算法》结构清晰,示例丰富,可作为广大程序员的参考用书。一起来看看 《程序员实用算法》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具