最近打算給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,有興趣的同窗能夠直接參考源碼,寫個本身的插件。