保姆級指南:一文擁有屬於你的vscode外掛

語言: CN / TW / HK

王志遠: 微醫前端技術部。

經常在掘金公司團隊發文章,而所在公司前端發文存在自己的固定格式,主要包含

  • ([\u4e00-\u9fa5]+)([\da-zA-Z]+) 替換為 $1 $2 :中文和英文要有一個空格
  • ([\da-zA-Z]+)([\u4e00-\u9fa5]+) 替換為 $1 $2 :中文和英文要有一個空格
  • !\[.+\] 替換為 ![] :處理圖片描述
  • 頭部插入主題,內容如下

---
theme: cyanosis
highlight: atom-one-dark
---
> 自我介紹

這些動作每次需要人為處理,費時費力且易出錯,固化流程嘗試改用 vscode 外掛自動實現,遂有 edit-article 外掛出現;

相關連結

貼下相關連結,可以直接down下來看看,如有類似需求可以留言提需求我來完成。(也求 star)

  • github:https://github.com/Sympath/edit-article-plugin

  • vscode 市場:edit-article

當前實現效果

本文目標

實現一款自己的 vscode 外掛併發布在應用市場,所有人可以在 vscode 擴充套件中搜索並下載;由於文章目標是實現效果,所以不打算用自己實現的 edit-article 外掛作為案例。

  • 思路:vscode 外掛是個 node 應用,那我們只需要找到對應的腳手架建立基礎,再實現我們外掛特定的功能即可

  • 本文 demo 外掛功能:快捷鍵反轉選中的字串

  • 實現效果:

實戰系列文章專注產出,看一個東西出現的滿足感是會上癮的,讓我們拋棄文件式的學習,開始吧!

腳手架建立基礎模板

安裝及使用

首先你需要的是 yeoman,一個腳手架工具。通過 yeoman 你可以快速建立程式碼模板,如下所示:

npm install -g yo

然後你需要安裝 VS Code 的模板:

npm install -g generator-code

有了腳手架,你就可以建立一個 VS Code 的外掛模板了。接下來執行:

yo code myextension

請注意,第三個引數將是你新建立的外掛的資料夾名字。

VS Code 外掛腳手架介紹

由上圖,你可以看到有七個外掛模板:

  • 前兩個是通過程式設計來提供外掛功能,你可以選擇 TypeScript 或者 JavaScript,結果都是類似的,因為 TypeScript 最後也需要被編譯成 JavaScript 再發布;

  • 第三個是主題外掛,你可以將你自己建立的主題分享給其他人;

  • 第四個是語言支援,也就是語法高亮、語言定義等;

  • 第五個是程式碼片段的分享;

  • 第六個則是分享快捷鍵;

  • 第七個就是對多個外掛進行組合分享。

先實現最基礎的 New Extension (JavaScript) ,即 javascript 版模板

接下來,你會依次被提示輸入外掛的名字、介紹、想要用哪個賬號釋出、是否要開啟 type check 以及是否要使用 git 等。你可以暫時按照我的樣例進行輸入,之後也可以再根據需要修改。

專案基礎資訊介紹

切換到專案根目錄

cd myextension

專案目錄結構及對應資訊

├── .vscode
│ ├── launch.json // 外掛載入和除錯的配置
│ └── tasks.json // 配置 TypeScript 編譯任務
├── .gitignore // 忽略構建輸出和 node_modules 檔案
├── README.md // 外掛文件
├── CHANGELOG.md // 外掛更新日誌
├── extension.ts // 外掛原始碼
├── package.json // 外掛配置清單
├── jsconfig.json //

檢視效果

啟動預設專案,按下 F5 啟動除錯,如果打開了一個 vscode 新視窗,試試開啟命令面板執行 hello world ,如果執行出現了彈窗,就說明我們建立 vscode 外掛專案成功啦。

命令面板喚起快捷鍵

  • mac: cmd + shift + p
  • win: ctrl + shift + p

關於面板的更多資訊可以閱讀:你不知道的 vscode 之空間控制

實現業務 -- 反轉字串

