VSCode插件开发全攻略(五)跳转到定义、自动补全、悬停提示
更多文章请戳VSCode插件开发全攻略系列目录导航。
跳转到定义
跳转到定义其实很简单,通过vscode.languages.registerDefinitionProvider
注册一个provider
,这个provider
如果返回了new vscode.Location()
就表示当前光标所在单词支持跳转,并且跳转到对应location。
为了示例更加有意义,我在这里写了一个支持package.json
中dependencies
、devDependencies
跳转到对应依赖包的例子jump-to-definition.js
(当然我们这里只是很简单的实现,没有考虑特殊情况,直接从node_modules
文件夹下面去找):
代码如下:
/**
* 跳转到定义示例,本示例支持package.json中dependencies、devDependencies跳转到对应依赖包。
*/
const vscode = require('vscode');
const path = require('path');
const fs = require('fs');
const util = require('./util');
/**
* 查找文件定义的provider,匹配到了就return一个location,否则不做处理
* 最终效果是,当按住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); // 当前文件完整路径
console.log('workDir: ' + workDir); // 当前文件所在目录
console.log('word: ' + word); // 当前光标所在单词
console.log('line: ' + line.text); // 当前光标所在行
console.log('projectPath: ' + projectPath); // 当前工程目录
// 只处理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) 表示跳转到某个文件的第一行第一列
return new vscode.Location(vscode.Uri.file(destPath), new vscode.Position(0, 0));
}
}
}
}
module.exports = function(context) {
// 注册如何实现跳转到定义,第一个参数表示仅对json文件生效
context.subscriptions.push(vscode.languages.registerDefinitionProvider(['json'], {
provideDefinition
}));
};
注意不要忘了修改activationEvents
:
"activationEvents": [
"onLanguage:json"
],
new vscode.Location
接收2个参数,第一个是要跳转到文件的路径,第二个是跳转之后光标所在位置,接收Range
或者Position
对象,Position
对象的初始化接收2个参数,行row
和列col
。
高亮显示范围
这里有一个问题我一直没找到解决方案,如下图所示:
当按住Ctrl
跳转的时候,虽然可以控制跳转目标位置,但是却无法控制高亮显示的范围,下图我本应该让page/video/list.html
全部变成蓝色的,但是默认却只能以单词为粒度变色,这个问题我找了很久官方文档就是没找到解决办法,如果大家有知道的欢迎评论指出。
自动补全
通过vscode.languages.registerCompletionItemProvider
方法注册自动完成实现,接收3个参数:
- 第一个是要关联的文件类型;
- 第二个是一个对象,里面必须包含
provideCompletionItems
和resolveCompletionItem
这2个方法; - 第三个是一个可选的触发提示的字符列表;
这里我们实现这样一个例子,当输入this.dependencies.xxx
时自动把package.json
中的依赖全部带出来,包括dependencies
、devDependencies
,就像这样:
实现代码如下:
const vscode = require('vscode');
const util = require('./util');
/**
* 自动提示实现,这里模拟一个很简单的操作
* 当输入 this.dependencies.xxx时自动把package.json中的依赖带出来
* 当然这个例子没啥实际意义,仅仅是为了演示如何实现功能
* @param {*} document
* @param {*} position
* @param {*} token
* @param {*} context
*/
function provideCompletionItems(document, position, token, context) {
const line = document.lineAt(position);
const projectPath = util.getProjectPath(document);
// 只截取到光标位置为止,防止一些特殊情况
const lineText = line.text.substring(0, position.character);
// 简单匹配,只要当前光标前的字符串为`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);
})
}
}
/**
* 光标选中当前自动补全item时触发动作,一般情况下无需处理
* @param {*} item
* @param {*} token
*/
function resolveCompletionItem(item, token) {
return null;
}
module.exports = function(context) {
// 注册代码建议提示,只有当按下“.”时才触发
context.subscriptions.push(vscode.languages.registerCompletionItemProvider('javascript', {
provideCompletionItems,
resolveCompletionItem
}, '.'));
};
悬停提示
从上面的跳转到定义我们可以看到,虽然我们只是定义了如何调整,到按住Ctrl键但是不点击的时候,vscode默认就会帮我们预览一部分内容作为提示,除此之外,如果想获得更多的提示,我们还可以通过vscode.languages.registerHoverProvider
命令来实现。
下面我们依然通过package.json中依赖跳转的例子来演示如何实现一个自定义hover,如下标红的内容是我们自己实现的,当鼠标停在package.json的dependencies
或者devDependencies
时,自动显示对应包的名称、版本号和许可协议:
如何实现的呢?也很简单,我们直接上代码:
const vscode = require('vscode');
const path = require('path');
const fs = require('fs');
/**
* 鼠标悬停提示,当鼠标停在package.json的dependencies或者devDependencies时,
* 自动显示对应包的名称、版本号和许可协议
* @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内容支持markdown语法
return new vscode.Hover(`* **名称**:${content.name}\n* **版本**:${content.version}\n* **许可协议**:${content.license}`);
}
}
}
}
module.exports = function(context) {
// 注册鼠标悬停提示
context.subscriptions.push(vscode.languages.registerHoverProvider('json', {
provideHover
}));
};
有些时候某个字段可能本身已经有提示内容了,如果我们仍然给它注册了hover的实现的话,那么vscode会自动将多个hover内容合并一起显示。
VSCode插件开发全攻略(五)跳转到定义、自动补全、悬停提示的更多相关文章
- Visual Studio Code 中实现 C++ 函数定义跳转和代码自动补全功能(25)
方法1: 1.1 安装插件 C++ Intellisense 名称: C++ Intellisense id: austin.code-gnu-global 说明: C/C++ Intellisens ...
- 裸眼3D全攻略3:拍摄3D—瞳距、镜距、视角偏转与空间感
http://sd89.blog.163.com/blog/static/356041322014112532958728/ 3D图片的拍摄,与平面有着全新的不同要求,那就是空间感的表现. 简单来说, ...
- ES系列十三、Elasticsearch Suggester API(自动补全)
1.概念 1.补全api主要分为四类 Term Suggester(纠错补全,输入错误的情况下补全正确的单词) Phrase Suggester(自动补全短语,输入一个单词补全整个短语) Comple ...
- 第一百八十一节,jQuery-UI,知问前端--自动补全 UI--邮箱自动补全
jQuery-UI,知问前端--自动补全 UI--邮箱自动补全 学习要点: 1.调用 autocomplete()方法 2.修改 autocomplete()样式 3.autocomplete()方法 ...
- eclipse自动补全的设置
eclipse自动补全的设置 如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的 ...
- Eclipse自动补全设置
如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的自动补全没有VS那么好是因为ecl ...
- eclipse自动补全的设置(自动提示)
如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的自动补全没有VS那么好是因为e ...
- emacs: 文本输入中文件目录自动补全
emacs: 文本输入中文件目录自动补全 // */ // ]]> UP | HOME emacs: 文本输入中文件目录自动补全 Table of Contents 1 引言 2 补全过程演 ...
- vim自动补全插件YouCompleteMe
前言 Valloric/YouCompleteMe可以说是vim安装最复杂的插件之一,但是一旦装好,却又是非常好用的.YouCompleteMe简称ycm 在安装折腾的过程中,我再一次的体会到,除了官 ...
- Qt Style Sheet实践(四):行文本编辑框QLineEdit及自动补全
导读 行文本输入框在用于界面的文本输入,在WEB登录表单中应用广泛.一般行文本编辑框可定制性较高,既可以当作密码输入框,又可以作为文本过滤器.QLineEdit本身使用方法也很简单,无需过多的设置就能 ...
随机推荐
- 对webdriver-driver句柄的理解
先贴代码: from selenium import webdriver //首先导入selenium(webdriver)相关模块 driver = webdriver.Firefox() ...
- 笔记之monkey自定义脚本
自定义脚本的稳定性测试 常规MOnkey测试执行的是随机的事件流,但如果只是想让Monkey测试某个特定场景者时候就需要用到自定义脚本,Monkey支持执行用户自定义脚本的测试,用户之需要按照Monk ...
- nginx新增tcp模板
最近在装nginx时,发现新增了tcp模板,装了一遍,现记录下来过程. 1.下载nginx源码包,并解压 2.下载tcp模板压缩包https://github.com/yaoweibin/nginx_ ...
- 13. Redis监控运维云平台CacheCloud
13. Redis监控运维云平台CacheCloud13.1 CacheCloud是什么13.1.1 现有问题13.1.2 CacheCloud基本功能13.2 快速部署13.2.1 CacheClo ...
- EasyPR源码剖析(3):车牌定位之颜色定位
一.简介 对车牌颜色进行识别,可能大部分人首先想到的是RGB模型, 但是此处RGB模型有一定的局限性,譬如蓝色,其值是255,还需要另外两个分量都为0,不然很有可能你得到的值是白色.黄色更麻烦,它是由 ...
- linux中du与df的区别和联系
1,两者区别 du,disk usage,是通过搜索文件来计算每个文件的大小然后累加,du能看到的文件只是一些当前存在 的,没有被删除的.他计算的大小就是当前他认为存在的所有文件大小的累加和. df, ...
- git 提交代码操作
1.修改1分支后 git add git commint2.切换到本地分支git checkout local-5.0git remote update 更新远程仓库3.git pull origin ...
- hbase_存储模型
Hbase 是按列存储,所以每个列族存储在一个HDFS文件上. Hbase表中的行是按照rowkey字典序进行排列的,并且表格在行的方向上被分割为多个region(按照行进行分割的) region 是 ...
- 推荐一款Notepad++主题Dracula
https://draculatheme.com/notepad-plus-plus/ Activating theme Go to %AppData%\Notepad++\themes Place ...
- 利用WMITool解决Windows10 浏览器主页被hao123劫持问题
利用Windows10 激活工具KMS10_1025激活系统之后会出现首页 被劫持的问题 解决办法如下 1.下载wmi tool 连接地址 链接: https://pan.baidu.com/s/1g ...