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