内容简介:为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编写思路
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Beginning ASP.NET 4 in C# and Vb
Imar Spaanjaars / Wrox / 2010-3-19 / GBP 29.99
This book is for anyone who wants to learn how to build rich and interactive web sites that run on the Microsoft platform. With the knowledge you gain from this book, you create a great foundation to ......一起来看看 《Beginning ASP.NET 4 in C# and Vb》 这本书的介绍吧!
URL 编码/解码
URL 编码/解码
html转js在线工具
html转js在线工具