vscode
vscode的官方源码下载地址:https://github.com/microsoft/vscode
我们可以将vscode源码运行起来看演示效果,假设我们将vscode源码下载到这个目录下:
D:\new-vscode\vscode-master,那么运行步骤如下:
vscode运行
1.打开cmd命令行,进入到D:\new-vscode\vscode-master,执行监听命令;
vscode开发
在开发之前,我们需要对vsocde有一个整体的认识,事实上,vscode是一个html页面,如图:
界面大致可以分为六部分:
1.标题栏titlebar 包含其中左边的(包括文件~帮助)为菜单栏menubar
2.活动栏activitybar
3.侧边栏sidebar
4.编辑器editor
5.终端及输出等panel
6.状态栏statusbar
可以通过"切换开发人员工具",快捷键为Ctrl+Shift+I打开查看,效果相当于在浏览器的F12;
所以当我们需要修改vsocde界面的时候,往往就是修改相关的html和css,但vscode界面的元素一般不写在html,而是在ts文件中动态生成的,所以vscode的界面一般有ts和css组成,如下图是部分源码截图:
在工作上,我们都是按照需求来进行开发的,下面我们增加一个需求,在vscode的标题栏上增加一个登录按钮。首先我们先找到标题栏的ts和css,分别为titlebarPart.ts和titlebarPart.css,我们是如何确定titlebarPart.ts文件的呢?
首先我们通过Ctrl+Shift+I,如下图:
找到标题栏的class,然后在官方vscode中打开我们要修改的源码,然后根据class也就是titlebar去搜索此关键字,打开搜索结果的文件,对ts文件的代码查看,而上图中的class为titlebar,是和搜索结果中的css文件定义的样式对应的,如下图中红框;所以最终我们确定为titlebarPart.ts和titlebarPart.css的代码是对标题栏进行操作的。
我们仿照右上角的按钮来进行修改,增加如图代码,我们在titlebarpart.css中.part.titlebar的里面增加.window-custom-login元素;
当我们增加了css样式的时候,还需要在titlebarPart.ts中渲染出来,代码如下:
private windowControls_login: HTMLElement;
至此,我们就实现了在标题栏中增加登录按钮功能了。效果如下图:
vscode快捷方式
通过 设置-> 键盘快捷方式,可以打开查看所有的vsocde命令
这些命令在vscode源码中经常出现,像打开文件或者保存功能,我们可能在别的地方需要用上这些功能,通过拷贝命令即可得到,如拷贝打开文件命令得到
workbench.action.files.openFile
vscode命令注册和使用
在源码中调用上方的命令:
import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/commands';
export class test
{
constructor(
@ICommandService private readonly commandService: ICommandService,
)
}
this.commandService.executeCommand('workbench.action.files.openFile'));
这样我们就可以调用vscode中所有的命令了。
在vscode插件:
const vscode = require("vscode");
/* 注册 */
vscode.commands.registerCommand('extension.newCourseDir', function (data) {
}
/* 使用 */
vscode.commands.executeCommand("extension.newCourseDir");
vscode插件
vscode插件属于vscode源码的一个扩展功能,有时候我们需要在vscode中增加一个功能的时候,我们可以写成一个插件,在插件里面进行编码,插件代码可以是JavaScript或者是typescript语言。
vscode插件开发可参考官方文档:
https://code.visualstudio.com/api
在本主题中,我们将教您构建扩展的基本概念。确保安装了Node.js和Git,然后安装Yeoman和VS Code Extension Generator:
npm install -g yo generator-code
右击打开Git Bash Here,输入
yo code
输入后如图所示
这里我推荐使用第二个(JavaScript),按一下 下箭头,然后回车,注意按下箭头的时候,界面不会出现变化,但是实际已经选择了。出现下图(红框是语言类型)
提示我们输入插件的名字,这里我们输入test,回车;
提示我们输入插件唯一id,这里我们输入test,回车;
提示我们输入插件描述,这里我们输入test,回车;
提示我们是否启用“jsconfig.json”中的JavaScript类型检查?这里我们输入y,回车;
提示我们是否初始化git仓库,这里我们输入n,回车;
当出现下图的时候,那插件创建完成了。
如何创建一个vscode插件呢?
图A
图A
如上图A,我们如何写一个课程功能,在1234每个区域显示我们需要的数据。
打开package.json,我们在“contibutes”节点下增加如下代码:
"viewsContainers": {
"activitybar": [
{
"id": "test_id",
"title": "测试",
"icon": "images/todo-tree-container1.svg"
}
]
},
"views": {
"test_id": [
{
"id": "test_ID",
"name": "测试列表"
}
]
}
我们F5运行,会出现下图多了一个按钮,看,这就是我们上面代码加的图标
这里说一下,2区域的数据其实就是树视图的数据,官方文档介绍的了两个方法registerTreeDataProvider和createTreeView。
https://code.visualstudio.com/api/references/vscode-api
registerTreeDataProvider,顾名思义就是注册树视图数据提供者,我们传入一个树视图的ID,然后在创建一个树视图的类,在类中写我们想要显示在树视图的数据,这样我们就可以将树视图数据显示出来。也就是在图A的2区域显示数据。如果不理解,我们写一段代码看看。
我们先创建一个CourseTreeProvider.js作为TreeDataProvider,我们再看看TreeDataProvider有哪些方法?
https://code.visualstudio.com/api/references/vscode-api#TreeDataProvider
我们通过官方文档了解这个TreeDataProvider有了哪些方法,方法都有什么用了,接下来我们贴出实现的代码:
CourseTreeProvider.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vscode = require("vscode");
class MyTreeProvider {
constructor() { }
static initMyTreeList() {
let myTreeProvider = new MyTreeProvider();
vscode.window.registerTreeDataProvider("test_ID", myTreeProvider);
}
getTreeItem(element) {
return element;
}
getChildren(element) {
let trees = [];
let temp1 = new vscode.TreeItem("测试1");
let temp2 = new vscode.TreeItem("测试2");
let temp3 = new vscode.TreeItem("测试3");
trees.push(temp1);
trees.push(temp2);
trees.push(temp3);
return new Promise(resolve => {
return resolve(trees);
});
}
}
exports.MyTreeProvider = MyTreeProvider;
//# sourceMappingURL=CourseTreeProvider.js.map
我们在initMyTreeList()方法中注册树视图对象,test_ID是package.json中视图容器的id。
我们还实现了TreeDataProvider对象的getTreeItem()和getChildren(),我们在getChildren显示我们想要显示的数据,这里我们简单的显示数据,就使用vscode.TreeItem(),这个TreeItem第一个属性label是树视图中每一个Item的名字。
最后,我们打开extension.js文件,我们先将activate()函数里面的代码删除,activate()是插件激活后执行的方法,其实就是插件入口,在这可以做一些初始化的操作,调用CourseTreeProvider.js的MyTreeProvider中的initMyTreeList()方法,完整代码如下图:
F5运行,最终我们发现树视图没有显示数据,为什么呢?我们看package.json中activationEvents节点,这个是插件在什么时候激活,默认创建的插件是当extension.helloWorld调用时激活,这里我们改为“*”即为插件启动就激活。
再次按F5运行,我们发现终于显示数据了。
具体看课程插件的代码,这里我们给出实现的思路:
重点在getChildren(element)方法中,我们自定义一个myTreeNode继承vscode.TreeItem,
我们可以给myTreeNode添加一个标识,比如树结构第一节点是a,第二节点是b,第三节点是c,那么在getChildren(element)中先new myTreeNode(“a”),注意这里的myTreeNode里面还有其他属性,“a”只是其中的一个属性,我们判断如果是当前element的标识是a,那么就再new myTreeNode(“b”),如果新创建的element的标识是b,那么在创建new myTreeNode(“c”),这样当我们点击a标识的元素时,就会显示b标识的元素,点击b标识的元素就会显示c标识的元素。从而达到树结构的目的。
区域3是vscode编辑器,主要是通过打开文件的方式显示所需要的东西,如打开一个cpp文件可在上面写代码然后在区域4中点击提交到后台;
区域4是一个webview,你可当成是html,接下来我们看如何生成这个webview的,vscode给我们提供了方法。
前面我们说过“vscode命令注册和使用”,接下来我们再来温习一遍。
我们在extension.js的activate中注册一个命令,然后在显示树视图时调用命令,代码:
在activate里:
context.subscriptions.push(vscode.commands.registerCommand('extension.demo.openWebview', function (uri) {
//创建webview
createCourseWebview(uri);
}));
function createCourseWebview(uri){
if (flag) {
return;
}
var panel = vscode.window.createWebviewPanel('testWebview', "课程内容", vscode.ViewColumn.Two, {
enableScripts: true,
retainContextWhenHidden: true,
enableFindWidget: true,
});
flag = true;
panel.webview.html = getWebViewContent(context, 'src/test-webview.html');
panel.onDidDispose(() => {
flag = false;
}, null, context.subscriptions);
}
function getWebViewContent(context, templatePath) {
const resourcePath = util.getExtensionFileAbsolutePath(context, templatePath);
const dirPath = path.dirname(resourcePath);
let html = fs.readFileSync(resourcePath, 'utf-8');
html = html.replace(/(
return $1 + vscode.Uri.file(path.resolve(dirPath, $2)).with({
scheme: 'vscode-resource'
}).toString() + '"';
});
return html;
}
createCourseWebview
是创建webview的方法,通过vscode.window.createWebviewPanel方法创建并显示新的Webview面板,panel.webview.html是给网页视图添加添加html文档。getWebViewContent是对html进行处理最终返回一个字符串的html内容。flag是我们对webview进行控制,如果创建一个就不创建了,关闭的时候将flag标识更改。
我们在src目录下增加一个html,名为test-webview.html。
然后我们在CourseTreeProvider.js中getChildren里增加调用命令:
vscode.commands.executeCommand('extension.demo.openWebview');
最后按F5运行,当点击test按钮时,弹出webview。
最终代码如图:
test-webview.html:
欢迎来到编程训练营! 界面说明:左边是课程列表、中间是代码编辑区、右边是课程内容区。 课程列表:显示老师给我们的课程题目列表 代码编辑区:提供给我们写代码的区域 课程内容区:显示我们的课程题目内容 οnclick="openCheckClick()">提交 课程实战
关于4个区域之间的联动?
点击课程左侧栏中的其中一项,弹出右侧webview;
注意每一个课程列表都有着不同的arguments的值,当传入不同的值的时候,右侧栏webview(区域4)就会跟着去更换数据,实现在
test-webview.html中window.addEventListener('message', event => {})中,对不同的courseId进行后台数据请求从而更换html页面显示。
同时当选择在发生改变时,按情况去创建课程目录和课程cpp文件,实现在extension.js中
当创建完cpp文件之后,我们执行了exports.p(),其实就是调用打开cpp文件命令,也就是显示区域3。
上图代码就是打开cpp文件的实现。
所以,当我们点击课程列表时,webview(区域4)发生变化,编辑器(区域3)也跟着打开不同的cpp文件,从而达到课程联动。
关于插件源码:https://github.com/zhouhangzooo/test