從0到1開(kāi)發(fā)一款自己的Vscode插件
一、vscode插件是什么?
大家對(duì)vscode肯定都不陌生,其是微軟推出的一款輕量級(jí)代碼編輯器,在使用的時(shí)候總會(huì)時(shí)不時(shí)的安裝一些插件去協(xié)助我們進(jìn)行開(kāi)發(fā),這些插件就是利用vscode給我們開(kāi)放的一些API的基礎(chǔ)上進(jìn)行擴(kuò)展功能的開(kāi)發(fā),從而解決開(kāi)發(fā)中的一些問(wèn)題,提高生產(chǎn)效率。這種插件化思想一方面使該代碼編輯器更輕量化;另一方面能夠充分利用社區(qū)的力量,為其提供更加多元化的插件。(下圖是我做的一個(gè)小插件的效果圖)
二、vscode插件能做什么?
vscode插件能做什么?其核心點(diǎn)在于vscode為其提供了哪些開(kāi)放能力,只有其開(kāi)放的能力才能為我們所用,就官網(wǎng)來(lái)看,利用vscode插件能夠做以下事情(該部分來(lái)自于vscode官網(wǎng)擴(kuò)展能力概述部分):
通用功能
可以在任何擴(kuò)展中使用的核心功能,主要包括以下幾點(diǎn):
(1)能夠添加命令、配置項(xiàng)、快捷鍵、菜單項(xiàng)、右鍵菜單;
(2)存儲(chǔ)工作區(qū)或全局?jǐn)?shù)據(jù);
(3)展示通知信息;
(4)使用快速選擇收集用戶的輸入;
(5)打開(kāi)文件選擇器讓用戶去選擇文件或文件夾;
(6)使用Progress API去闡述長(zhǎng)時(shí)間運(yùn)行的操作;
主題化
控制vscode的外觀,包括編輯器中源代碼的顏色和vscode ui的顏色,其主要包含三種類型的主題:
(1)顏色主題:其允許將顏色應(yīng)用于VS Code UI組件和編輯器中的文本;
(2)文件圖標(biāo)主題:文件圖標(biāo)顯示在VS Code UI中的位置,例如文件資源管理器、快速打開(kāi)列表和編輯器選項(xiàng)卡;
(3)產(chǎn)品圖標(biāo)主題:在整個(gè)UI中使用的一組圖標(biāo)
聲明性語(yǔ)言特性
聲明性語(yǔ)言功能為編程語(yǔ)言添加了基本的文本編輯支持,例如括號(hào)匹配、自動(dòng)縮進(jìn)和語(yǔ)法突出顯示。
程序語(yǔ)言特性
編程語(yǔ)言功能添加了豐富的編程語(yǔ)言支持,例如懸停、轉(zhuǎn)到定義、診斷錯(cuò)誤、IntelliSense 和 CodeLens。
擴(kuò)展工作臺(tái)
工作臺(tái)是指包含標(biāo)題欄、活動(dòng)欄、側(cè)邊欄、控制板、編輯組、狀態(tài)欄等UI組件的整體Visual Studio Code UI。VS Code提供了各種API,允許將自己的組件添加到工作臺(tái)。
調(diào)試
可以通過(guò)編寫將 VS Code 的調(diào)試 UI 連接到特定調(diào)試器或運(yùn)行時(shí)的調(diào)試器擴(kuò)展來(lái)利用 VS Code 的調(diào)試功能。
三、vscode插件實(shí)戰(zhàn)
vscode插件其實(shí)是vscode對(duì)外提供了一些能力,如果不是特別需要其實(shí)沒(méi)有必要完整的學(xué)習(xí)整體內(nèi)容,僅僅需要了解其大體開(kāi)發(fā)思路、能夠解決的問(wèn)題,之所以這么說(shuō)是因?yàn)?以上純個(gè)人觀點(diǎn),不一定正確)學(xué)習(xí)該部分的內(nèi)容需要一定精力,但學(xué)后并不一定能夠在自己項(xiàng)目中得到使用,深入學(xué)習(xí)投入于產(chǎn)出并不成正比,所以本次我只會(huì)講述入門級(jí)內(nèi)容,具體的內(nèi)容扔需要讀者在需要這一部分能力的時(shí)候再深入研究。
3.1 項(xiàng)目初始化
官方為了方便開(kāi)發(fā)人員進(jìn)行vscode插件的開(kāi)發(fā),提供了對(duì)yo應(yīng)的腳手架來(lái)生成對(duì)應(yīng)的項(xiàng)目。
- // 安裝需要的包
- npm install -g yo generator-code
- // 運(yùn)行
- yo code
上述命令其實(shí)安裝了兩個(gè)包(yo和generator-code),這兩個(gè)包用途如下:
yo模塊全局安裝后就安裝了Yeoman,Yeoman是通用型項(xiàng)目腳手架工具,可以根據(jù)一套模板,生成一個(gè)對(duì)應(yīng)的項(xiàng)目結(jié)構(gòu)
generator-code模塊是VS Code擴(kuò)展生成器,與yo配合使用才能構(gòu)建項(xiàng)目。
3.2 重要文件
在項(xiàng)目生成之后,目錄結(jié)構(gòu)如下所示,其中最重要的文件是package.json和extension.js,了解這兩個(gè)文件基本上就可以入門開(kāi)發(fā)一個(gè)vscode插件了。
3.2.1 package.json
該文件是vscode擴(kuò)展的清單文件,里面有很多字段,官方對(duì)每個(gè)字段都進(jìn)行了詳細(xì)闡述,本次我們重點(diǎn)闡述以下初始化后期清單文件。
- {
- "name": "demo", // 插件名
- "displayName": "插件", // 顯示在應(yīng)用市場(chǎng)的名字
- "description": "我的第一個(gè)插件測(cè)試", // 具體描述
- "version": "0.0.1", // 插件的版本號(hào)
- "engines": {
- "vscode": "^1.60.0" // 最低支持的vscode版本
- },
- "categories": [
- "Other" // 擴(kuò)展類別
- ],
- // 激活事件組,在那些事件情況下被激活
- "activationEvents": [
- "onCommand:demo.helloWorld"
- ],
- // 插件的主入口文件
- "main": "./extension.js",
- // 貢獻(xiàn)點(diǎn)
- "contributes": {
- // 命令
- "commands": [
- {
- "command": "demo.helloWorld",
- "title": "Hello World"
- }
- ]
- },
- "scripts": {
- "lint": "eslint .",
- "pretest": "npm run lint",
- "test": "node ./test/runTest.js"
- },
- // 開(kāi)發(fā)依賴項(xiàng)
- "devDependencies": {
- "@types/vscode": "^1.60.0",
- "@types/glob": "^7.1.3",
- "@types/mocha": "^8.2.2",
- "@types/node": "14.x",
- "eslint": "^7.27.0",
- "glob": "^7.1.7",
- "mocha": "^8.4.0",
- "typescript": "^4.3.2",
- "vscode-test": "^1.5.2"
- }
- }
在這份清單文件中,重點(diǎn)關(guān)注的主要有三部分內(nèi)容:activationEvents、main以及contributes,其是整個(gè)文件中的重中之重。
main
指明了該插件的主入口在哪,只有找到主入口整個(gè)項(xiàng)目才能正常的運(yùn)轉(zhuǎn)、
activationEvents
指明該插件在何種情況下才會(huì)被激活,因?yàn)橹挥屑せ詈蟛寮拍鼙徽J褂?,官網(wǎng)已經(jīng)指明了激活的時(shí)機(jī),這樣我們就可以按需設(shè)置對(duì)應(yīng)時(shí)機(jī)。(具體每個(gè)時(shí)機(jī)用的時(shí)候詳細(xì)查看即可)
- onLanguage 打開(kāi)解析為特定語(yǔ)言文件時(shí)被激活,例如"onLanguage:python"
- onCommand 在調(diào)用命令時(shí)被激活
- onDebug 在啟動(dòng)調(diào)試話之前被激活
- onDebugInitialConfigurations
- onDebugResolve
- workspaceContains 每當(dāng)打開(kāi)文件夾并且該文件夾包含至少一個(gè)與 glob 模式匹配的文件時(shí)
- onFileSystem 每當(dāng)讀取來(lái)自特定方案的文件或文件夾時(shí)
- onView 每當(dāng)在 VS Code 側(cè)欄中展開(kāi)指定 id 的視圖
- onUri 每當(dāng)打開(kāi)該擴(kuò)展的系統(tǒng)范圍的 Uri 時(shí)
- onWebviewPanel
- onCustomEditor
- onAuthenticationRequest
- * 只要一啟動(dòng)vscode,插件就會(huì)被激活
- onStartupFinished
contributes
通過(guò)擴(kuò)展注冊(cè)contributes用來(lái)擴(kuò)展Visual Studio Code中的各項(xiàng)技能,其有多個(gè)配置,如下所示:
- breakpoints 斷點(diǎn)
- colors 主題顏色
- commands 命令
- configuration 配置
- configurationDefaults 默認(rèn)的特定于語(yǔ)言的編輯器配置
- customEditors 自定義編輯器
- debuggers
- grammars
- iconThemes
- jsonValidation
- keybindings 快捷鍵綁定
- languages
- menus
- problemMatchers
- problemPatterns
- productIconThemes
- resourceLabelFormatters
- snippets 特定語(yǔ)言的片段
- submenus
- taskDefinitions
- themes 顏色主題
- typescriptServerPlugins
- views
- viewsContainers
- viewsWelcome
- walkthroughs
3.2.2 extension.js文件
該文件時(shí)其入口文件,即package.json中main字段對(duì)應(yīng)的文件(不一定叫extension.js這個(gè)名字),該文件中將導(dǎo)出兩個(gè)方法:activate和deactivate,兩個(gè)方法的執(zhí)行時(shí)機(jī)如下所示:
activate
這是插件被激活時(shí)執(zhí)行的函數(shù)
deactivate
這是插件被銷毀時(shí)調(diào)用的方法,比如釋放內(nèi)存等。
3.3 實(shí)戰(zhàn)
上述已經(jīng)對(duì)vscode插件有了基礎(chǔ)的認(rèn)識(shí),下面就進(jìn)行一個(gè)簡(jiǎn)單的實(shí)戰(zhàn),打造屬于自己的一個(gè)vscode插件,此插件的功能如下:
通過(guò)在文件編輯區(qū)域或文件名上右擊彈出按鈕,點(diǎn)擊按鈕獲取文件的大小、創(chuàng)建時(shí)間和修改時(shí)間;
如果獲取的是文件夾,則指明該文件是文件夾,不是文件,給予提示。
3.3.1 package.json修改項(xiàng)
- {
- // ……
- // 在getFileState指令下激活
- "activationEvents": [
- "onCommand:getFileState"
- ],
- // 入口文件
- "main": "./extension.js",
- "contributes": {
- // 命令
- "commands": [
- {
- "command": "getFileState",
- "title": "File State"
- }
- ],
- // 菜單項(xiàng)
- "menus": {
- // 編輯上下文菜單
- "editor/context": [
- {
- "when": "editorFocus",
- "command": "getFileState",
- "group": "navigation"
- }
- ],
- // 資源管理器上下文菜單
- "explorer/context": [
- {
- "command": "getFileState",
- "group": "navigation"
- }
- ]
- }
- },
- // ……
- }
3.3.2 主函數(shù)內(nèi)容
- const vscode = require('vscode');
- const fs = require('fs');
- function activate(context) {
- console.log('插件已經(jīng)被激活');
- // 注冊(cè)命令
- let commandOfGetFileState = vscode.commands.registerCommand('getFileState', uri => {
- // 文件路徑
- const filePath = uri.path.substring(1);
- fs.stat(filePath, (err, stats) => {
- if (err) {
- vscode.window.showErrorMessage(`獲取文件時(shí)遇到錯(cuò)誤了${err}!!!`)
- }
- if (stats.isDirectory()) {
- vscode.window.showWarningMessage(`檢測(cè)的是文件夾,不是文件,請(qǐng)重新選擇?。。);
- }
- if (stats.isFile()) {
- const size = stats.size;
- const createTime = stats.birthtime.toLocaleString();
- const modifyTime = stats.mtime.toLocaleString();
- vscode.window.showInformationMessage(`
- 文件大小為:${size}字節(jié);
- 文件創(chuàng)建時(shí)間為:${createTime};
- 文件修改時(shí)間為:${modifyTime}
- `, { modal: true });
- }
- });
- const stats = fs.statSync(filePath);
- console.log('stats', stats);
- console.log('isFile', stats.isFile());
- });
- // 將命令放入其上下文對(duì)象中,使其生效
- context.subscriptions.push(commandOfGetFileState);
- }
- function deactivate() {}
- module.exports = {
- activate,
- deactivate
- }
3.3.3 效果圖
經(jīng)過(guò)開(kāi)發(fā)后,該插件調(diào)試效果如下所示:
3. 4 發(fā)布
插件看法完畢之后就是需要分享出去供大家使用,目前有三種方式:
直接把文件夾發(fā)給別人,讓別人找到vscode的插件存放目錄并放進(jìn)去,然后重啟vscode,一般不推薦;
打包成vsix插件,然后發(fā)送給別人安裝,如果你的插件涉及機(jī)密不方便發(fā)布到應(yīng)用市場(chǎng),可以嘗試采用這種方式;
注冊(cè)開(kāi)發(fā)者賬號(hào),發(fā)布到官網(wǎng)應(yīng)用市場(chǎng),這個(gè)發(fā)布和npm一樣是不需要審核的。
每一種方式都可行,并且網(wǎng)上也有很多教程講述其發(fā)布方式,今天我重點(diǎn)講述一下第二種,畢竟在插件這么多的情況下,很多人更樂(lè)于開(kāi)發(fā)一款屬于自己的專用插件或者特定自己領(lǐng)域使用的插件,完全沒(méi)必要發(fā)布到應(yīng)用市場(chǎng)。
安裝對(duì)應(yīng)的模塊vsce
- npm i vsce -g
利用vsce進(jìn)行打包,生成對(duì)應(yīng)的vsix文件
- vsce package
安裝到vscode
安裝完成之后就可以正常的進(jìn)行使用了
四、總結(jié)
因?yàn)楣ぷ髦心壳斑€沒(méi)有遇到這種需求,此次我只是對(duì)vscode插件的開(kāi)發(fā)流程進(jìn)行了一個(gè)簡(jiǎn)單的概述,并沒(méi)有進(jìn)一步深入探索,待工作中有這樣的場(chǎng)景需要這樣的能力去解決某些問(wèn)題時(shí),能夠快速反應(yīng)有這樣的解決方案,再進(jìn)一步學(xué)習(xí)也為時(shí)不晚,也希望愛(ài)學(xué)習(xí)的小伙伴們也對(duì)這一部分能夠有一定了解,彌補(bǔ)自己知識(shí)上欠缺的一環(huán),后續(xù)為己所用。
五、參考文獻(xiàn)
vscode插件編寫實(shí)戰(zhàn)
vscode插件開(kāi)發(fā)全攻略
本文轉(zhuǎn)載自微信公眾號(hào)「前端點(diǎn)線面」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系前端點(diǎn)線面公眾號(hào)。