在前幾天的美國紐約,微軟舉行了Connect(); //2015大會。經過此次大會,咱們能夠很高興的看到微軟的確變得更加開放也更加務實了。固然,會上放出了很多新產品和新功能,其中就包括了VS Code的beta版本。並且微軟更進一步,已經在github將VS Code的代碼開源了。除了這些讓人興奮的消息,咱們還應該注意到VS Code提供了對拓展的支持。
因此本文就來聊一聊使用TypeScript開發VS Code拓展的話題吧。
本文所使用的拓展的應用商店頁面:node
https://marketplace.visualstudio.com/items/JiadongChen.LicenseHeaderpython
github頁面:git
https://github.com/chenjd/VSCode-StandardHeadergithub
"萬事開頭,Hello World"。因此咱們就從一個Hello World做爲起點,開始一步一步構建本身的VScode的拓展。
在開發vscode的拓展以前,咱們先要確保電腦上已經安裝了Node.js。以後,咱們即可以利用微軟所提供的基於Yeoman的模板生成器來生成vscode拓展的模板了。typescript
npm install -g yo generator-code
以後,咱們只須要在終端中運行yo code命令,便可以進入建立拓展模板的引導過程。npm
yo code
在引導過程當中將TypeScript選擇爲開發語言,而且填完一些基本信息以後,咱們的第一個vscode拓展便建立完成了。
那麼,yo code命令主要爲咱們作了一些什麼事情呢?json
會根據咱們在引導中所填的信息,在當前目錄生成一個拓展的文件夾,文件夾名即咱們在引導中填入的拓展名稱。併發
該文件夾中主要包括了盛放源文件(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呢?
做爲拓展項目的資源配置文件,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文件。
正如上文所說,VS Code默認情況下並不會在啓動時馬上執行拓展中的代碼。所以,爲了使拓展可以被激活,咱們須要在package.json文件中定義activationEvents項的內容。例如上例中,activationEvents的定義以下:
... "activationEvents": [ "onCommand:extension.sayHello" ], ...
意思是當「onCommand:extension.sayHello」事件被觸發以後,拓展會被激活。那麼在VS Code中,激活事件都有哪些種類呢?下面咱們就來歸一下類。
當打開的文件是使用onLanguage所規定的語言時,拓展會被激活。
例如:
... "activationEvents": [ "onLanguage:python" ] ...
當在onCommand中規定的命令被觸發時,拓展會被激活。在上文生成的Hello World模板中,咱們就能夠看到。
... "activationEvents": [ "onCommand:extension.sayHello" ] ...
"activationEvents": [ "workspaceContains:package.json" ],
... "activationEvents": [ "*" ] ...
因爲沒有限制,所以在VS Code一啓動時便會激活該拓展。所以,這種不加以條件限制就激活拓展的方式並非十分推薦的。你們最好謹慎使用。
在package.json文件中的contributes項中,一樣包含不少種類。若是須要歸類的話,能夠分爲如下幾個類型。
configuration commands keybindings languages debuggers grammars themes snippets
可是本文限於篇幅,將只關注commands和keybindings這兩種。
還以上文中的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",則激活事件被觸發,拓展的代碼被激活。
固然,和commands對應的,咱們還能夠經過在package.json中定義keybindings項,經過綁定快捷鍵的方式觸發命令。這樣操做起來更加便捷,例以下文中咱們本身開發一個插入標準頁眉的拓展時,使用的即是綁定快捷鍵的方式。
"contributes": { "keybindings": [{ "command": "extension.insertHeader", "key": "shift+cmd+1", "when": "editorTextFocus" }] },
若是咱們在VS Code中安裝了定義了快捷鍵觸發的拓展,則打開VS Code的KeyBoard ShortCut就能夠看到拓展中定義的快捷鍵和它對應的命令了。
經過上一小節的內容,咱們就能很清楚的理解上文中那個模板拓展的運行過程了。
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頁眉。
既然要打造本身的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的應用商店讓你們一塊兒分享咱們的勞動成果吧。
爲了避免必再每次都要進入拓展開發模式才能「使用」咱們的拓展,咱們就必須讓本身的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講的已經差很少了。但願各位多多交流~