使用TypeScript拓展你自己的VSCode

來源:互聯網
上載者:User

標籤:

轉自:http://www.iplaysoft.com/brackets.html
使用TypeScript拓展你自己的VSCode! 0x00 前言
在前幾天的美國紐約,微軟舉行了Connect(); //2015大會。通過這次大會,我們可以很高興的看到微軟的確變得更加開放也更加務實了。當然,會上放出了不少新產品和新功能,其中就包括了VS Code的beta版本。而且微軟更進一步,已經在github將VS Code的代碼開源了。除了這些讓人興奮的訊息,我們還應該注意到VS Code提供了對拓展的支援。
所以本文就來聊一聊使用TypeScript開發VS Code拓展的話題吧。


本文所使用的拓展的市集頁面:
https://marketplace.visualstudio.com/items/JiadongChen.LicenseHeader
github頁面:
https://github.com/chenjd/VSCode-StandardHeader
0x01 你好,世界
"萬事開頭,Hello World"。所以我們就從一個Hello World作為起點,開始一步一步構建自己的VScode的拓展。
在開發vscode的拓展之前,我們先要確保電腦上已經安裝了Node.js。之後,我們便可以利用微軟所提供的基於Yeoman的模板產生器來產生vscode拓展的模板了。

npm install -g yo generator-code


之後,我們只需要在終端中運行yo code命令,即可以進入建立拓展模板的引導過程。

yo code


在引導過程中將TypeScript選擇為開發語言,並且填完一些基本資料之後,我們的第一個vscode拓展便建立完成了。
那麼,yo code命令主要為我們做了一些什麼事情呢?
會根據我們在引導中所填的資訊,在目前的目錄產生一個拓展的檔案夾,檔案夾名即我們在引導中填入的拓展名稱。 該檔案夾中主要包括了盛放源檔案(extension.ts)的src檔案夾、test檔案夾以及out檔案夾。需要注意的是out檔案夾,在編譯typescript源檔案之前out檔案夾是沒有建立的,而編譯之後會建立out檔案夾並且其中的內容是typescript經過編譯之後產生的js檔案。 產生了資源設定檔package.json,package.json檔案描述了該拓展的資訊和它的功能。下文我還會具體說明package.json檔案。 建立了launch.json以及tasks.json和settings.json(位於項目中的.vscode目錄下),其中launch.json檔案規定了啟動一個在拓展開發(Extension Development)模式的VS Code進程,並且規定在VS Code啟動之前會先運行tasks.json檔案中所定義的task(根據tasks.json中的定義,相當於npm run compile),即先使用TypeScript的編譯器將ts檔案編譯為js檔案。這樣我們就可以直接編譯(因為是typescript)運行並且調試我們的拓展項目了。 當然,還會根據我們在引導中的選擇來決定是否建立一個Git倉庫,用來做版本控制。
下面便是我們的拓展項目的完整目錄:

.├── .gitignore                    //配置不需要加入版本管理的檔案├── .vscode                     // VS Code的整合│   ├── launch.json│   ├── settings.json│   └── tasks.json├── .vscodeignore                //配置不需要加入最終發布到拓展中的檔案├── README.md├── src                         // 源檔案│   └── extension.ts            // 如果我們使用js來開發拓展,則該檔案的尾碼為.js├── test                        // test檔案夾│   ├── extension.test.ts       // 如果我們使用js來開發拓展,則該檔案的尾碼為.js│   └── index.ts                // 如果我們使用js來開發拓展,則該檔案的尾碼為.js├── node_modules│   ├── vscode                  // vscode對typescript的語言支援。│   └── typescript              // TypeScript的編譯器├── out                         // 編譯之後的輸出檔案夾(只有TypeScript需要,JS無需)│   ├── src│   |   ├── extension.js│   |   └── extension.js.map│   └── test│       ├── extension.test.js│       ├── extension.test.js.map│       ├── index.js│       └── index.js.map├── package.json                // 該拓展的資源設定檔├── tsconfig.json               // ├── typings                     // 類型定義檔案夾│   ├── node.d.ts               // 和Node.js關聯的類型定義│   └── vscode-typings.d.ts     // 和VS Code關聯的類型定義└── vsc-extension-quickstart.md 


 此時,我們只需要點擊在VS Code的Debug地區的Start按鈕即可。


