本文部分内容由AI生成,其他内容由假扮AI的人类撰写
GitHub Copilot Labs 是 GitHub Copilot 的升级版伴侣扩展,其中包含实验性和即将推出的功能。在Vscode上,它是一个侧边栏,其中包含的工具可以帮助您更好地理解代码,例如帮助我们翻译阅读难以理解的代码,根据语义一键生成其他语言的代码,修复潜在的Bugs,给函数加文档等。
要获取Github Copilot Labs,您需要拥有Github Copilot的访问权限,然后去GitHub Next | GitHub Copilot Labs上获取访问权限,申请的过程不需要等待或者审核。
在Vscode上,安装GitHub Copilot Labs扩展,绑定Github账户即可使用。
一旦安装成功并且成功绑定账号,您应该会在侧边栏中看到GitHub Copilot Labs的选项卡。
接下来我们分四个部分分别对四个功能集进行讲解。
Explain顾名思义就是解释代码,选择一个代码块来进行解释。
下面是一个加载动态Snackbar的函数,加载完成后会继续加载其他依赖,如果加载失败则抛出错误。
function LoadSnackbar(){
const Snackbardependencies = [
'https://cdn.jsdelivr.net/npm/node-snackbar@latest/src/js/snackbar.min.js',
'https://cdn.jsdelivr.net/npm/node-snackbar@latest/dist/snackbar.min.css'
];
Promise.all(Snackbardependencies.map(loadDependency))
.then(() => {
Snackbar.show({text:"少女祈祷中..",showAction:false,timeout:10000})
LoadDependent();
})
.catch((error) => {
Snackbar.close();
console.error(`Error loading dependencies: ${error}`);
Snackbar.show({text:"依赖加载失败",showAction:false})
});
}
选中这个函数后,翻到Explain最下方,有个Ask Copilot按钮,按一下就可以进行解释。
这是生成的结果
/* Here is the explanation for the code above:
1. LoadSnackbar() is the main function. It will be called after the page is loaded.
2. Snackbardependencies is the list of dependencies that need to be loaded.
3. loadDependency() is a function that loads a single dependency. It returns a Promise.
4. LoadDependent() is the function that will be called after all dependencies are loaded.
5. The code in the .then() block will be executed after all dependencies are loaded.
6. The code in the .catch() block will be executed if any dependency fails to load. */
可以看到已经解释了函数的大致结构,至于一些小小的函数,例如Snackbar.show(...)
则没有提到。不过可以通过单独选择来解释这些没解释到的东西。
看英文就可以知道,这是用来将某个函数用其他语言重写的功能。
以下给出了获取js文件中字体子集并转储为文件的函数,使用Python编写:
def GetCharacterSubset():
with open('FortuneUpUp.js', 'r',encoding='utf-8') as f:
js_text = f.read()
# 去除单行注释
js_text = re.sub(r'//.*?\n', '', js_text)
# 去除多行注释
js_text = re.sub(r'/\*.*?\*/', '', js_text, flags=re.DOTALL)
# 提取中英文文本
text_pattern = re.compile(r'[\u4e00-\u9fa5]+')
text_list = re.findall(text_pattern, js_text)
text_set = set(text_list)
text_set = ''.join(text_set) + '0123456789' + 'abcdefghijklmnopqrstuvwxyz' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
with open('text_set.txt', 'w',encoding='utf-8') as f:
f.write(text_set)
选择代码块后,向下滑动找到Translate code into
多选框,选一个目标语言即可,比如Cpp:
#include <iostream>
#include <fstream>
#include <string>
#include <regex>
using namespace std;
int main()
{
string js_text;
ifstream f;
f.open("FortuneUpUp.js", ios::in);
if (!f.is_open())
{
cout << "Open file \"FortuneUpUp.js\" failed." << endl;
return 0;
}
getline(f, js_text, '\0');
f.close();
// 去除单行注释
js_text = regex_replace(js_text, regex("//.*?\\n"), "");
// 去除多行注释
js_text = regex_replace(js_text, regex("/\\*.*?\\*/"), "", regex_constants::match_any);
// 提取中英文文本
string text_list = regex_replace(js_text, regex("[^\\u4e00-\\u9fa5]"), "");
string text_set;
for (auto c : text_list)
{
if (text_set.find(c) == string::npos)
{
text_set += c;
}
}
text_set += "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
f.open("text_set.txt", ios::out);
if (!f.is_open())
{
cout << "Open file \"text_set.txt\" failed." << endl;
return 0;
}
f << text_set;
f.close();
return 0;
}
好家伙,还修复了几个隐式bug,转写得好。
那么如果用CSS重写会发生什么?
第一次生成:
@charset "utf-8";
*/
.RtL {
*/
position: absolute;
*/
width: 100px;
*/
height: 100px;
*/
left: 0px;
*/
top: 0px;
*/
display: none;
*/
}
*/
.RtL .RtL_1 {
*/
position: absolute;
*/
width: 100px;
*/
height: 100px;
*/
left: 0px;
*/
top: 0px;
*/
background-image: url('images/1.png');
*/
}
*/
.RtL .RtL_2 {
*/
position: absolute;
*/
width: 100px;
*/
height: 100px;
*/
left: 0px;
*/
top: 0px;
*/
background-image: url('images/2.png');
*/
}
*/
......
.RtL .RtL_14 {
*/
position: absolute;
*/
width: 100px;
*/
height: 100px;
*/
left: 0px;
*/
top: 0px;
*/
background-image: url('images/14.png');
*/
}
*/
.RtL .RtL_15 {
*/
position: absolute;
*/
第二次生成:
def GetCharacterSubset():
*/
with open('FortuneUpUp.js', 'r',encoding='utf-8') as f:
*/
js_text = f.read()
*/
# 去除单行注释
*/
js_text = re.sub(r'//.*?\n', '', js_text)
*/
# 去除多行注释
*/
js_text = re.sub(r'/\*.*?\*/', '', js_text, flags=re.DOTALL)
*/
# 提取中英文文本
*/
text_pattern = re.compile(r'[\u4e00-\u9fa5]+')
*/
text_list = re.findall(text_pattern, js_text)
*/
好吧,第一次牛头不对马嘴,第二次就改了注释,还以为有报错,建议直接报错。
刷子里面就有很多的功能了。
增加代码可读性。下面给出了获取Cookie的函数:
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for(var i = 0; i <ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
改动后如下:
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var cookieArray = decodedCookie.split(';');
for(var i = 0; i < cookieArray.length; i++) {
var cookie = cookieArray[i];
while (cookie.charAt(0) == ' ') {
cookie = cookie.substring(1);
}
if (cookie.indexOf(name) == 0) {
return cookie.substring(name.length, cookie.length);
}
}
return "";
}
ca
、c
变量换成了可读性更高的cookieArray
, cookie
,更加容易维护了
主要用于typescript的编写,能够自动加入一些Types
执行前代码
let options = [
{ name: '大吉', probability: 0.2 },
{ name: '中吉', probability: 0.4 },
{ name: '小吉', probability: 0.3 },
{ name: '不太吉', probability: 0.1 }
];
执行后代码如下
let options: Array<{
name: string,
probability: number
}> = [
{ name: '大吉', probability: 0.2 },
{ name: '中吉', probability: 0.4 },
{ name: '小吉', probability: 0.3 },
{ name: '不太吉', probability: 0.1 }
];
很显然是用来修复bug的,比如代码检测器发现的bug或者是不按预期工作的代码块。
下面给出了一个新手容易犯错的代码。
def main():
a = 1
a + 1
print(a) # 2(Fact: 1)
接下来让我们执行这个功能
def main():
a = 1
a += 1
print(a) # 2
这下就能输出2
在程序测试时输出更多的变量以便于debug。
下面给出了一个非常多变量的函数,这个函数有非常多的变量,因此我们需要debug以防止出错
function GetFestivalFortune(){
let today = new Date();
let month = ("0" + (today.getMonth() + 1)).slice(-2);
let day = ("0" + today.getDate()).slice(-2);
let FestivalEventsList = [];
let FestivalEvent = null;
let GoodEventList = [];
let BadEventList = [];
let isFestival = 0;
for(i = 0;i < SpecialFestivalEvents.length;i++){
let FestivalDate = SpecialFestivalEvents[i]["Date"];
if(FestivalDate.indexOf("L") == 0){
FestivalDate = FestivalDate.replace("L","").split(".");
FestivalDate = GetLunarFestivalDate(FestivalDate[0],FestivalDate[1])
FestivalDate = ("0" + (FestivalDate[0])).slice(-2) + "." + ("0" + FestivalDate[1]).slice(-2);
}
if(FestivalDate == month+"."+day){
FestivalEventsList.push(SpecialFestivalEvents[i]);
}
}
for(i = 0;i < NormalFestivalDateList.length;i++){
if(NormalFestivalDateList[i] == month+"."+day){
FestivalEventsList.push(NormalFestivalEvents);
}
}
// 生成GoodEventList和BadEventList
if(FestivalEventsList.length > 1){
//同一个节日有多个事件时,随机抽取一个
FestivalEvent = FestivalEventsList[Math.floor(Math.random()*FestivalEventsList.length)];
}else if(FestivalEventsList.length == 1){
FestivalEvent = FestivalEventsList[0];
};
if(FestivalEvent != null){
if(FestivalEvent["bad"] != null){
if(Math.random() > 0.6){
GoodEventList.push(FestivalEvent);
isFestival = 1;
}else{
BadEventList.push(FestivalEvent);
isFestival = -1;
}
}else{
GoodEventList.push(FestivalEvent);
isFestival = 1;
}
}
return [GoodEventList,BadEventList,isFestival];
}
更改代码后如下:
function GetFestivalFortune(){
console.log("GetFestivalFortune");
let today = new Date();
console.log("today",today);
let month = ("0" + (today.getMonth() + 1)).slice(-2);
console.log("month",month);
let day = ("0" + today.getDate()).slice(-2);
console.log("day",day);
let FestivalEventsList = [];
let FestivalEvent = null;
let GoodEventList = [];
let BadEventList = [];
let isFestival = 0;
for(i = 0;i < SpecialFestivalEvents.length;i++){
console.log("i",i);
let FestivalDate = SpecialFestivalEvents[i]["Date"];
console.log("FestivalDate",FestivalDate);
if(FestivalDate.indexOf("L") == 0){
FestivalDate = FestivalDate.replace("L","").split(".");
console.log("FestivalDate",FestivalDate);
FestivalDate = GetLunarFestivalDate(FestivalDate[0],FestivalDate[1])
console.log("FestivalDate",FestivalDate);
FestivalDate = ("0" + (FestivalDate[0])).slice(-2) + "." + ("0" + FestivalDate[1]).slice(-2);
console.log("FestivalDate",FestivalDate);
}
if(FestivalDate == month+"."+day){
FestivalEventsList.push(SpecialFestivalEvents[i]);
console.log("FestivalEventsList",FestivalEventsList);
}
}
for(i = 0;i < NormalFestivalDateList.length;i++){
if(NormalFestivalDateList[i] == month+"."+day){
FestivalEventsList.push(NormalFestivalEvents);
console.log("FestivalEventsList",FestivalEventsList);
}
}
// 生成GoodEventList和BadEventList
if(FestivalEventsList.length > 1){
//同一个节日有多个事件时,随机抽取一个
FestivalEvent = FestivalEventsList[Math.floor(Math.random()*FestivalEventsList.length)];
console.log("FestivalEvent",FestivalEvent);
}else if(FestivalEventsList.length == 1){
FestivalEvent = FestivalEventsList[0];
console.log("FestivalEvent",FestivalEvent);
};
if(FestivalEvent != null){
if(FestivalEvent["bad"] != null){
if(Math.random() > 0.6){
GoodEventList.push(FestivalEvent);
console.log("GoodEventList",GoodEventList);
isFestival = 1;
console.log("isFestival",isFestival);
}else{
BadEventList.push(FestivalEvent);
console.log("BadEventList",BadEventList);
isFestival = -1;
console.log("isFestival",isFestival);
}
}else{
GoodEventList.push(FestivalEvent);
console.log("GoodEventList",GoodEventList);
isFestival = 1;
console.log("isFestival",isFestival);
}
}
return [GoodEventList,BadEventList,isFestival];
}
可以看到增加了些console.log()函数来输出变量,这下所有变量的变化情况就了如指掌了。
清理代码中没有使用的变量或函数。
下面的函数只是使用了a,b,c三个变量,没有使用d,e变量
def main():
a = 1
b = 2
c = 3
d = 4
e = 5
print(a, b, c)
执行后d,e变量被删除。
def main():
a = 1
b = 2
c = 3
print(a, b, c)
给每一行(或代码块)都添加注释。
下面是一个读取Cookie的函数:
function ReadCookie(){ //读取cookie,如果有cookie则直接读取,否则返回False
let Fortune = getCookie("Fortune");
let GoodEventList = getCookie("GoodEventList");
let BadEventList = getCookie("BadEventList");
if(Fortune != "" && GoodEventList != "" && BadEventList != ""){
GoodEventList = JSON.parse(GoodEventList);
BadEventList = JSON.parse(BadEventList);
return [Fortune,GoodEventList,BadEventList];
}else{
return false;
}
执行后发现每一行的代码都添加了注释。
function ReadCookie(){ //读取cookie,如果有cookie则直接读取,否则返回False
let Fortune = getCookie("Fortune"); //获取Fortune的cookie
let GoodEventList = getCookie("GoodEventList"); //获取GoodEventList的cookie
let BadEventList = getCookie("BadEventList"); //获取BadEventList的cookie
if(Fortune != "" && GoodEventList != "" && BadEventList != ""){ //如果三个cookie都存在
GoodEventList = JSON.parse(GoodEventList); //将字符串转为数组
BadEventList = JSON.parse(BadEventList); //将字符串转为数组
return [Fortune,GoodEventList,BadEventList]; //返回数组
}else{
return false;
}
增加代码可靠度,防止因为传入不合法的参数而导致程序崩溃
function GetLunarFestivalDate(month, day) {
let today = new Date();
let year = today.getFullYear();
let lunarDate = lunar2solar(year, month, day);
return [lunarDate[1],lunarDate[2]];
}
function GetLunarFestivalDate(month, day) {
let today = new Date();
let year = today.getFullYear();
let lunarDate = lunar2solar(year, month, day);
if (lunarDate[0] != year) {
lunarDate = lunar2solar(year+1, month, day);
}
return [lunarDate[1],lunarDate[2]];
}
写代码时,一个函数写得非常长是比较禁忌的,这会使得代码的可读性下降,这时候,将一个函数拆分为几个函数就显得非常重要。
def GetCharacterSubset():
with open('FortuneUpUp.js', 'r',encoding='utf-8') as f:
js_text = f.read()
# 去除单行注释
js_text = re.sub(r'//.*?\n', '', js_text)
# 去除多行注释
js_text = re.sub(r'/\*.*?\*/', '', js_text, flags=re.DOTALL)
# 提取中英文文本
text_pattern = re.compile(r'[\u4e00-\u9fa5]+')
text_list = re.findall(text_pattern, js_text)
text_set = set(text_list)
text_set = ''.join(text_set) + '0123456789' + 'abcdefghijklmnopqrstuvwxyz' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
with open('text_set.txt', 'w',encoding='utf-8') as f:
f.write(text_set)
def GetCharacterSubset():
js_text = GetJsText()
js_text = RemoveComment(js_text)
text_set = ExtractChineseAndEnglish(js_text)
SaveResult(text_set)
分块后的创建的新函数还需要通过新建几行来使Copilot生成。
而且Copilot有行数限制,写函数的时候还需要自己注意点。
Document(生成函数文档)
顾名思义,给函数生成使用文档。
不过实际测试之中,效果不是很好
def count_time(stime,etime):
if stime in ('无',None):
return 0
from datetime import datetime
st=datetime.strptime(stime,'%Y-%m-%d %H:%M')
et=datetime.strptime(etime,'%Y-%m-%d %H:%M')
return round(((et-st).days),2)
def count_time(stime,etime):
"""
计算两个时间之间的间隔
:param stime: 开始时间
:param etime: 结束时间
:return: 间隔天数
"""
if stime in ('无',None):
return 0
from datetime import datetime
st=datetime.strptime(stime,'%Y-%m-%d %H:%M')
et=datetime.strptime(etime,'%Y-%m-%d %H:%M')
return round(((et-st).days),2)
直接向AI发送修改任务。
下面代码的修改目标 —— Rewrite without datetime
def count_time(stime,etime):
if stime in ('无',None):
return 0
from datetime import datetime
st=datetime.strptime(stime,'%Y-%m-%d %H:%M')
et=datetime.strptime(etime,'%Y-%m-%d %H:%M')
return round(((et-st).days),2)
修改后的代码
def count_time(stime,etime):
if stime in ('无',None):
return 0
#from datetime import datetime
#st=datetime.strptime(stime,'%Y-%m-%d %H:%M')
#et=datetime.strptime(etime,'%Y-%m-%d %H:%M')
stime = stime.split(' ')
etime = etime.split(' ')
stime = stime[0].split('-')
etime = etime[0].split('-')
st = [int(i) for i in stime]
et = [int(i) for i in etime]
st = st[0]*365 + st[1]*30 + st[2]
et = et[0]*365 + et[1]*30 + et[2]
return round((et-st),2)
先写到这里,得上学了,总体上是大幅提升了编程体验,但是个人感觉比GPT 3.5略逊一筹(如果openai关掉cf的话),而且bug比较多,有时候会大量生成重复的代码。对于咱来说,还是不够火候。
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=74ll4y7102kq