xmake-vscode插件開發(fā)過程記錄

最近打算給xmake寫一些IDE和編輯器的集成插件署咽,發(fā)現(xiàn)vscode的編輯器插件比較容易上手的损拢,就先研究了下vscode的插件開發(fā)流程,并且完成了xmake-vscode插件的開發(fā)。

我們先來看幾張最后的效果圖:

語(yǔ)法高亮和自動(dòng)補(bǔ)全

狀態(tài)欄

statusbar

要實(shí)現(xiàn)上面的效果,其實(shí)并不復(fù)雜霎褐,首先我們先來簡(jiǎn)單介紹下,vscode的插件開發(fā)的基本流程:

安裝插件開發(fā)環(huán)境

安裝cnpm

由于國(guó)內(nèi)環(huán)境比較復(fù)雜衡查,直接用npm安裝也許很慢或者訪問不穩(wěn)定,因此這里先安裝了cnpm去默認(rèn)使用淘寶的鏡像源必盖。

$ npm install -g cnpm --registry=https://registry.npm.taobao.org

創(chuàng)建空工程

通過cnpm去安裝yo工具拌牲,用來創(chuàng)建一個(gè)vscode插件的空工程

$ cnpm install -g yo generator-code
$ yo code

大體的源碼結(jié)構(gòu)如下:

選擇創(chuàng)建項(xiàng)目后有四個(gè)輸入和一個(gè)選擇:

  • 輸入你擴(kuò)展的名稱 xmake-vscode
  • 輸入一個(gè)標(biāo)志(項(xiàng)目創(chuàng)建的文件名稱用這個(gè))xmake-vscode
  • 輸入對(duì)這個(gè)擴(kuò)展的描述
  • 輸入以后要發(fā)布用到的一名稱(和以后再發(fā)布時(shí)候有一個(gè)名字是對(duì)應(yīng)上的)tboox
  • 是問你要不要?jiǎng)?chuàng)建一個(gè)git倉(cāng)庫(kù)用于版本管理

創(chuàng)建完成后的空工程,我們可以用vscode直接打開歌粥,然后進(jìn)行調(diào)試加載運(yùn)行下:

加載起來后塌忽,敲F1打開命令窗口,運(yùn)行默認(rèn)的hello world測(cè)試命令:


到此失驶,一個(gè)簡(jiǎn)答的demo插件就搞定了土居,接下來我們簡(jiǎn)單介紹下如何發(fā)布這個(gè)插件到vscode的market上去。

創(chuàng)建發(fā)布者

首先我們需要在marketplace.visualstudio.com上注冊(cè)一個(gè)賬號(hào)嬉探,創(chuàng)建一個(gè)發(fā)布者擦耀,這里我取名為tboox