在接下來開啟的一個處於拓展開發模式的新的VS Code中,我們只需要在命令選擇區中輸入Hello World便可以啟用這個模板拓展,彈出一個Hello World的訊息彈窗。


那麼,VS Code到底是如何載入並運行拓展的呢?我們又應該如何開發拓展供自己甚至是分享給更多的人更好的使用VS Code呢?
0x02 關於package.json的兩三事
作為拓展項目的資源設定檔,package.json不僅僅描述了該拓展的資訊還描述了拓展的功能。需要說明的是,當VS Code啟動時,拓展的package.json檔案便會被讀取,並且VS Code還會對package.json檔案中的contributes部分的內容做處理。這一點和拓展的源檔案extension.ts有所區別。VS Code並不會在啟動時便載入拓展的原始碼。
下面我們就來看一看我們剛剛產生的這個拓展項目中的package.json檔案的內容吧。

{    "name": "Standard-Header",    "displayName": "Standard-Header",    "description": "standard-header",    "version": "0.0.1",    "publisher": "JiadongChen",    "engines": {        "vscode": "^0.10.1"    },    "categories": [        "Other"    ],    "activationEvents": [        "onCommand:extension.sayHello"    ],    "main": "./out/src/extension",    "contributes": {        "commands": [{            "command": "extension.sayHello",            "title": "Hello World"        }]    },    "scripts": {        "vscode:prepublish": "node ./node_modules/vscode/bin/compile",        "compile": "node ./node_modules/vscode/bin/compile -watch -p ./"    },    "devDependencies": {        "typescript": "^1.6.2",        "vscode": "0.10.x"    }}


我們可以看到,package.json描述了該拓展的一些基本資料,例如拓展的名稱name、拓展的描述資訊description以及拓展的版本號碼version和發行者的資訊publisher等等。順帶提一句,直接通過提高版本號碼的方式就可以使用拓展發布工具來更新已經發布到VS Code市集的拓展版本。
除了這些,我們甚至還可以在package.json檔案中配置一些拓展在VS Code的市集中的展示資訊,例如拓展在商店中的種類:categories、拓展的icon圖:icon以及拓展在應用市場首頁的一些展示資訊:galleryBanner等等。

..."icon": "res/icon.png","galleryBanner": {    "color": "#5c2d91",    "theme": "dark"},"categories": [    "Other"],...




當然,更重要的內容是activationEvents、contributes以及scripts和main這幾項內容。其中scripts項的內容是使用TypeScript進行開發時所特有的,主要的作用是用來提供對ts檔案進行編譯的相關資訊。而main項則指向了將ts源檔案編譯後所產生的js檔案。
ActivationEvents
正如上文所說,VS Code預設狀況下並不會在啟動時立刻執行拓展中的代碼。因此,為了使拓展能夠被啟用,我們需要在package.json檔案中定義activationEvents項的內容。例如上例中,activationEvents的定義如下:

..."activationEvents": [    "onCommand:extension.sayHello"],...


意思是當“onCommand:extension.sayHello”事件被觸發之後,拓展會被啟用。那麼在VS Code中,啟用事件都有哪些種類呢?下面我們就來歸一下類。
根據檔案所使用的語言:onLanguage:${language}
當開啟的檔案是使用onLanguage所規定的語言時,拓展會被啟用。
例如:

..."activationEvents": [    "onLanguage:python"]...


根據所輸入的命令:onCommand:${command}
當在onCommand中規定的命令被觸發時,拓展會被啟用。在上文產生的Hello World模板中,我們就可以看到。