我們在之前已經知道了怎麼用腳手架建立 vscode 外掛專案,接下來就是實現我們自己的業務邏輯了。本章目標只有兩個

  • 功能:實現命令【選中文字反轉字串】

    • package.json 中註冊命令和對應的描述

    • extension.js 中完成命令的實現

  • 優化:繫結快捷鍵

注意:建議在 launch.json 中的“args”中新增"--disable-extensions",阻止其他外掛載入,不然要除錯的外掛載入很慢。

命令的註冊:package.json

我們先了解下【命令的註冊】,先說流程

  • package.json 中註冊命令和對應的描述

  • extension.js 中完成命令的實現

package.json 中註冊命令和對應的描述

package.json 中存在 contributes 物件,有屬性 commands 對應著命令陣列,每個命令是一個物件有如下屬性

  • command:命令的 key,在命令的實現中會被用到

  • title:命令描述,會出現在命令面板中

配置如下

"commands": [
{
"command": "edit-article.reserve",
"title": "Hello reserve"
}
],

配置完成!

命令的實現:extension.js

前置總結

  • package.json 中通過配置 activationEvents ,定義外掛的啟用時機
  • 專案根路徑的 extension.js 檔案中通過 active 鉤子註冊命令和對應的實現

啟用時機:activationEvents

我們的業務邏輯實現在專案根路徑的 extension.js 檔案中,預設匯出兩個鉤子方法

  • activate:外掛啟用時

  • deactivate:外掛關閉時

module.exports = {
activate,
deactivate,
};

這裡的啟用時機並不是一開啟 vscode 就執行,而是需要在 package.json 中存在一個屬性 activationEvents ,值是一個數組,儲存著所有會觸發外掛啟用的時機;改為開啟 js 檔案時才會啟用,配置如下

"activationEvents": [
"onLanguage:javascript"
],

業務邏輯實現

extension.js 檔案中還引入了一個 vscode 物件,這是 vscode 提供能力的載體,我們在後面單獨分析。

const vscode = require("vscode");

這裡的 active 函式實現的邏輯很清晰。首先,我們要讀取的資訊就是當前的文件資訊和主游標的資訊。

let document = editor.document;
let selection = editor.selection;

有了這兩個資訊,讀取游標選中的內容就簡單了。

let text = document.getText(selection);

document 一共哪些 API 這裡我就不介紹了,相信你可以自己探索,這裡我們使用就是 getText,以獲取某段程式碼。

接下來就是將這段文字進行反轉了,我們可以寫一個非常簡單的版本,將字串分割成字母陣列,然後反轉,最後重新組合成字串。

let result = text.split('').reverse().join('');

最後一步操作就是將原來編輯器內的文字進行替換了。此時我們就要用到 edit 這個 API 函式 了。值得注意的是,這個 API 的第一引數,是一個 callback,callback 的引數是 editBuilder,也就是真正用於修改程式碼的物件。

editBuilder 有以下幾個 API:

  • delete

  • insert

  • replace

  • setEndOfLine

這裡我們要使用的當然就是 replace 了。

editBuilder.replace(selection, result);

我們只需將原先的 selection 裡的內容,替換成新的 result 即可。

完整程式碼如下

const vscode = require("vscode");

function activate(context) {

let reserve = vscode.commands.registerCommand(
"edit-article.reserve",
function () {
let editor = vscode.window.activeTextEditor;
if (!editor) {
return;
}
let document = editor.document;
let selection = editor.selection;
let text = document.getText(selection);
let result = text.split("").reverse().join("");
editor.edit((editBuilder) => {
editBuilder.replace(selection, result);
});
}
);
context.subscriptions.push(reserve);
}
function deactivate() {}

module.exports = {
activate,
deactivate,
};

至此,如何註冊一個命令我們也就瞭解到了,當我們要實現其他功能,自然重點就成了 vscode 這個物件,在文末【擴充套件】模組分享。

優化:繫結快捷鍵

實現繫結

支援我們完成了命令的設定、命令的實現,但每次都要自己找命令面板去執行;如果我們能用一個快捷鍵繫結命令,按下快捷鍵就執行,會不會方便很多?說幹就幹!

