VSCode插件開發(fā)全攻略之跳轉(zhuǎn)到定義、自動補全、懸停提示功能
跳轉(zhuǎn)到定義
跳轉(zhuǎn)到定義其實很簡單,通過vscode.languages.registerDefinitionProvider
注冊一個provider
,這個provider
如果返回了new vscode.Location()
就表示當(dāng)前光標(biāo)所在單詞支持跳轉(zhuǎn),并且跳轉(zhuǎn)到對應(yīng)location。
為了示例更加有意義,我在這里寫了一個支持package.json
中dependencies
、devDependencies
跳轉(zhuǎn)到對應(yīng)依賴包的例子jump-to-definition.js
(當(dāng)然我們這里只是很簡單的實現(xiàn),沒有考慮特殊情況,直接從node_modules
文件夾下面去找):
代碼如下:
/** * 跳轉(zhuǎn)到定義示例,本示例支持package.json中dependencies、devDependencies跳轉(zhuǎn)到對應(yīng)依賴包。 */ const vscode = require('vscode'); const path = require('path'); const fs = require('fs'); const util = require('./util'); /** * 查找文件定義的provider,匹配到了就return一個location,否則不做處理 * 最終效果是,當(dāng)按住Ctrl鍵時,如果return了一個location,字符串就會變成一個可以點擊的鏈接,否則無任何效果 * @param {*} document * @param {*} position * @param {*} token */ function provideDefinition(document, position, token) { const fileName = document.fileName; const workDir = path.dirname(fileName); const word = document.getText(document.getWordRangeAtPosition(position)); const line = document.lineAt(position); const projectPath = util.getProjectPath(document); console.log('====== 進入 provideDefinition 方法 ======'); console.log('fileName: ' + fileName); // 當(dāng)前文件完整路徑 console.log('workDir: ' + workDir); // 當(dāng)前文件所在目錄 console.log('word: ' + word); // 當(dāng)前光標(biāo)所在單詞 console.log('line: ' + line.text); // 當(dāng)前光標(biāo)所在行 console.log('projectPath: ' + projectPath); // 當(dāng)前工程目錄 // 只處理package.json文件 if (/\/package\.json$/.test(fileName)) { console.log(word, line.text); const json = document.getText(); if (new RegExp(`"(dependencies|devDependencies)":\\s*?\\{[\\s\\S]*?${word.replace(/\//g, '\\/')}[\\s\\S]*?\\}`, 'gm').test(json)) { let destPath = `${workDir}/node_modules/${word.replace(/"/g, '')}/package.json`; if (fs.existsSync(destPath)) { // new vscode.Position(0, 0) 表示跳轉(zhuǎn)到某個文件的第一行第一列 return new vscode.Location(vscode.Uri.file(destPath), new vscode.Position(0, 0)); } } } } module.exports = function(context) { // 注冊如何實現(xiàn)跳轉(zhuǎn)到定義,第一個參數(shù)表示僅對json文件生效 context.subscriptions.push(vscode.languages.registerDefinitionProvider(['json'], { provideDefinition })); };
注意不要忘了修改activationEvents
:
"activationEvents": [ "onLanguage:json" ],
new vscode.Location接收2個參數(shù),第一個是要跳轉(zhuǎn)到文件的路徑,第二個是跳轉(zhuǎn)之后光標(biāo)所在位置,接收Range或者Position對象,Position對象的初始化接收2個參數(shù),行row和列col。
高亮顯示范圍
這里有一個問題我一直沒找到解決方案,如下圖所示:
當(dāng)按住Ctrl跳轉(zhuǎn)的時候,雖然可以控制跳轉(zhuǎn)目標(biāo)位置,但是卻無法控制高亮顯示的范圍,下圖我本應(yīng)該讓page/video/list.html全部變成藍色的,但是默認(rèn)卻只能以單詞為粒度變色,這個問題我找了很久官方文檔就是沒找到解決辦法,如果大家有知道的歡迎評論指出。
自動補全
通過vscode.languages.registerCompletionItemProvider方法注冊自動完成實現(xiàn),接收3個參數(shù):
- 第一個是要關(guān)聯(lián)的文件類型;
- 第二個是一個對象,里面必須包含provideCompletionItems和resolveCompletionItem這2個方法;
- 第三個是一個可選的觸發(fā)提示的字符列表;
這里我們實現(xiàn)這樣一個例子,當(dāng)輸入this.dependencies.xxx時自動把package.json中的依賴全部帶出來,包括dependencies、devDependencies,就像這樣:
實現(xiàn)代碼如下:
const vscode = require('vscode'); const util = require('./util'); /** * 自動提示實現(xiàn),這里模擬一個很簡單的操作 * 當(dāng)輸入 this.dependencies.xxx時自動把package.json中的依賴帶出來 * 當(dāng)然這個例子沒啥實際意義,僅僅是為了演示如何實現(xiàn)功能 * @param {*} document * @param {*} position * @param {*} token * @param {*} context */ function provideCompletionItems(document, position, token, context) { const line = document.lineAt(position); const projectPath = util.getProjectPath(document); // 只截取到光標(biāo)位置為止,防止一些特殊情況 const lineText = line.text.substring(0, position.character); // 簡單匹配,只要當(dāng)前光標(biāo)前的字符串為`this.dependencies.`都自動帶出所有的依賴 if(/(^|=| )\w+\.dependencies\.$/g.test(lineText)) { const json = require(`${projectPath}/package.json`); const dependencies = Object.keys(json.dependencies || {}).concat(Object.keys(json.devDependencies || {})); return dependencies.map(dep => { // vscode.CompletionItemKind 表示提示的類型 return new vscode.CompletionItem(dep, vscode.CompletionItemKind.Field); }) } } /** * 光標(biāo)選中當(dāng)前自動補全item時觸發(fā)動作,一般情況下無需處理 * @param {*} item * @param {*} token */ function resolveCompletionItem(item, token) { return null; } module.exports = function(context) { // 注冊代碼建議提示,只有當(dāng)按下“.”時才觸發(fā) context.subscriptions.push(vscode.languages.registerCompletionItemProvider('javascript', { provideCompletionItems, resolveCompletionItem }, '.')); };
懸停提示
從上面的跳轉(zhuǎn)到定義我們可以看到,雖然我們只是定義了如何調(diào)整,到按住Ctrl鍵但是不點擊的時候,vscode默認(rèn)就會幫我們預(yù)覽一部分內(nèi)容作為提示,除此之外,如果想獲得更多的提示,我們還可以通過vscode.languages.registerHoverProvider命令來實現(xiàn)。
下面我們依然通過package.json中依賴跳轉(zhuǎn)的例子來演示如何實現(xiàn)一個自定義hover,如下標(biāo)紅的內(nèi)容是我們自己實現(xiàn)的,當(dāng)鼠標(biāo)停在package.json的dependencies或者devDependencies時,自動顯示對應(yīng)包的名稱、版本號和許可協(xié)議:
如何實現(xiàn)的呢?也很簡單,我們直接上代碼:
const vscode = require('vscode'); const path = require('path'); const fs = require('fs'); /** * 鼠標(biāo)懸停提示,當(dāng)鼠標(biāo)停在package.json的dependencies或者devDependencies時, * 自動顯示對應(yīng)包的名稱、版本號和許可協(xié)議 * @param {*} document * @param {*} position * @param {*} token */ function provideHover(document, position, token) { const fileName = document.fileName; const workDir = path.dirname(fileName); const word = document.getText(document.getWordRangeAtPosition(position)); if (/\/package\.json$/.test(fileName)) { console.log('進入provideHover方法'); const json = document.getText(); if (new RegExp(`"(dependencies|devDependencies)":\\s*?\\{[\\s\\S]*?${word.replace(/\//g, '\\/')}[\\s\\S]*?\\}`, 'gm').test(json)) { let destPath = `${workDir}/node_modules/${word.replace(/"/g, '')}/package.json`; if (fs.existsSync(destPath)) { const content = require(destPath); console.log('hover已生效'); // hover內(nèi)容支持markdown語法 return new vscode.Hover(`* **名稱**:${content.name}\n* **版本**:${content.version}\n* **許可協(xié)議**:${content.license}`); } } } } module.exports = function(context) { // 注冊鼠標(biāo)懸停提示 context.subscriptions.push(vscode.languages.registerHoverProvider('json', { provideHover })); };
有些時候某個字段可能本身已經(jīng)有提示內(nèi)容了,如果我們?nèi)匀唤o它注冊了hover的實現(xiàn)的話,那么vscode會自動將多個hover內(nèi)容合并一起顯示。
總結(jié)
到此這篇關(guān)于VSCode插件開發(fā)全攻略之跳轉(zhuǎn)到定義、自動補全、懸停提示功能的文章就介紹到這了,更多相關(guān)VSCode插件開發(fā) 跳轉(zhuǎn)到定義、自動補全、懸停提示內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
??C++11系列學(xué)習(xí)之Lambda表達式
這篇文章主要介紹了??C++11系列學(xué)習(xí)之Lambda表達式,C++11終于也引入了lambda表達式,lambda最早來源于函數(shù)式編程,現(xiàn)代語言慢慢都引入了這個語法,下文關(guān)于??C++11Lambda表達式相關(guān)內(nèi)容需要的小伙伴可以參考一下2022-04-04VC判斷進程是否具有administrator權(quán)限的方法
這篇文章主要介紹了VC判斷進程是否具有administrator權(quán)限的方法,在Windows應(yīng)用程序設(shè)計中具有一定的實用價值,需要的朋友可以參考下2014-10-10C語言連續(xù)生成隨機數(shù)的實現(xiàn)方法
這篇文章主要介紹了C語言連續(xù)生成隨機數(shù)的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01