..."activationEvents": ["onCommand:extension.sayHello"]...


根據檔案夾:workspaceContains:${toplevelfilename}

"activationEvents": [    "workspaceContains:package.json"],


 無限制:*

..."activationEvents": [    "*"]...


由於沒有限制,因此在VS Code一啟動時便會啟用該拓展。因此,這種不加以條件限制就啟用拓展的方式並不是十分推薦的。大家最好謹慎使用。
Contribution
在package.json檔案中的contributes項中,同樣包含很多種類。如果需要歸類的話,可以分為以下幾個類型。
configuration commands keybindings languages debuggers grammars themes snippets
但是本文限於篇幅,將只關注commands和keybindings這兩種。
commands
還以上文中的Hello World為例,我們在commands項中定義了命令的title以及title所對應的具體命令。如下所示:

"contributes": {    "commands": [{        "command": "extension.sayHello",        "title": "Hello World"    }]},


此時一旦安裝了該拓展,我們就可以在VS Code中的命令選擇區(我在Mac上的快速鍵是Shift+cmd+p)中找到“Hello World”,輸入便會觸發extension.sayHello這條命令,而上文中的拓展啟用事件項activationEvents中如果定義的內容是"onCommand:extension.sayHello",則啟用事件被觸發,拓展的代碼被啟用。


keybindings
當然,和commands對應的,我們還可以通過在package.json中定義keybindings項,通過綁定快速鍵的方式觸發命令。這樣操作起來更加便捷,例如下文中我們自己開發一個插入標準頁首的拓展時,使用的便是綁定快速鍵的方式。

"contributes": {    "keybindings": [{        "command": "extension.insertHeader",        "key": "shift+cmd+1",        "when": "editorTextFocus"    }]},


如果我們在VS Code中安裝了定義了快速鍵觸發的拓展,則開啟VS Code的KeyBoard ShortCut就可以看到拓展中定義的快速鍵和它對應的命令了。


0x03 VS Code運行拓展的原理
通過上一小節的內容,我們就能很清楚的理解上文中那個模板拓展的運行過程了。
VS Code首先會檢測到拓展並且讀取拓展的package.json檔案的內容並將package.json檔案中的contributes項應用到VS Code中。這樣,我們就可以根據contributes項中的內容,或者是在命令選擇區中輸入contributes項中定義的commands,或者是使用contributes項中所定義的快速鍵keybindings來觸發extension.sayHello命令。
一旦extension.sayHello觸發,VS Code會建立一個叫做onCommand:extension.sayHello的啟用事件。
與此同時,所有在自己的package.json檔案中將activationEvents設定為onCommand:extension.sayHello的拓展會被啟用。並且會根據package.json檔案中main項的內容,將./out/src/extension.js檔案載入到JavaScript VM中。接下來,VS Code會調用在extension.js檔案中的active函數,在active函數中,我們需要提供“extension.sayHello”這個函數的具體實現並執行。
好了,瞭解了VS Code拓展的基本知識之後我們就可以開始著手開發自己的拓展了,這個拓展的目的是向源檔案添加License頁首。
0x04 一個插入License頁首的拓展
既然要打造自己的VS Code,那麼自己喜歡的一些操作習慣自然希望能夠用在VS Code上。而插入頁首便是這樣一個簡單的小功能。
我們首先來看一看在上文中那個Hello World模板拓展的源檔案即extension.ts檔案的基本內容。

import * as vscode from ‘vscode‘;export function activate(context: vscode.ExtensionContext) {    var disposable = vscode.commands.registerCommand(‘extension.sayHello‘, () => {    ...
     vscode.window.showInformationMessage(‘Hello World!‘);
...

});}