package.jsoncontributes 中還存在 keybindings 屬性,就是用於實現繫結快捷鍵的,這是一個物件陣列,儲存的物件結構如下

  • key:快捷鍵

  • command:命令

  • when:何時觸發

假定我們將反轉命令繫結在 ctrl+shift+r 上,就可以新增如下內容

"keybindings": [
{
"key": "ctrl+shift+r",
"command": "edit-article.reserve"
}
]

實現效果

釋出外掛

終於,到了最激動人心的時刻!還記得第一次在瀏覽器上看到我們頁面時的激動嗎?再一次,讓我們回到那個瞬間。按後文一步步走,遇到過按別人文章走結果遇問題卡一半的痛苦,所以詳細(囉嗦)了點,大家多擔待,無論如何,結果親測有效!

要釋出,先建立賬號

Visual Studio Code 的 應用市場 基於微軟自己的 Azure DevOps ;所以需要在兩個平臺都註冊好賬號。有賬號後,根據 Azure DevOps 平臺生成 PATPersonal Access Token ,個人訪問令牌);根據 應用市場 建立釋出者賬號,有了這兩者就能釋出了。

整理如下

  • 註冊賬號

  • 根據 Azure DevOps 平臺生成 PATPersonal Access Token ,個人訪問令牌);
  • 根據 應用市場 建立釋出者賬號

  • 根據 vsce 在本地釋出

根據 Azure DevOps 平臺生成 token

登入 Microsoft

首先訪問Microsoft 官網登入你的 Microsoft 賬號,沒有的先註冊一個:

中間會要求輸入郵箱,沒有也可以直接通過手機號獲取一個

一路 next,直到建立成功。

登入 Azure

然後訪問:Azure 官網 ,如果你從來沒有使用過 Azure,那麼會看到如下提示:

點選繼續,預設會建立一個以郵箱字首為名的組織。(只需要填寫驗證碼即可)

建立令牌

預設進入組織的主頁後,點選右上角的 Security