然后涩堤,我們需要在自己的賬號(hào)里面眷蜓,添加一個(gè)Personal Access Token(地址:https://[your name].visualstudio.com/_details/security/tokens,注意Token只顯示一次胎围,最好自己保存一份)

接著吁系,我們安裝下vsce這個(gè)工具,用于vscode的插件工程打包編譯和發(fā)布白魂。

$ cnpm install -g vsce

安裝好vsce后汽纤,我們先創(chuàng)建一個(gè)發(fā)布者,這里為tboox福荸,輸入剛剛market賬號(hào)里面提供的token進(jìn)行綁定蕴坪。

$ vsce create-publisher (publisher name)

構(gòu)建發(fā)布

最后,只需要通過下面命令進(jìn)行打包或者發(fā)布就行了敬锐,如果僅僅打個(gè)本地包辞嗡,拖入vscode加載測(cè)試,可以運(yùn)行:

$ vsce package

這將會(huì)生成一個(gè)類似xmake-vscode-0.0.1.vslx的插件包文件滞造,用vscode可直接加載運(yùn)行续室。

如果,我們已經(jīng)開發(fā)完了插件谒养,想要發(fā)布到market市場(chǎng)挺狰,可以執(zhí)行:

$ vsce publish [version]

這個(gè)時(shí)候明郭,我們就可以在xmake-vscode on marketplace上看到你的插件了,用戶也可以直接通過vscode進(jìn)行搜索和安裝使用丰泊。

插件開發(fā)詳解

插件的加載機(jī)制

插件通過工程根目錄extension.json中配置的activationEvents進(jìn)行觸發(fā)薯定,例如:

{
    "activationEvents": [
        "workspaceContains:xmake.lua",
        "onCommand:xmake.sayHello"
    ]
}

當(dāng)vscode打開帶有xmake.lua的目錄或者執(zhí)行xmake.XXX相關(guān)命令的時(shí)候,都會(huì)觸發(fā)加載xmake-vscode插件瞳购,然后調(diào)用src/extension.ts中的activate入口函數(shù)话侄,進(jìn)行插件的加載和初始化。

export function activate(context: vscode.ExtensionContext) {

    let disposable = vscode.commands.registerCommand('xmake.sayHello', () => {
        vscode.window.showInformationMessage('Hello XMake!');
    });

    context.subscriptions.push(disposable);
}

上述代碼学赛,在加載插件的時(shí)候年堆,注冊(cè)sayHello命令,去顯示Hello XMake!提示信息盏浇。

創(chuàng)建自定義輸出

vscode通過創(chuàng)建OutputChannel來輸出自己的日志信息变丧,代碼如下:

import * as vscode from 'vscode';

let log = vscode.window.createOutputChannel("xmake/log");
log.show();
log.appendLine("hello xmake!");

在創(chuàng)建的時(shí)候可以指定一個(gè)label名,用于區(qū)分不同的輸出通道绢掰,最后顯示的結(jié)果如下:

需要注意的是痒蓬,必須執(zhí)行log.show(),輸出才會(huì)被顯示出來滴劲,并且輸出行為是帶緩存刷新的攻晒,并不會(huì)實(shí)時(shí)輸出,也不支持色彩高亮輸出班挖。

創(chuàng)建和控制終端

之前炎辨,xmake-vscode就是采用channel的方式來輸出xmake的構(gòu)建信息,效果不是很理想聪姿,因此后來改用了終端直接執(zhí)行的方式碴萧,可以看下下面的效果圖:

那如何控制終端,執(zhí)行自己的命令呢末购,其實(shí)也非常簡(jiǎn)單:

let terminal = vscode.window.createTerminal({name: "xmake"});
terminal.show(true);
terminal.sendText("xmake");

上面的代碼破喻,通過創(chuàng)建一個(gè)label名為xmake的獨(dú)立終端,然后發(fā)送執(zhí)行命令:xmake盟榴,去讓終端執(zhí)行xmake進(jìn)行項(xiàng)目的構(gòu)建曹质,當(dāng)然如果要顯示出來,還是要先調(diào)用下terminal.show(true)擎场。

添加和讀取全局配置

xmake-vscode里面增加了一些全局vscode配置項(xiàng)羽德,用于控制xmake-vscode插件的行為,配置清單是在package.json文件中進(jìn)行描述的迅办,例如:

{
    "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"
            }
        }
    }
}

上述配置宅静,增加了三個(gè)配置項(xiàng),都在xmake.域下面站欺,可在vscode配置中直接搜索xmake相關(guān)字樣就能方便找到姨夹。

讀取配置也很方便纤垂,只要獲取xmake相關(guān)域配置,進(jìn)行讀取就行了:

const config = vscode.workspace.getConfiguration('xmake');
config.get("buildDirectory");

創(chuàng)建狀態(tài)欄

狀態(tài)欄上的按鈕是可以響應(yīng)之前創(chuàng)建的那些命令的磷账,例如:xmake.sayHello等峭沦,下面我們?cè)跔顟B(tài)欄上創(chuàng)建一個(gè)debug按鈕,用來調(diào)試運(yùn)行xmake構(gòu)建的程序:

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中第二個(gè)參數(shù)4.5用于控制按鈕在狀態(tài)欄上的布局順序逃糟,創(chuàng)建好后吼鱼,再設(shè)置下一些基礎(chǔ)屬性就行了,這里按鈕的文本直接通過$(bug)設(shè)置了一個(gè)圖標(biāo)來顯示绰咽,更加的直觀菇肃。

更多vscode內(nèi)置支持的圖標(biāo),可以自己從octicons上面去找剃诅。

點(diǎn)擊這個(gè)按鈕巷送,將會(huì)觸發(fā)xmake.onDebug命令驶忌,然后在終端上執(zhí)行xmake run -d命令矛辕,去運(yùn)行調(diào)試程序。

添加選項(xiàng)輸入列表

xmake-vscode的狀態(tài)欄上付魔,我們還增加了幾個(gè)快速配置的狀態(tài)按鈕聊品,用于快速切換不同的平臺(tái)、架構(gòu)几苍、編譯模式翻屈,例如:

這個(gè)時(shí)候,需要有個(gè)選項(xiàng)選擇列表的支持妻坝,在點(diǎn)擊按鈕后伸眶,列出可以選擇的幾個(gè)選項(xiàng),然后選擇切換刽宪,那如何創(chuàng)建這個(gè)選項(xiàng)列表呢厘贼,直接上代碼:


// 初始化選項(xiàng)列表清單
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"});

// 顯示選項(xiàng)列表,提示用戶選擇
const chosen: vscode.QuickPickItem|undefined = await vscode.window.showQuickPick(items);
if (chosen) {

    // 獲取選擇后的結(jié)果圣拄,然后更新狀態(tài)欄按鈕文本
    platButton.text = chosen.label;
}

自定義語(yǔ)法高亮