首先,我們自然要引入vscode命名空間下的API,以獲得控制VS Code的能力。
其次,我們注意到了拓展的源檔案需要export一個叫做activate的函數,當拓展的package.json檔案中activationEvents所定義的事件被觸發時,VS Code會調用activate函數。
最後,我們可以看到我們使用vscode的API註冊了一個叫做“extension.sayHello”的命令,並且提供了它的具體實現,按照模板中的邏輯,“extension.sayHello”命令的邏輯是在視窗中顯示一個內容為“Hello World”的資訊訊息。具體的效果在本文一開始的部分各位已經看到了。
那麼接下來就十分簡單了,我們首先建立一個叫做HeaderGenerator的類,用來執行插入頁首的任務。

class HeaderGenerator {    private _disposable: Disposable;    public insertHeader() {        // Get the current text editor         let editor = window.activeTextEditor;         if (!editor) {             return;         }                 // Define header content        var header = "License Header";                // Get the document        var doc = editor.document;                // Insert header        editor.edit((eb) => {            eb.insert(doc.positionAt(0), header);        });    }          dispose() {        this._disposable.dispose();    }}


插入頁首的具體執行是當前視窗的editor(TextEditor類)的edit方法,通過利用TextEditorEdit類的insert方法實現對當前的文檔doc(TextDocument類)插入新的內容。
之後,我們只需在extension.ts檔案中的activate函數中實現調用HeaderGenerator類的insertHeader方法即可。

import * as vscode from ‘vscode‘; import {window, commands, Disposable, ExtensionContext, TextDocument} from ‘vscode‘;export function activate(context: vscode.ExtensionContext) {    console.log(‘Congratulations, your extension "standard-header" is now active!‘);     let headerGen = new HeaderGenerator();    var disposable = vscode.commands.registerCommand(‘extension.insertHeader‘, () => {        headerGen.insertHeader();    });    context.subscriptions.push(headerGen);    context.subscriptions.push(disposable);}


當然,為了增加快速鍵“shift+cmd+1”的支援,我們還需要在package.json中修改contributes的內容:

"contributes": {    "keybindings": [{        "command": "extension.insertHeader",        "key": "shift+cmd+1",        "when": "editorTextFocus"    }]},


之後,讓我們先進入拓展開發模式看一下效果。使用快速鍵shift+cmd+1,我們可以看到在VS Code的視窗中插入了頁首(中的頁首內容我已經換成了MIT協議)。


好了,到此我們的小小的在源檔案中插入頁首的拓展就完成了,下面就讓我們來使用安裝、甚至是發布到VS Code的市集讓大家一起分享我們的勞動成果吧。
0x05 本地安裝或在市集發布
為了不必再每次都要進入拓展開發模式才能“使用”我們的拓展,我們就必須讓自己的VS Code安裝這個拓展。
事實上在本地安裝供自己的拓展是十分簡單並且方便的事情。VS Code會在.vscode/extensions檔案夾中擷取本地的拓展。而.vscode/extensions檔案夾所在的位置我們可以總結如下:
Windows %USERPROFILE%\.vscode\extensions Mac $HOME/.vscode/extensions Linux $HOME/.vscode/extensions
我們只需拷貝一份我們的拓展到.vscode/extensions檔案夾中,VS Code在啟動時便能夠檢查到該拓展了。
當然,除了自己使用自己開發的拓展之外,我們還可以將拓展發布到VS Code的市集。此時我們就要藉助一個拓展發布工具——vsce了。
首先是安裝vsce:

npm install -g vsce


之後我們還需要到Visual Studio Team Services註冊並登陸,以擷取Personal Access Token。
一旦擷取了Personal Access Token,我們就可以使用vsce建立一個發行者帳號了。

vsce create-publisher 


緊接著,登陸並發布:

vsce login vsce publish


發布成功之後,我們就可以在VS Code的市集中看到自己的拓展了。


並且在VS Code的命令選擇區中,我們也可以使用命令安裝:

ext install 




好啦,行文至此,使用TypeScript拓展你自己的VS Code講的已經差不多了。希望各位多多交流~

使用TypeScript拓展你自己的VSCode

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.