點選建立新的個人訪問令牌,這裡特別要注意

  • Organization 要選擇`all accessible organizations``
  • ``Scopes 要選擇 Full access

否則後面釋出會失敗。

建立令牌成功後你 需要本地記下來 ,因為網站是不會幫你儲存的。

根據應用市場建立釋出者賬號

訪問應用市場,填完名稱,滑到最後儲存即可

至此,我們就有了如下內容

  • PAT:Personal Access Token,個人訪問令牌

  • publisher:釋出者賬號

就可以執行在本地釋出的動作啦!

根據 vsce 在本地釋出

進入自己的外掛,如果沒有,可以閱讀【外掛腳手架:如何建立一個外掛】瞭解建立

配置外掛資訊

在釋出前,我們需要配置一些專案資訊在 package.json 中,下面是必備資訊

  • publisher:釋出者 id

  • activationEvents:擴充套件的啟用事件,建議先填指定檔案型別啟用(如 js 檔案, onLanguage:javascript )配置項可見官網文件
  • repository:倉庫地址

其他還有很多配置,我們慢慢了解,文末放置 package.json 配置總覽。

安裝命令包

利用釋出工具釋出外掛

vsce是一個用於將外掛釋出到市場上的命令列工具。

請確認本機已經安裝了Node.js,然後執行:

npm install -g vsce

然後你就可以在命令列裡直接使用 vsce 了。下面是一個快速釋出的示例

  1. 登陸

vsce login [publisherName]
# 然後輸入之前獲取到的 token
  1. 執行釋出(這裡的 patch 是指自動更新版本後釋出,不帶也可以,就得手動修改 package.json 檔案了)
$ vsce publish patch
Publishing [email protected]
Successfully published [email protected]!

完成後過幾分鐘就可以去 vscode 的擴充套件區看自己的外掛啦!

檢視結果

一圖勝千言,靜靜體會成就感的美妙吧!

至此,閱讀本文的小夥伴應該已經在外掛市場上可以找到自己的外掛啦。

老規矩,分享一個感悟:重視你的、甚至是別人的每一個吐槽,嘗試解決它,這就是成長。

擴充套件知識:package.json 配置總覽

// package.json
{
"name": "vscode-demo",
"displayName": "vscode-demo",
"description": "",
"version": "0.0.1",
"repository""",// 倉庫地址
"publisher": "", //釋出者 id,後面會講怎麼釋出到外掛市場
"engines": { //vscode 最低版本
"vscode": "^1.57.0"
},
"categories": [ //外掛市場的分類 可以設定成語言主題等其他型別
"Other"
],
"activationEvents": [ //擴充套件的啟用事件
"onCommand:vscode-demo.helloWorld", //呼叫命令時啟用
"onLanguage:python", //py 時啟用外掛
"workspaceContains:**/.editorconfig",// 資料夾開啟時啟用
"onDebug",//除錯前啟用
...
"*" //啟動時候啟用,使用這個不需要設定其他的
],
"main": "./extension.js", //指定外掛入口檔案
"icon": "", //外掛圖示
"contributes": { //大部分的配置都要在這裡配置
"commands":[], //配置命令,如果需要暴露給使用者使用的需要在這裡配置
"menus":[], //配置選單
"submenus":[], //配置子選單會用到
"languages": [], //配置語言
"grammars":[], //為語言配置 TextMate 語法
"keybindings":[], //配置快捷鍵
"snippets":[], //配置程式碼片段
"themes":[], //配置主題
"views":[], //配置活動欄檢視
"viewsWelcome":[], //配置左側檢視歡迎頁
"viewsContainers":[], //配置檢視容器
"configuration":{}, //配置外掛配置
"configurationDefaults":{}, //配置外掛預設配置
"colors":{},
"problemMatchers":{},
"taskDefinitions":{},
"typescriptServerPlugins":{}
},
}

擴充套件知識:vscode 釋出相關

釋出鉤子

預釋出步驟

可以在清單檔案中新增預釋出步驟,下面的命令會在外掛每次打包時執行:

{
"name": "uuid",
"version": "0.0.1",
"publisher": "joaomoreno",
"engines": {
"vscode": "0.10.x"
},
"scripts": {
"vscode:prepublish": "tsc"
}
}

上面的示例會在每次外掛打包時呼叫 Typescript 編譯器。

增量更新外掛版本

用 SemVer 語義識別符號: major (最大位加一), minor (次位加一), patch (最小位加一)增量更新外掛版本號。

例如,你想把外掛從 1.0.0 更新到 1.1.0,那麼加上 minor

vsce publish minor

外掛 package.json 的 version 會先更新,然後才釋出外掛。

你也可以通過命令列指定版本號:

vsce publish 2.0.1

更多可用的命令引數,請使用 vsce --help

擴充套件知識:vscode 提供能力

獲取編輯器物件

既然是編輯器相關的命令,那麼我們肯定需要能夠訪問到編輯器,以及其中的內容。首先我們要獲取的就是:當前工作區內,使用者正在使用的編輯器。

const vscode = require('vscode');
let editor = vscode.window.activeTextEditor;

我們重點關注的也是這個物件。

有了這個編輯器,我們就能獲取非常多的資訊了。不過先別急,editor 這個變數並非一定總是有效的值,比如使用者現在並沒有開啟任何檔案,編輯器是空的,那麼此時 editor 的值就是 undefined。所以, 在正式使用 editor 之前,我們要判斷一下,editor 是否為 undefined,是的話就結束命令的執行。

if (!editor) {
return;
}

接下來,我們可以輸入 editor. ,自動補全立刻給我們提示了不少的屬性。

編輯器物件能力

  • document,也就是當前編輯器中的文件內容;

  • edit,用於修改編輯器中的內容;

  • revealRange,用於將某段程式碼滾動到當前視窗中;

  • selection,當前編輯器內的主游標;

  • selections,當前編輯器中的所有游標,第一個游標就是主游標,後面的則是使用者創建出來的多游標;

  • setDecorations,設定編輯器裝飾器(我會在後面的章節專門介紹這個 API 的使用)。

image.png

前往微醫網際網路醫院線上診療平臺,快速問診,3分鐘為你找到三甲醫生。(https://wy.guahao.com/?channel=influence)