語(yǔ)法高亮完全可以通過配置文件來搞定嘴秸,不用寫代碼,當(dāng)然也可以在代碼中動(dòng)態(tài)配置庇谆,這樣稍微繁瑣些岳掐。

xmake-vscode里面需要處理工程xmake.lua描述文件的語(yǔ)法高亮,因此這邊在package.json里面先定義了一個(gè)叫xmake的語(yǔ)言類型饭耳,如果編輯器打開xmake.lua文件串述,就會(huì)對(duì)其進(jìn)行語(yǔ)法高亮處理。

{
    "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"
            }
        ]
    }
}

跟語(yǔ)法高亮相關(guān)的描述寞肖,都放置在/languages/xmake-grammars.json中剖煌,用json來描述材鹦,我們也可以用xml的格式來描述,但是這樣可讀性不是很好耕姊。

xmake-grammars.json中的描述規(guī)則桶唐,我們摘錄自lua的grammars文件,因?yàn)?code>xmake.lua本身就是基于lua語(yǔ)法的茉兰,例如尤泽,我們匹配'xxx'單引號(hào)字符串的規(guī)則,進(jìn)行字符串的高亮輸出规脸。

{
    "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"
        }
    ]
}

自動(dòng)補(bǔ)全的實(shí)現(xiàn)

代碼的自動(dòng)提示和補(bǔ)全比較麻煩下坯约,需要寫個(gè)自定義的class,通過languages進(jìn)行注冊(cè):

vscode.languages.registerCompletionItemProvider("xmake", new Completion());

這里我們定義了一個(gè)Completion類莫鸭,注冊(cè)到xmake語(yǔ)言上去闹丐,xmake語(yǔ)言定義,就是剛才講的在package.json中的配置被因。

然后我們實(shí)現(xiàn)下這個(gè)Completion類:

export class Completion implements vscode.CompletionItemProvider {

    // 匹配當(dāng)前輸入卿拴,提供需要補(bǔ)全的候選文本列表
    public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Thenable<vscode.CompletionItem[]> {

        // 獲取當(dāng)前輸入的單詞文本
        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);
        }

        // 猜測(cè)匹配結(jié)果,返回候選列表
        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); });
        });
    }

    // 這里可以對(duì)剛剛返回的候選文本列表在做二次處理梨与,例如:增加詳細(xì)的文檔描述信息
    public resolveCompletionItem(item: vscode.CompletionItem, token: vscode.CancellationToken): Thenable<vscode.CompletionItem> {
        
        // 對(duì)每個(gè)候選文本增加文檔描述
        return new Promise(function (resolve, reject) { 
            item.documentation = "xxxxxxxxxxx";
            resolve(item);
         });
    }
}

這部分代碼比較多堕花,就不完全貼出來了,完整實(shí)現(xiàn)粥鞋,可參考:completion.ts

結(jié)語(yǔ)

本文講述的一些vscode插件代碼都來自xmake-vscode缘挽,有興趣的同學(xué)可以直接參考源碼,寫個(gè)自己的插件呻粹。

原文出處:http://tboox.org/cn/2017/10/11/xmake-vscode/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末壕曼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子等浊,更是在濱河造成了極大的恐慌腮郊,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凿掂,死亡現(xiàn)場(chǎng)離奇詭異伴榔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)庄萎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門踪少,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人糠涛,你說我怎么就攤上這事援奢。” “怎么了忍捡?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵集漾,是天一觀的道長(zhǎng)切黔。 經(jīng)常有香客問我,道長(zhǎng)具篇,這世上最難降的妖魔是什么纬霞? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮驱显,結(jié)果婚禮上诗芜,老公的妹妹穿的比我還像新娘。我一直安慰自己埃疫,他們只是感情好伏恐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著栓霜,像睡著了一般翠桦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胳蛮,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天销凑,我揣著相機(jī)與錄音,去河邊找鬼鹰霍。 笑死闻鉴,一個(gè)胖子當(dāng)著我的面吹牛茵乱,可吹牛的內(nèi)容都是我干的茂洒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼瓶竭,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼督勺!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起斤贰,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤智哀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后荧恍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瓷叫,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年送巡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了摹菠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡骗爆,死狀恐怖次氨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情摘投,我是刑警寧澤煮寡,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布虹蓄,位于F島的核電站,受9級(jí)特大地震影響幸撕,放射性物質(zhì)發(fā)生泄漏薇组。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一坐儿、第九天 我趴在偏房一處隱蔽的房頂上張望体箕。 院中可真熱鬧,春花似錦挑童、人聲如沸累铅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)娃兽。三九已至,卻和暖如春尽楔,著一層夾襖步出監(jiān)牢的瞬間投储,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工阔馋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留玛荞,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓呕寝,卻偏偏與公主長(zhǎng)得像勋眯,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子下梢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容