VSCODE 扩展开发 01

此文章的 撰写时间 撰写日期 绝对有问题

此文章的部分图片可能无法加载。这是因为大概这一版的博客搭建在云服务器上所以图片没有用图床
为什么呢?难道云服务器流量不要钱吗?白嫖图床不好吗?

开新坑了,VSCode: 扩展开发攻略系列主要介绍如何从零开始(不需要Js/TS基础)开发一个VSCode插件

序: 写在前面的废话

由于英语不好谷歌翻译后的官方文档 很迷惑,我就打算自己简单翻翻看 翻一下 顺便加上一些注解

需要注意的一点是 有些东西你别理解 先能复现再说 因为有些Js语法你没学肯定看不懂

放心,这个系列一定会咕咕咕的,估计十年都写不好

开始吧! (等帖子多了我会专门搞出来一个帖子收集起来)

概览

我们先了解下vscode插件开发的流程. VSCode是Chromium内核,Electron+TypeScript编写的,底层有些可以瞎改的CSS VSCode插件开发并不难,熟悉API之后很简单 vscode插件开发时,重要的就是两个文件package.jsonextension.js文件 一个用来描述有什么,一个用来告诉干什么 > 注: 虽然我还是比较喜欢TypeScript,但这里我们还是使用Js演示 毕竟TS还不火

环境: 工欲善其事,必先利其器

Node.Js : 使用npm并换源(cnpm)

首先你需要一个node.js,下好了node.js才能使用npm命令 进入https://nodejs.org/zh-cn/下载npm(推荐LTS版) 然后你可以换源(换源的目的是为了提升部署速度,我知道你node.js下载了快半小时了) 打开cmd,输入

1
npm install -g cnpm --registry=https://registry.npm.taobao.org
这样,就可以换淘宝的镜像源了 淘宝真是啥都有 然后下面的操作,就可以直接使用cnpm而不是npm了(速度明显提升)

官方VSCode插件生成环境

1
cnpm install -g yo generator-code

注意,不要把cnpm打成cnpm ! ! ! 别笑,真就有人(比如我)犯了这样的低级错误

然后新建一个目录,在cmd中使用cd+新建的目录路径进入这个目录 这个目录将会是你的插件的工作区

