<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【實(shí)戰(zhàn)入門】你不知道的 VSCode 插件開發(fā)教程

          共 10167字,需瀏覽 21分鐘

           ·

          2020-10-28 22:21


          原本鏈接:https://hellogithub2014.github.io/2019/06/09/vscode-plugin-development/

          之前一直以為開發(fā)VS code插件是一件很難的事情,后來(lái)工作上需要搞一個(gè)效率小工具,就試著找了些資料來(lái)入門,發(fā)現(xiàn)其實(shí)就入門和開發(fā)一些簡(jiǎn)單功能的插件來(lái)說難度還是很低的。因?yàn)関scode本身是基于electron開發(fā)的,所以總體來(lái)說開發(fā)插件就是在寫node代碼,額外再加一些編輯器api,插件發(fā)布的過程和npm包的發(fā)布很類似。

          vscode官方提供的腳手架還幫忙加上了調(diào)試配置,調(diào)試非常方便。下面就來(lái)說下具體步驟,在學(xué)習(xí)的過程中參考了一些博客,放在了最后面。

          環(huán)境準(zhǔn)備

          這個(gè)很簡(jiǎn)單,我就直接拷貝過來(lái)了。

          • nodejs: 建議使用 LTS 版本
          • npm: 建議最新版本
          • yeoman : npm install -g yo
          • generator-code : npm install -g generator-code

          另外小TIPS,我們平時(shí)直接安裝的插件所在目錄是~/.vscode/extensions,有興趣的可以看看這些插件是怎么實(shí)現(xiàn)的。

          腳手架

          安裝的yo可以直接生成一個(gè)Hello World版本的插件目錄。執(zhí)行

          yo?code

          即會(huì)提示一些問題,按照個(gè)人喜好填寫即可,最后會(huì)生成樣板代碼:

          .
          ├──?CHANGELOG.md?????????????????插件變更記錄
          ├──?README.md
          ├──?extension.js?????????????????插件入口main文件
          ├──?jsconfig.json????????????????編輯器關(guān)于js的配置
          ├──?package.json?????????????????全局配置
          ├──?test?????????????????????????測(cè)試代碼文件夾
          │???├──?extension.test.js
          │???└──?index.js
          ├──?vsc-extension-quickstart.md??新手介紹
          └──?yarn.lock

          其中的quickstart.md是新手引導(dǎo),里面包含了對(duì)文件的作用解析、如何運(yùn)行插件、測(cè)試插等等,推薦去看一看,我們?cè)谙旅嬉矔?huì)介紹一些。除此之外在package.json里也包含了很多非常重要的信息:

          {
          ??"name":?"hello-world",?//?插件名
          ??"displayName":?"hello-world",
          ??"description":?"hello?world",?//?插件描述
          ??"version":?"0.0.1",
          ??"engines":?{
          ????"vscode":?"^1.35.0"?//?運(yùn)行插件需要vscode最低版本
          ??},
          ??"categories":?["Other"],
          ??"activationEvents":?["onCommand:extension.helloWorld"],?//?如何激活插件:在命令面板(Command+Shift+P吊起)輸入helloWorld.?注意command名需要在contributes.commands中有配置
          ??"main":?"./extension.js",?//?插件入口
          ??"contributes":?{
          ????"commands":?[
          ??????//?此數(shù)組表示插件支持的所有命令
          ??????{
          ????????"command":?"extension.helloWorld",?//?命令對(duì)應(yīng)的Command,需要和代碼里保持一致
          ????????"title":?"Hello?World"?//?命令的顯示名稱
          ??????}
          ????]
          ??},
          ??"scripts":?{
          ????//?正常的npm?script
          ????"postinstall":?"node?./node_modules/vscode/bin/install",
          ????"test":?"node?./node_modules/vscode/bin/test"
          ??},
          ??"devDependencies":?{
          ????//?依賴包
          ????"typescript":?"^3.3.1",
          ????"vscode":?"^1.1.28",
          ????"eslint":?"^5.13.0",
          ????"@types/node":?"^10.12.21",
          ????"@types/mocha":?"^2.2.42"
          ??}
          }

          啟動(dòng)、調(diào)試插件

          啟動(dòng)運(yùn)行

          腳手架生成的其實(shí)就是一個(gè)node應(yīng)用,直接按F5即可運(yùn)行。對(duì)配置感興趣的也可以查看根目錄下的.vscode/launch.json

          跑起來(lái)以后默認(rèn)會(huì)新開一個(gè)vscode窗口,然后會(huì)發(fā)現(xiàn)什么都沒有發(fā)生,這是由插件的啟動(dòng)方式?jīng)Q定的,配置于package.json里的activationEvents項(xiàng)。常用的有:

          • onLanguage?? 在打開特定語(yǔ)言類型的文件后激活
          • onCommand?? ?在執(zhí)行特定命令后激活

          由于我們的插件是配置的onCommand啟動(dòng),并且指定的命令名是Hello World,所以我們?cè)谛麻_的vscode窗口中按下快捷鍵Command+Shift+P后再找到Hello World,選中并執(zhí)行即可。

          最后順利的話,編輯器右下角會(huì)彈出Hello World!。

          如果細(xì)心的話,還會(huì)在源窗口的控制臺(tái)的調(diào)試控制臺(tái)tab 中看到如下輸出:

          Congratulations,?your?extension?"hello-world"?is?now?active!

          這個(gè)就是由插件的真正代碼部分輸出的了。我們接下來(lái)看看extension.js的內(nèi)容:

          //?vscode編輯器api入口
          const?vscode?=?require('vscode');

          /**
          ?*?此生命周期方法在插件激活時(shí)執(zhí)行
          ?*?@param?{vscode.ExtensionContext}?context
          ?*/

          function?activate(context)?{
          ??//?console的各種方法都是輸出在`調(diào)試控制臺(tái)`tab下
          ??console.log('Congratulations,?your?extension?"hello-world"?is?now?active!');

          ??// registerCommand用于注冊(cè)命令并提供具體邏輯,命令名需要和package.json里寫的一致。
          ??//?回調(diào)函數(shù)在命令被觸發(fā)時(shí)執(zhí)行。
          ??let?disposable?=?vscode.commands.registerCommand('extension.helloWorld',?function()?{
          ????//?在編輯器右下角展示一個(gè)message?box
          ????vscode.window.showInformationMessage('Hello?World!');
          ??});

          ??//?將registerCommand的返回值放入subscriptions可以自動(dòng)執(zhí)行內(nèi)存回收邏輯。
          ??context.subscriptions.push(disposable);
          }
          exports.activate?=?activate;

          //?當(dāng)插件被設(shè)置為無(wú)效時(shí)執(zhí)行此生命周期鉤子
          function?deactivate()?{}

          module.exports?=?{
          ??activate,
          ??deactivate,
          };

          以上就是此插件的完整邏輯了,配置注釋是很簡(jiǎn)單的。可以看到主要就是兩個(gè)生命周期函數(shù),另外搭配一些編輯器api就完成了。

          調(diào)試

          腳手架已經(jīng)貼心的幫我們加了調(diào)試配置,我們只用添加斷點(diǎn)即可:

          Command 配置

          上面提到了生成一個(gè)command只需要 2 步,先是利用vscode.commands.registerCommand注冊(cè)一個(gè),然后再到package.json里的contributes.commands中配置即可。圍繞command還可以做一些其他事情,最常見的就是配置右鍵菜單和快捷鍵。

          右鍵菜單

          表示右鍵的菜單里出現(xiàn)指定command,配置方法:

          "contributes":{
          ??"menus":?{
          ????"editor/context":?[
          ??????{
          ????????"when":?"editorHasSelection?&&?resourceFilename?=~?/.js|.vue|.ts/",?//?出現(xiàn)時(shí)機(jī),當(dāng)編輯器中有選中文本同時(shí)文件名后綴是js/vue/ts
          ????????"command":?"extension.starling_textSearch",?//?需要在`contributes.commands`存在此命令
          ????????"group":?"6_Starling"?//?命令所在的組,右鍵菜單可以分組,組與組之間存在分隔線
          ??????},
          ????]
          ??}
          }

          快捷鍵

          有了快捷鍵后,就不用每次在命令面板里查找并運(yùn)行命令了,同樣是在package.json中配置:

          "contributes":?{
          ??"keybindings":?[
          ????{
          ??????"command":?"extension.starling_textSearch",
          ??????"key":?"ctrl+f11",?//?在Windows上的快捷鍵
          ??????"mac":?"cmd+f11",?//?在mac上的快捷鍵
          ??????"when":?"editorTextFocus"?//?出現(xiàn)時(shí)機(jī),?當(dāng)編輯器焦點(diǎn)在某個(gè)文本中
          ????}
          ??],
          }

          發(fā)布

          主要參考的是官方文檔

          首先需要安裝vsce工具:

          npm?install?-g?vsce

          本地打包將插件打包成.vsix文件。

          vsce?package

          會(huì)在項(xiàng)目根目錄生成hello-world-0.0.1.vsix,然后在編輯器的插件面板選擇從VSIX安裝即可:

          發(fā)布到插件市場(chǎng)

          • 需要獲取一個(gè)token,參考官方文檔
          • 利用token創(chuàng)建一個(gè)publisher,這是在插件市場(chǎng)的用戶
          vsce?create-publisher?(publisher?name)
          • 本地登錄此用戶
          vsce?login?(publisher?name)
          • 發(fā)布插件
          vsce?publish

          順利的話在控制臺(tái)會(huì)提示發(fā)布成功,然后過幾分鐘就可以在插件市場(chǎng)搜到自己的插件啦!?

          版本升級(jí)

          當(dāng)插件內(nèi)容發(fā)生變更時(shí),重新發(fā)布時(shí)最好更新版本號(hào),vsce可以遵循語(yǔ)義化版本指定升級(jí)大(major)/小(minor)/補(bǔ)丁(patch)版本,也可以直接指定版本號(hào)。例如只升級(jí)小版本:

          vsce?publish?minor

          如果插件代碼在gitlab上,因?yàn)閭}(cāng)庫(kù)在內(nèi)網(wǎng),需要事先將README里的圖片替換為公網(wǎng)cdn上的路徑。

          snippets

          snippets是代碼片段,可以理解為代碼快捷鍵,在輸入很少量觸發(fā)代碼后即可聯(lián)想出一大坨關(guān)聯(lián)代碼,非常方便。對(duì)于js、ts、vue都可以在插件市場(chǎng)找到非常多的snippets插件。

          開發(fā)snippets只用兩步:

          • 編寫snippets映射文件,它是一個(gè)json,例如javascript.json:
          {
          ??"this$t":?{
          ????"prefix":?"tt'",?//?觸發(fā)代碼
          ????"body":?[
          ??????//?聯(lián)想出來(lái)的關(guān)聯(lián)代碼
          ??????"this.\\$t('${1:key}')"?//?${1:?key}?是占位符,聯(lián)想出來(lái)后會(huì)自動(dòng)聚焦在這里
          ????],
          ????"description":?"this.$t"?//?snippets描述,當(dāng)有多個(gè)匹配的代碼片段時(shí),可以用來(lái)識(shí)別
          ??}
          }
          • 在package.json中配置
          "contributes":?{
          ??"snippets":?[
          ????{
          ??????"language":?"javascript",?//?代碼片段起作用的語(yǔ)言類型
          ??????"path":?"./src/snippets/javascript.json"?//?對(duì)應(yīng)的映射文件
          ????}
          ??]
          }

          最后就可以在編輯器看到效果了:

          • 更多細(xì)節(jié)參考snippets-syntax

          插件默認(rèn)配置

          很多插件是需要一些額外配置才能工作的,設(shè)置默認(rèn)配置同樣在package.json里:

          "contributes":?{
          ??"configuration":?{?//?默認(rèn)配置
          ????"type":?"object",
          ????"title":?"",
          ????"required":?[
          ??????"sid"
          ????],
          ????"properties":?{
          ??????"includes":?{
          ????????"type":?"Array",
          ????????"default":?[
          ??????????"json"
          ????????],
          ????????"description":?"文件類型過濾器"
          ??????}
          ????}
          ??},
          }

          默認(rèn)配置是json schema格式,在覆蓋默認(rèn)配置時(shí)如果校驗(yàn)出錯(cuò)會(huì)有提示。

          插件中使用getConfiguration來(lái)讀取配置:

          function?getConfig()?{
          ??const?config?=?vscode.workspace.getConfiguration();
          ??const?includes:?string[]?|?undefined?=?config.get('includes');?//?獲取指定配置項(xiàng)

          ??return?{
          ????includes:?includes?||?[],
          ??};
          }

          監(jiān)聽配置項(xiàng)修改

          在用戶安裝了插件后,可能會(huì)修改配置,如何實(shí)時(shí)監(jiān)聽配置項(xiàng)的修改呢?vscode提供了onDidChangeConfiguration事件監(jiān)聽。

          vscode.workspace.onDidChangeConfiguration(function(event)?{
          ??const?configList?=?['includes'];
          ??//?affectsConfiguration:?判斷是否變更了指定配置項(xiàng)
          ??const?affected?=?configList.some(item?=>?event.affectsConfiguration(item));
          ??if?(affected)?{
          ????//?do?some?thing?...
          ??}
          });

          常見編輯器 api

          所有vscode相關(guān)api都可以在官網(wǎng)文檔查找,vscode內(nèi)部也集成了.d.ts文件,編輯器內(nèi)直接跳轉(zhuǎn)定義即可。這里只列舉一些常見的api.

          • messgae

          用于展示提示性消息,出現(xiàn)在編輯器右下角,而不是頂部或右上角。

          和console類似,提供了普通消息、警告消息、錯(cuò)誤消息。

          vscode.window.showInformationMessage('普通消息');
          vscode.window.showWarningMessage('警告消息');
          vscode.window.showErrorMessage('錯(cuò)誤消息');

          消息也支持交互按鈕,當(dāng)選中按鈕時(shí)返回的是按鈕本身:

          vscode.window.showErrorMessage(`與starling的遠(yuǎn)程交互依賴vscode-starling.sid配置項(xiàng)`,?'打開配置項(xiàng)').then(selection?=>?{
          ??if?(selection?===?'打開配置項(xiàng)')?{
          ????vscode.commands.executeCommand('workbench.action.openSettings');
          ??}
          });

          input box

          在編輯器頂部展示一個(gè)input輸入框,使用vscode.window.showInputBox,會(huì)返回一個(gè)Promise:

          const?text:?string?|?undefined?=?await?vscode.window.showInputBox({
          ??'最后一步,輸入文案'
          })

          quick pick

          用于從一組選項(xiàng)中選擇一個(gè),類似于select組件。使用vscode.window.showQuickPick,同樣返回一個(gè)Promise,resolve時(shí)得到被選中的選項(xiàng)或undefined:

          const?lang:?string?|?undefined?=?await?vscode.window.showQuickPick(['en',?'zh',?'ja'],?{
          ??placeHolder:?'第一步:選擇語(yǔ)言',
          });

          每個(gè)選項(xiàng)也可以是對(duì)象類型:

          const?option:?Object?|?undefined?=?await?vscode.window.showQuickPick([{?id:?1,?name:?'a'?},?{?id:?2,?name:?'b'?},?{?id:?3,?name:?'c'?}],?{
          ??placeHolder:?'select?an?option',
          });

          output channel

          在利用Control + ~打開控制臺(tái)后,會(huì)出現(xiàn) 4 個(gè)tab,從左到右依次是問題、輸出、調(diào)試控制臺(tái)、終端。output channel就是用于控制輸出 tab的內(nèi)容,可以往其中追加文本、追加行、清空,可以將其看成一個(gè)簡(jiǎn)單的文件。output channel適用于一次展示大量信息.

          使用vscode.window.createOutputChannel創(chuàng)建output channel實(shí)例,然后就可以操作各種api了。

          const?opc?=?vscode.window.createOutputChannel('textSearch');?//?可以有多個(gè)OutputChannel共存,使用參數(shù)名區(qū)分

          opc.clear();?//?清空
          opc.appendLine('水電費(fèi)');?//?追加一行
          opc.show();?//?打開控制臺(tái)并切換到OutputChannel?tab

          一個(gè)例子:

          file selector

          有些時(shí)候需要操作本地文件系統(tǒng),例如選擇某個(gè)文件、將文件保存到指定位置等。

          • 保存文件到指定位置使用showSaveDialog,它會(huì)打開文件選擇器彈窗,選擇了保存路徑后點(diǎn)擊確定會(huì)返回選中的路徑,如果點(diǎn)擊取消會(huì)返回undefined。
          //?讓用戶手動(dòng)選擇文件的的存儲(chǔ)路徑
          const?uri?=?await?vscode.window.showSaveDialog({
          ??filters:?{
          ????zip:?['zip'],?//?文件類型過濾
          ??},
          });
          if?(!uri)?{
          ??return?false;
          }

          writeFile(uri.fsPath);?//?寫入文件
          • 文件選擇showOpenDialog同樣會(huì)打開文件選擇器彈窗,不過這次是用于選擇文件,如果有選擇文件會(huì)返回選中的文件路徑,反之返回undefined。
          //?showOpenDialog返回的是文件路徑數(shù)組
          const?uris?=?await?window.showOpenDialog({
          ??canSelectFolders:?false,?//?是否可以選擇文件夾
          ??canSelectMany:?false,?//?是否可以選擇多個(gè)文件
          ??filters:?{
          ????json:?['json'],?//?文件類型過濾
          ??},
          });

          if?(!uris?||?!uris.length)?{
          ??return;
          }

          handleFiles(uris);

          hover

          有時(shí)候需要在hover到文本上時(shí)展示一些提示信息,例如eslint插件在hover到不合規(guī)的代碼上時(shí)會(huì)展示具體違反了哪些規(guī)則:

          處理hover需要注冊(cè)一個(gè)hover處理器,vscode會(huì)在hover到文本上時(shí)自動(dòng)調(diào)用處理器,同時(shí)傳遞hover相關(guān)的信息。例如一個(gè)展示光標(biāo)所在的單詞hover處理器:

          /**
          ?*?document:?打開的文本
          ?* position:hover的位置
          ?* token:?用于取消hover處理器作用
          ?*/

          async?function?hover(document:?vscode.TextDocument,?position:?vscode.Position,?token:?vscode.CancellationToken)?{
          ??const?line?=?document.lineAt(position).text;?//?光標(biāo)所在的行
          ??// getWordRangeAtPosition獲取光標(biāo)所在單詞的行列號(hào)范圍;getText獲取指定范圍的文本
          ??const?positionWord?=?document.getText(document.getWordRangeAtPosition(position));

          ??console.log('光標(biāo)所在位置的單詞是:',?positionWord);
          }

          //?registerHoverProvider的第一個(gè)參數(shù)數(shù)組表明此處理器的作用范圍
          const?hoverDisposable?=?vscode.languages.registerHoverProvider(['javascript',?'vue'],?{
          ??provideHover:?hover,
          });

          context.subscriptions.push(hoverDisposable);

          selection

          與hover類似,有時(shí)候需要處理選中的文本,獲取它是通過vscode.TextEditor實(shí)例上的屬性,有兩個(gè)相關(guān)屬性

          • selections:所有被選中的文本信息
          • selection:第一個(gè)被選中的文本信息, 等同于selections[0]

          獲取TextEditor的一個(gè)方法是通過注冊(cè)textEditorCommand,會(huì)在回調(diào)函數(shù)里提供TextEditor實(shí)例,例如展示選中文本:

          let?command?=?vscode.commands.registerTextEditorCommand('extension.selection',?function(textEditor,?edit)?{
          ??const?text?=?textEditor.document.getText(textEditor.selection);
          ??console.log('選中的文本是:',?text);
          });

          context.subscriptions.push(command);

          FileSystemWatcher

          用于監(jiān)聽文件是否發(fā)生了變化,可以監(jiān)聽到新建、更新、刪除這 3 種事件,也可以選擇忽略其中某個(gè)類型事件。創(chuàng)建watcher是利用vscode.workspace.createFileSystemWatcher:

          function?createFileSystemWatcher(globPattern:?GlobPattern,?ignoreCreateEvents?:?boolean,?ignoreChangeEvents?:?boolean,?ignoreDeleteEvents?:?boolean):?FileSystemWatcher;

          例如監(jiān)聽所有js文件的變動(dòng):

          const?watcher?=?vscode.workspace.createFileSystemWatcher('*.js',?false,?false,?false);
          watcher.onDidChange(e?=>?{?//?文件發(fā)生更新
          ??console.log('js?changed,'?e.fsPath);
          });
          watcher.onDidCreate(e?=>?{?//?新建了js文件
          ??console.log('js?created,'?e.fsPath);
          });
          watcher.onDidDelete(e?=>?{?//?刪除了js文件
          ??console.log('js?deleted,'?e.fsPath);
          });

          參考文章

          • https://code.visualstudio.com/api
          • VSCode插件開發(fā)全攻略:https://www.cnblogs.com/liuxianan/p/vscode-plugin-overview.html
            VSCode插件開發(fā)急速入門:https://juejin.im/entry/6844903640826642440


          掃碼關(guān)注公眾號(hào),訂閱更多精彩內(nèi)容。



          你點(diǎn)的每個(gè)贊,我都認(rèn)真當(dāng)成了喜歡
          瀏覽 41
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本熟妇一二三区视频 | 天天干天天操天天爽 | 中文字幕日本无码 | 国产黄色小视频在线观看 | 丁香五月天网站 |