前言
在日常的代码开发中,总会遇到很多很小的知识点,想用却无从记起。尤其是在日常的前端开发,想要添加一个自己想要的css样式,却又想不起属性名,然后再css网站和笔记中搜索。当时想,如果能在IDE中内嵌一个AI编程助手就好了。
后来GitHub推出了Copilot,再后来腾讯云基于混元大模型,推出了腾讯云AI代码助手。在惊喜之余,更多的是想要体验一下腾讯云AI代码助手的功能。
开发需求
以前都是用IDEA做代码开发,但是IDEA太占内存,所以最近在朋友的推荐下,开始尝试使用vscode做前端开发。但是在开发中发现一个问题:vscode不和IDEA一样的是,在一个字符或者变量后面紧跟.log,无法自动补全为console.log。
我在IDEA可以自动补全console.log:
而在vscode中,却无法使用.log生成console.log,只能输入console.log,然后通过腾讯云AI编程助手的自动补全功能,补全括号和其中的变量部分:
vscode有着丰富的插件,同时也给开发者提供了独立开发插件的功能。虽然我对vscode插件开发没有涉猎过,但是这次想借着腾讯云AI代码助手的“东风”,看我是否可以从零基础,独自开发一个vscode的插件,实现IDEA中console.log的功能。
腾讯云AI代码助手
首先我们先在vscode中安装腾讯云AI助手的插件。在vscode插件市场中搜索腾讯云AI代码助手下载安装。
安装之后在下方就能看到AI助手的图标,点击即可使用。
腾讯云AI代码助手除了提供完善的自动补全代码、根据注释生成代码、代码解释、生成测试代码、转换代码语言、技术对话等能力,还内置了很多对话快捷指令,在对话输入框中输入 / 或 @ 就可调用快捷指令:
- /clear:清空当前会话。
- /comments:为所选的代码添加文档注释。
- /newNotebook:创建一个新的 Jupyter 笔记本。
- /explain:解释所选代码的工作原理。
- /fix:针对所选代码中的问题提出修复方案。
- /tests:为所选代码生成单元测试。
- /nameVariable:变量命名。
- @vscode:询问 VS Code。
- @terminal:询问如何在终端中执行某些操作。
- @workspace:询问您的工作空间,将自动引用当前代码。
插件开发环境准备
询问腾讯云AI代码助手创建vscode插件的流程:
根据给出的代码安装vocode插件的开发依赖和环境。在腾讯云AI代码助手给出的操作代码中,我们无需再通过选中,然后CTRL + C复制,在代码助手中提供了辩解的一键复制功能。
然后在terminal中执行代码,创建过程中根据提示操作,最后打包方式选择unbundled。
这样,vscode创建项目就创建完成。在src中只生成了一个extension.ts文件,猜测这就是vscode插件的代码文件。
选中代码,使用腾讯云AI代码助手的代码解释(Explain code),来解释一下代码。
从下图中可以看出,上面操作与在对话框中直接输入 @workpace /explain 的快捷指令效果相同。
通过腾讯云AI代码助手的代码解释,明白了extension.ts是如何定义插件的。对于开发者要做的就是在vscode.commands.registerCommand接口中,定义插件的逻辑代码即可。
代码语言:typescript
复制
const disposable = vscode.commands.registerCommand('test.helloWorld', () => {
// 在这里编写插件的功能代码
vscode.window.showInformationMessage('Hello World from aqi!');
});
context.subscriptions.push(disposable);
}
在给出的模板代码中,插件功能主题是vscode.window.showInformationMessage,在vscode中展示提示信息,提示信息我改成了“Hello World from aqi!”。
而test.helloWorld就是插件注册的命令,调用这个命令就可以执行插件的功能。同时,也需要在package.json声明这个命令。
其中title意味着在命令界面输入Hello World,就可以调用这个插件命令。
运行插件
第一次使用vscode,第一次开发vscode插件,还是要求助腾讯云AI代码助手:如何在vscode中运行自己开发的插件。
F5启动vscode的debug,进入Extension Development Host页面。
然后使用快捷键Ctrl + Shift + P调出命令面板,输入Hello World就可以执行插件命令。
执行Hello World之后,可以从上图右下角看到执行结果,弹出了"aqi"的消息提示框。至此,在腾讯云AI编程助手的助力下,关于vscode插件的开发环境搭建、开发框架以及运行流程都已经完成,接下来就是继续实现我们的console.log的需求。
插件功能实现接口
我在github搜索vscode插件项目的时候,搜到了一个名叫quickly-log的插件,看介绍是将光标放在变量后面,通过快捷键实现log补全的功能。我感觉这个项目和我的需求十分吻合,然后我就把代码pull下来,学习一下人家是如何实现功能的。
运行插件
pull代码之后,运行插件体验quickly-log的功能。根据项目的README所写,此插件一共提供了三个功能,目前我只触发了前两个功能。
1. 生成console.log
quickly-log插件中,将光标放在变量后面,然后使用CTRL + SHIFT + L快捷键,就自动将生成console.log(),并在括号中的输入内容中回填变量。
2. 清除console.log
使用Ctrl + Shift + K快捷键,就可以删除编辑器中所有console.log的语句。
阅读代码
从quickly-log生成console.log的功能来看,虽然和我想要的最终结果不一样,但是对同样都是对vscode编辑器的文本输入进行了监听,以及代码的插入。所以我打算阅读这部分代码,来了解插件中对于vscode编辑器的接口是如何实现的。
1. 获取编辑器对象
通过对quickly-log项目结构的分析,生成console.log的核心代码如下。
我大概看了一下代码,猜测window.activeTextEditor就是我想要获取的vscode的编辑器对象,后面的document、selection都是编辑器对象的一些属性。为了验证自己的猜想,我使用腾讯云AI代码助手求证。
2. 获取插入行号
然后就是获取在编辑器中,要插入console.log的行号,getInsertLine就实现了这个功能。
先调用getLineText,根据行号调用document的lineAt,就可以获取到当前行的代码。
那么形参中行号line是怎么来的?
其实在上面quickly-log生成console.log的演示中,是将光标放在了变量的后面,所以通过编辑器的selection.active属性,获取当前光标所在的行号就可以了。
同样,对于selection.active想希的解释,可以求助腾讯云AI代码助手。
最后在getInsertLine中,将line + 1,表示将console.log插入到光标所在行的下一行。
同时,我在阅读获取代码缩进位置的实现方法getStartSpace时,编辑器波浪线标识出代码不规范,这里我使用腾讯云AI代码助手的快速修复(Quick Fix)功能,直接生成规范符合要求的代码。
同时,AI代码助手还“兼职”接口文档的功能,遇到不懂的方法,选中会弹出详细的方法描述。
在腾讯云AI代码助手的帮助下,我迅速阅读完了quickly-log的逻辑功能代码。
基本功能开发
接下来就是我在extension.ts中,实现自己预期生成console.log的代码逻辑。
1.获取当前行代码
同样,在registerCommand中注册一个logCompletion命令,然后获取vscode的编辑器对象。在获取了编辑器对象之后,通过document和selection分别获取编辑器的文档对象和当前行。
然后使用腾讯云AI代码助手的注释生成代码功能,直接生成获取光标所在行文本的代码。如图所示,变量lineText代表的就是当前行我输入的代码。
2. 替换.log
例如我输入的是"aqi".log,所以我要进行判断,如果代码以.log结尾,那么就将前面的变量填充到console.log中,即让其变成console.log("aqi");
代码语言:typescript
复制
if (lineText.endsWith('.log')) {
const logText = lineText.substring(0, lineText.length - 4);
const logStatement = `console.log(${logText});`;
editor.edit(editBuilder => {
const range = new vscode.Range(line.range.start, line.range.end);
editBuilder.replace(range, logStatement);
});
}
通过对当前行的代码lineText进行substring,去掉最后的四个字符,即.log。然后将结果字符串(即.log前面的字符)拼接到logStatement对象中。
最后使用vscode.Range的对象,选定当前行的所有内容,然后将当前行的所有代码替换成console.log。
3. 定义快捷键
最后就是在package.json中声明logCompletion命令,并在keybindings中将其快捷键定义为CTRL + SHIFT + H。
4. 运行结果
输入"aqi".log,然后按下CTRL + SHIFT + H快捷键,如图所示实现了console.log的功能。
但是这里出现了两个问题:
- 括号内“aqi”前面有空格(缩进)
- 代码没有缩进
所以下一步就是对这两个问题进行优化。
5. 优化缩进问题
个人猜测问题1出现的原因是,在获取获当前代码logText时,调用substring的起始下标是从0开始的,所以将前面的缩进(空格)也带进去了,所以我们调用trim()或者trimStart()去掉前面的空格就行了。
去掉代码缩进
我将问题抛给了AI代码助手,果然和我猜测的原因一致。在AI代码助手给出的代码块右上方,除了一键复制功能的功能,还能将代码一键插入到编辑器中。
这样就成功解决了问题1。
获取代码缩进index
至于问题2,生成的console.log直接定格没有缩进,原因是在创建用于表明替换范围的vscode.Range时,使用line.range.start作为起始坐标,line表示一行代码,在编辑器中一行代码的起始坐标肯定是0。所以,要想办法获取到缩进结尾的index,以此作为Range的起始范围。
这时候再次使用腾讯云AI代码助手的注释声成代码功能。
最终,通过firstNonWhitespaceCharacterIndex获取到缩进结尾的index。然后使用腾讯云AI代码助手生成修改偏移量的代码。
优化后代码
对上面的代码进行合并之后,最终的优化代码如下:
代码语言:typescript
复制
if (lineText.endsWith('.log')) {
const logText = lineText.substring(0, lineText.length - 4).trimStart();
const logStatement = `console.log(${logText});`;
// 获取前面的缩进最后的index
const indent = line.firstNonWhitespaceCharacterIndex;
editor.edit(editBuilder => {
const newStartCharacter = line.range.start.character + indent;
const newStart = new vscode.Position(line.range.start.line, newStartCharacter);
const range = new vscode.Range(newStart, line.range.end);
editBuilder.replace(range, logStatement);
});
}
- 使用trimStart去掉了前面的空格
- indent表示缩进结尾的index,然后以indent为起始创建一个Position对象,在创建Range时作为参数,用于标明起始位置。
6. 优化后的运行结果
运行插件,在输入.log和按下快捷键一波操作之后,效果如预期的一样,两个缩进问题都完美解决。
至此,console.log插件的基本功能已完成。但是我想要进一步的简化操作,不想每次都使用CTRL + SHIFT + H快捷键生成,能不能在输入.log之后,再输入回车就能自动生成呢。
回车生成console.log
我第一时间把需求交给了腾讯云AI代码助手。
1. 开发思路
我尝试用JavaScript的开发思维,看vscode是否能监听文本输入或者输入回车的事件。
腾讯云AI代码助手根据我的描述,并结合我已经实现的插件代码,给出了插件的详细功能设计方案和代码实现。
2. 监听回车
主要使用onDidChangeTextDocument监听vscode编辑器的文本变化,只要输入或者删除代码造成文本变化,都会触发这个监听。如果想要实现监听回车,那么文本进行判断,看是否最后的一个字符输入的是否是回车。
代码语言:typescript
复制
context.subscriptions.push(vscode.workspace.onDidChangeTextDocument(event => {
const editor = vscode.window.activeTextEditor;
if (!editor) {
return;
}
const document = event.document;
const changes = event.contentChanges;
// 只处理用户输入的最后一个字符
if (changes.length === 1) {
const change = changes[0];
const text = change.text;
// 检查用户是否输入了回车键,并且之前的文本是 .log
if (text === '\n' || text === '\r\n') {
const line = document.lineAt(change.range.start.line);
const lineText = line.text.trim();
if (lineText.endsWith('.log')) {
vscode.window.showInformationMessage(`Generated console.log by 回车`);
vscode.commands.executeCommand('extension.logCompletion');
}
}
}
}));
通过change.text变化文本,然后判断是否为回车(mac为\n,windowsw为\r\n),如果回车,且代码是以.log结尾的,就调用vscode.commands的executeCommand方法,执行我们上面定义的生成console.log的插件功能,即extension.logCompletion。
3. 功能演示
为了区分回车与快捷键生成console.log,我在监听回车的逻辑中增加了一个消息弹出:Generated console.log by 回车。
如图所示,我在.log后面输入回车,就自动生成了console.log,右下角也弹出了提示。
其他
DIY console.log
如果我们想要在console.log的文本中,加入一些有意思的文本元素,可以直接在logStatement变量中修改即可。
运行结果:
添加注释
在编写完所有的代码之后,为了提高自己代码的可读性,还是要对主要的功能代码加上注释。与以前需要手动输入或者依赖IDE添加注释不同的是,腾讯云AI代码助手的文档注释(Complete comments)功能会帮助我们生成注释。
在编辑器中代码上方,选择文档注释,在腾讯云AI代码助手对话框中就会生成注释。
除此之外,在输入框中选择快捷键 /comments,效果和上面等同。
最后将通过AI代码助手的一键复制或一键插入功能,完成代码注释。
结语
通过腾讯云AI代码助手的智能代码补全、自动代码生成、代码优化等功能的助力,让我从零基础开发了一个vscode插件。在整个开发过程中,腾讯云AI代码助仿佛是一个“知识宝库”,也像是一个全能的开发者,带给了我完全不一样的coding体验。
期待腾讯云AI编程助手将会在未来带来更多的创新和惊喜,为全球开发者赋能,推动编程生产力的革命性提升。