内容简介:为vscode编写扩展
vscode 是个超级好用的开发工具,谁用谁知道。
背景故事
一个项目开发、维护的时间久了之后,总会多多少少碰到一段不是你写的,而现在你要维护,但你却看不明白的那是什么鬼的代码;当然有时候也可能是多人在同一个项目里协作开发时,对于bug最终责任人的确诊问题(找到最终责任人不是要“修理他”。帮助他认识问题,提高自身能力,加深团队协作意识才是重点)。
大多数人都用 git ,也知道git里诸如: git log , git blame 等命令都可以帮我们做到以上需求,可每次看到一段代码之后,先从 IDE 里切换到 Terminal 下,然后敲打命令,并且要记好事故代码的行号,以及准确的文件路径,敲来敲去还是挺烦人的。
于是,能在不来回切换工作环境的情况下,迅速找到某一段代码的作者、写作时间、写作目的就显的还是有点用了。
一个扩展的诞生
写作思路
为了更直观表达这个扩展的设计思路,我用了一个图:
后面我们就根据图里描述的思路来开展工作。
获取信息
要得到一段指定行号(行区间)代码的信息,大家都知道用 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-git-blamer
项目源码地址: vscode-git-blamer
以上所述就是小编给大家介绍的《为vscode编写扩展》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- (全栈学习实践)三、创建php、添加扩展,其他Dockerfile编写
- Just for fun——PHP7扩展编写中的宏
- DockOne微信分享(二六五):如何基于 OAM 编写一个扩展 Trait?
- 使用 Dingo API 扩展包快速构建 Laravel RESTful API(二) —— 编写第一个 API 接口
- 在项目文件 / MSBuild / NuGet 包中编写扩展编译的时候,正确使用 props 文件和 targets 文件
- 基于顺丰同城接口编写sdk,java三方sdk编写思路
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Dreamweaver基础教程
李振华、季小武、季小武、李振华 / 清华大学 / 2005-6 / 23.00元
本书通过实例的方式介绍了Macromedia公司的Dreamweaver MX 2004的使用方法和技巧。 全书由14章组成,第1章和第2章介绍了软件的应用领域、知识结构、界面组成等;第3章到第12章是本书的重点部分,通过实例制作介绍了站点的建立,表格、文本及样式的创建,链接、图像、行为的使用,层、表单、框架的创建和使用以及动画、多媒体的制作等主要知识点;第13章和第14章介绍了插件技......一起来看看 《Dreamweaver基础教程》 这本书的介绍吧!