最近打算给xmake写一些IDE和编辑器的集成插件,发现vscode的编辑器插件比较容易上手的,就先研究了下vscode的插件开发流程,而且完成了xmake-vscode插件的开发。linux
咱们先来看几张最后的效果图:android
要实现上面的效果,其实并不复杂,首先咱们先来简单介绍下,vscode的插件开发的基本流程:git
因为国内环境比较复杂,直接用npm安装也许很慢或者访问不稳定,所以这里先安装了cnpm去默认使用淘宝的镜像源。github
$ npm install -g cnpm --registry=https://registry.npm.taobao.org复制代码
经过cnpm去安装yo工具,用来建立一个vscode插件的空工程macos
$ cnpm install -g yo generator-code
$ yo code复制代码
大致的源码结构以下:npm
选择建立项目后有四个输入和一个选择:json
建立完成后的空工程,咱们能够用vscode直接打开,而后进行调试加载运行下:windows
加载起来后,敲F1打开命令窗口,运行默认的hello world测试命令:缓存
到此,一个简答的demo插件就搞定了,接下来咱们简单介绍下如何发布这个插件到vscode的market上去。bash
首先咱们须要在marketplace.visualstudio.com上注册一个帐号,建立一个发布者,这里我取名为tboox
而后,咱们须要在本身的帐号里面,添加一个Personal Access Token(地址:https://[your name].visualstudio.com/_details/security/tokens
,注意Token只显示一次,最好本身保存一份)
接着,咱们安装下vsce这个工具,用于vscode的插件工程打包编译和发布。
$ cnpm install -g vsce复制代码
安装好vsce后,咱们先建立一个发布者,这里为tboox,输入刚刚market帐号里面提供的token进行绑定。
$ vsce create-publisher (publisher name)复制代码
最后,只须要经过下面命令进行打包或者发布就好了,若是仅仅打个本地包,拖入vscode加载测试,能够运行:
$ vsce package复制代码
这将会生成一个相似xmake-vscode-0.0.1.vslx
的插件包文件,用vscode可直接加载运行。
若是,咱们已经开发完了插件,想要发布到market市场,能够执行:
$ vsce publish [version]复制代码
这个时候,咱们就能够在xmake-vscode on marketplace上看到你的插件了,用户也能够直接经过vscode进行搜索和安装使用。
插件经过工程根目录extension.json中配置的activationEvents进行触发,例如:
{
"activationEvents": [
"workspaceContains:xmake.lua",
"onCommand:xmake.sayHello"
]
}复制代码
当vscode打开带有xmake.lua
的目录或者执行xmake.XXX
相关命令的时候,都会触发加载xmake-vscode插件,而后调用src/extension.ts
中的activate入口函数,进行插件的加载和初始化。
export function activate(context: vscode.ExtensionContext) {
let disposable = vscode.commands.registerCommand('xmake.sayHello', () => {
vscode.window.showInformationMessage('Hello XMake!');
});
context.subscriptions.push(disposable);
}复制代码
上述代码,在加载插件的时候,注册sayHello
命令,去显示Hello XMake!
提示信息。
vscode经过建立OutputChannel来输出本身的日志信息,代码以下:
import * as vscode from 'vscode';
let log = vscode.window.createOutputChannel("xmake/log");
log.show();
log.appendLine("hello xmake!");复制代码
在建立的时候能够指定一个label名,用于区分不一样的输出通道,最后显示的结果以下:
须要注意的是,必须执行log.show()
,输出才会被显示出来,而且输出行为是带缓存刷新的,并不会实时输出,也不支持色彩高亮输出。
以前,xmake-vscode就是采用channel的方式来输出xmake的构建信息,效果不是很理想,所以后来改用了终端直接执行的方式,能够看下下面的效果图:
那如何控制终端,执行本身的命令呢,其实也很是简单:
let terminal = vscode.window.createTerminal({name: "xmake"});
terminal.show(true);
terminal.sendText("xmake");复制代码
上面的代码,经过建立一个label名为xmake的独立终端,而后发送执行命令:xmake
,去让终端执行xmake进行项目的构建,固然若是要显示出来,仍是要先调用下terminal.show(true)
。
xmake-vscode里面增长了一些全局vscode配置项,用于控制xmake-vscode插件的行为,配置清单是在package.json文件中进行描述的,例如:
{
"configuration": {
"type": "object",
"title": "XMake configuration",
"properties": {
"xmake.logLevel": {
"type": "string",
"default": "normal",
"description": "The Log Level: normal/verbose/minimal",
"enum": [
"verbose",
"normal",
"minimal"
]
},
"xmake.buildDirectory": {
"type": "string",
"default": "${workspaceRoot}/build",
"description": "The Build Output Directory"
},
"xmake.androidNDKDirectory": {
"type": "string",
"default": "",
"description": "The Android NDK Directory"
}
}
}
}复制代码
上述配置,增长了三个配置项,都在xmake.
域下面,可在vscode配置中直接搜索xmake相关字样就能方便找到。
读取配置也很方便,只要获取xmake相关域配置,进行读取就好了:
const config = vscode.workspace.getConfiguration('xmake');
config.get("buildDirectory");复制代码
状态栏上的按钮是能够响应以前建立的那些命令的,例如:xmake.sayHello
等,下面咱们在状态栏上建立一个debug按钮,用来调试运行xmake构建的程序:
let debugButton = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 4.5);
debugButton.command = 'xmake.onDebug';
debugButton.text = `$(bug)`;
debugButton.tooltip = "Debug the given target";
debugButton.show();复制代码
createStatusBarItem中第二个参数4.5用于控制按钮在状态栏上的布局顺序,建立好后,再设置下一些基础属性就好了,这里按钮的文本直接经过$(bug)
设置了一个图标来显示,更加的直观。
更多vscode内置支持的图标,能够本身从octicons上面去找。
点击这个按钮,将会触发xmake.onDebug
命令,而后在终端上执行xmake run -d
命令,去运行调试程序。
在xmake-vscode的状态栏上,咱们还增长了几个快速配置的状态按钮,用于快速切换不一样的平台、架构、编译模式,例如:
这个时候,须要有个选项选择列表的支持,在点击按钮后,列出能够选择的几个选项,而后选择切换,那如何建立这个选项列表呢,直接上代码:
// 初始化选项列表清单
let items: vscode.QuickPickItem[] = [];
items.push({label: "linux", description: "The Linux Platform"});
items.push({label: "macosx", description: "The MacOS Platform"});
items.push({label: "windows", description: "The Windows Platform"});
items.push({label: "android", description: "The Android Platform"});
items.push({label: "iphoneos", description: "The iPhoneOS Platform"});
items.push({label: "watchos", description: "The WatchOS Platform"});
items.push({label: "mingw", description: "The MingW Platform"});
items.push({label: "cross", description: "The Cross Platform"});
// 显示选项列表,提示用户选择
const chosen: vscode.QuickPickItem|undefined = await vscode.window.showQuickPick(items);
if (chosen) {
// 获取选择后的结果,而后更新状态栏按钮文本
platButton.text = chosen.label;
}复制代码
语法高亮彻底能够经过配置文件来搞定,不用写代码,固然也能够在代码中动态配置,这样稍微繁琐些。
xmake-vscode里面须要处理工程xmake.lua描述文件的语法高亮,所以这边在package.json里面先定义了一个叫xmake的语言类型,若是编辑器打开xmake.lua
文件,就会对其进行语法高亮处理。
{
"contributes": {
"languages": [
{
"id": "xmake",
"filenames": [
"xmake.lua"
],
"aliases": [
"XMake"
],
"configuration": "./languages/xmake-configuration.json"
}
],
"grammars": [
{
"language": "xmake",
"scopeName": "source.xmake",
"path": "./languages/xmake-grammars.json"
}
]
}
}复制代码
跟语法高亮相关的描述,都放置在/languages/xmake-grammars.json
中,用json来描述,咱们也能够用xml的格式来描述,可是这样可读性不是很好。
xmake-grammars.json
中的描述规则,咱们摘录自lua的grammars文件,由于xmake.lua
自己就是基于lua语法的,例如,咱们匹配'xxx'
单引号字符串的规则,进行字符串的高亮输出。
{
"begin": "'",
"beginCaptures": {
"0": {
"name": "punctuation.definition.string.begin.xmake"
}
},
"end": "'",
"endCaptures": {
"0": {
"name": "punctuation.definition.string.end.xmake"
}
},
"name": "string.quoted.single.xmake",
"patterns": [
{
"include": "#escaped_char"
}
]
}复制代码
代码的自动提示和补全比较麻烦下,须要写个自定义的class,经过languages进行注册:
vscode.languages.registerCompletionItemProvider("xmake", new Completion());复制代码
这里咱们定义了一个Completion类,注册到xmake语言上去,xmake语言定义,就是刚才讲的在package.json中的配置。
而后咱们实现下这个Completion类:
export class Completion implements vscode.CompletionItemProvider {
// 匹配当前输入,提供须要补全的候选文本列表
public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Thenable<vscode.CompletionItem[]> {
// 获取当前输入的单词文本
let wordAtPosition = document.getWordRangeAtPosition(position);
var currentWord = '';
if (wordAtPosition && wordAtPosition.start.character < position.character) {
var word = document.getText(wordAtPosition);
currentWord = word.substr(0, position.character - wordAtPosition.start.character);
}
// 猜想匹配结果,返回候选列表
return new Promise(function (resolve, reject) {
Promise.all([
getLuaKeywordsSuggestions(currentWord),
getXMakeCommandsSuggestions(currentWord)
]).then(function (results) {
var suggestions = Array.prototype.concat.apply([], results);
resolve(suggestions);
}).catch(err => { reject(err); });
});
}
// 这里能够对刚刚返回的候选文本列表在作二次处理,例如:增长详细的文档描述信息
public resolveCompletionItem(item: vscode.CompletionItem, token: vscode.CancellationToken): Thenable<vscode.CompletionItem> {
// 对每一个候选文本增长文档描述
return new Promise(function (resolve, reject) {
item.documentation = "xxxxxxxxxxx";
resolve(item);
});
}
}复制代码
这部分代码比较多,就不彻底贴出来了,完整实现,可参考:completion.ts
本文讲述的一些vscode插件代码都来自xmake-vscode,有兴趣的同窗能够直接参考源码,写个本身的插件。