1
2
d:
cd D:\VSCode_Ext\AirxWorld\
然后执行
1
yo code
下面的操作类似这样 中间有些耗时较长的地方我暂停了下GIF,不影响实际操作 YlTHgI.gif 然后
1
2
cd name
code .
(这里的name就是你? What's the identifier of your extension? name这里输入的名字) 然后cmd就可以关掉了,你发现你惊喜的进入了VSCode Yl7K2R.png (背景图片来自WLOP) (忽略我打开的那个json文件)

开始征程: 第一个HelloWorld插件

##熟悉文件

左侧文件资源管理器已经能看到package.jsonextension.js这两个文件了,qwq 这两个文件就是官方那个轮子生成的文件 我们先熟悉一下这个package.json文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
{
"name": "name", //插件名
"displayName": "name", //显示名
"description": "描述 可以中文", //描述 对应你在命令行cmd输入的描述
"version": "0.0.1", //版本号 注: 以上在vscode插件市场可见
"engines": {
"vscode": "^1.45.0"
},
"categories": [
"Other"
],
//扩展被激活时的事件(也就是干的事 有基础的同学可以理解为一个函数)
"activationEvents": [
"onCommand:name.helloWorld"
],
//入口文件
"main": "./extension.js",
//插件差不多所有的东西到要在这改,主要是一些命令的描述
"contributes": {
"commands": [
{
"command": "name.helloWorld",
"title": "Hello World"
}
]
},
"scripts": {
"lint": "eslint .",
"pretest": "npm run lint",
"test": "node ./test/runTest.js"
},
"devDependencies": {
"@types/vscode": "^1.45.0",
"@types/glob": "^7.1.1",
"@types/mocha": "^7.0.2",
"@types/node": "^13.11.0",
"eslint": "^6.8.0",
"glob": "^7.1.6",
"mocha": "^7.1.2",
"typescript": "^3.8.3",
"vscode-test": "^1.3.0"
}
}

没注释的地方可以忽略掉

然后我们再熟悉下extension.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
const vscode = require('vscode');

// this method is called when your extension is activated
// your extension is activated the very first time the command is executed

/**
* @param {vscode.ExtensionContext} context
*/
//插件被激活时执行这个
function activate(context) {

// Use the console to output diagnostic information (console.log) and errors (console.error)
// This line of code will only be executed once when your extension is activated
console.log('Congratulations, your extension "name" is now active!');

// The command has been defined in the package.json file
// Now provide the implementation of the command with registerCommand
// The commandId parameter must match the command field in package.json
let disposable = vscode.commands.registerCommand('name.helloWorld', function () {
// The code you place here will be executed every time your command is executed

// Display a message box to the user
vscode.window.showInformationMessage('Hello World from name!');
});

context.subscriptions.push(disposable);
}
exports.activate = activate;

// this method is called when your extension is deactivated
//被释放时激活这个(上面那句英文也是这个意思,是自己生成的不关我事 ( ( (
function deactivate() {}

module.exports = {
activate,
deactivate
}

## 文件分析 这两个自己生成的文件已经带有了输出hello world提示信息的功能,我们来分析下他是如何实现的 package.json节选:
1
2
3
4
5
6
7
8
"contributes": {
"commands": [
{
"command": "name.helloWorld",
"title": "Hello World"
}
]
},
commands的意思是”命令”,也就是说,以后要执行的命令都要在这注册(即进行描述) 了解json格式的同学也能发现commands其实是一个json数组,包含很多个json对象,不理解没关系 其中内部”command”是命令的名字,name.helloworld也就是这个命令的名字,可以理解为身份证, 比如以后要用到这个命令就要用这个名字叫他 > 一个人呼喊另一个人: 张三! > 人群中一堆叫张三的走了过来: 咋啦? > 于是他喊: 身份证号是888888888888888888的人过来一下! > 于是他要的张三就来了

这里的888888888888888888就可以理解为name.helloworld > 注意,这里name不是固定的,而是我们这个项目的名称

title的意思是标题,顾名思义,也就是标题 然后我们看看extension.js节选

1
2
3
4
5
6
function activate(context) {
let disposable = vscode.commands.registerCommand('name.helloWorld', function () {
vscode.window.showInformationMessage('Hello World from name!');
});
context.subscriptions.push(disposable);
}
function中文意思函数 可以理解为一长串清单 告诉某个对象要做什么 我们看代码里有这么一句context.subscriptions.push(disposable); > context n. 环境;上下文;来龙去脉

前面不看 不要理解 直接从push开始 > push vt. 推动,增加;对…施加压力,逼迫;按;说服; vi. 推进;增加;努力争取; n. 推,决心

你可以形象一点理解: 把一个函数”扔”进一个地方 由别人去执行它 就好像 > 你找了一张纸,写了一些任务,“给我端茶,倒水”,然后把这张纸”扔”到你家机器人的脑子里 > 然后你机器人帮你干活去了,依据是这张纸

let disposable什么意思呢?let”让,你可以理解为 让”disposable”(一个名字)这个东西出现(实际上是声明了一个变量) 后面=是赋值的意思,是把一个东西的值给另一个东西,比如,a=3就是把3值给a 既然是赋值,那为什么后面没有数字却有一串英文呢? 实际上可以这样理解,你有一个神奇的箱子,你往里放进去一个面团,他就会吐出一个面包 不就是面包机 你可以把函数理解为这个神奇的箱子,参数理解为面团(你放进去的东西),返回值理解为面包(吐出来的东西) > 当然,有的函数不会”吐东西”,甚至也不接收东西

1
2
3
vscode.commands.registerCommand('name.helloWorld', function () {
vscode.window.showInformationMessage('Hello World from name!');
});

这段代码就是执行一个函数,函数名字(面包机的型号)registerCommand, 参数是’name.helloWorld’这个字符串和另一个函数(Js中字符串不是"而是') 参数是什么?就是上面说的你放进面包机的东西 返回结果是Disposable对象,至于对象,你暂时理解成你对象好了,你对象是一个人这个类的个体 如果你没有对象的话,赶紧去找啊,还学什么学啊(大雾 > 小提示: 实际上,`vscode.commands.registerCommand()就是一个API(Application Programming Interface,应用程序接口,也就是那个面包机的入口,用于注册命令,不理解没关系

有时候,您可能看到这样的写法

1
2
3
context.subscriptions.push(vscode.commands.registerCommand('name.helloWorld', () => {
//......
}));
实际上这里它直接把值”扔”了进去,而没有用”纸”记下来 第二,它使用了() => {…}这样的写法,实际上叫一个Lambda表达式,暂时忽略即可 感兴趣可以自行百度/Bing/Google

而函数内部呢,也是一个API,这个APIvscode.window.showInformationMessage()用于输出一句调试信息 也很好理解,vscode就是vscode,window是窗口,show information message也就是显示 信息 消息 而括号中的’Hello World from name!’就是一个字符串,表示你要输出的信息,可以自己改

这样就分析完了,如何测试一下是否可以呢? 按f5,在你键盘的第一行,不算esc键的第五个按键 可以看到它弹出来了一个新窗口 按下Ctrl+Shift+P,也就是打开VSCode的命令面板 YlOvV0.png (注意看上图上方) 输入hello,就能看到我们的helloworld命令了(title就是Hello World) 回车选择这个命令 YlXFM9.png (那个登录成功是我装的另一个插件vscode-luogu显示的,与本插件无关) 就能看到我们的输出信息了,即vscode.window.showInformationMessage()括号里的字符串(参数)

这样,第一个Hello World就说完了,是不是很容易? 剩下的 以后再说吧 不会咕的 至少我也会把右键菜单命令和快捷键说完吧 掰掰~ 下期再见 ~