# 前言
背景:项目中预定义了主题样式,在代码编写过程中用到颜色的地方只使用相关变量,然鹅在使用变量时往往记不住各个主题值表示什么颜色,需要反复查阅文档,故希望在coding时能知道当前变量表示的颜色。且支持多套映射,以支持主题切换(如:text_color
默认主题下#333
,dark
主题下#d9d9d9
)。
考虑自定义主题值的场景还挺常见,参考项目中使用的插件Color Highlight
,最终敲定将插件形式做成高亮自定义字符。
好记性不如烂笔头✏️,写文章记录一下插件开发中用到的知识点。
ps:关于插件项目的初始化、package.json各个配置的作用等,已经很多其他优秀文章介绍过了,可查阅文末的附录参考文献,此处便一笔带过了,本文只介绍实现目标功能用到的核心API
# 插件演示&功能介绍
先看下最终实现的效果,插件支持
- 高亮自定义字符
- 主题切换
- 鼠标悬浮到主题变量时显示真实色值
按规则配置完成后,编辑器会以指定颜色高亮目标字符
点击右下角切换预定义的主题
鼠标悬浮到主题变量时显示真实色值
# 下载安装
应用商店搜索:Highlight My Word ☘️
# 核心功能API
# 初始化工程
安装脚手架
npm install -g yo generator-code
初始化工程
yo code
? What type of extension do you want to create? New Extension (TypeScript)
? What's the name of your extension? highlight-my-word-api-demo
? What's the identifier of your extension? highlight-my-word-api-demo
? What's the description of your extension? highlight-my-word-api-demo
? Initialize a git repository? Yes
? Bundle the source code with webpack? No
? Which package manager to use? npm
2
3
4
5
6
7
8
9
# 在编辑器目标位置设置样式
下例🌰演示了如何高亮编辑器中的第一个目标字段,多主题多映射的情况可以此类推
import * as vscode from 'vscode';
export const highlightTargetStr = (str = 'primary') => {
// ① 创建装饰器
const decorator = vscode.window.createTextEditorDecorationType({
overviewRulerLane: vscode.OverviewRulerLane.Center,
borderRadius: '2px',
color: '#fff',
backgroundColor: '#3072f6',
});
// ② 获取可见编辑器实例
const visibleTextEditors = vscode.window.visibleTextEditors;
visibleTextEditors.forEach((editor) => {
// 获取文档实例
const { document } = editor;
// ③ 通过文档实例获取目标字符串位置
const startIndex = document.getText().indexOf(str);
const startPos = document.positionAt(startIndex);
const endPos = document.positionAt(startIndex + str.length);
const range = [new vscode.Range(startPos, endPos)];
// ④ 在目标位置设置装饰器
editor.setDecorations(decorator, range);
});
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
相关代码的作用可见注释,最终效果如下:
注意事项:
①中创建的
decorator
对象可存储起来,调用decorator.dispose()
可释放资源,释放后用同一decorator
重新调用④,样式不会再生效想刷新样式作用的范围,通过
editor.setDecorations
第二个参数设置新的range
即可。若仅设置一次,该装饰的样式会一直作用于该区域,即使在中间插入新的文本
故需要根据内容的变化(vscode.workspace.onDidChangeTextDocument
)来更新装饰器作用的range
# 读写配置
package.json
注册
// package.json
{
...
"contributes": {
"configuration": [
{
"title": "%extension-title%",
"properties": {
"highlight-my-word-api-demo.themes": {
"type": "object",
"description": "%configuration-themes%"
}
}
}
]
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
其中%%
包住的变量是在package.nls.json
中定义的
// package.nls.json
{
"extension-title": "highlight my word",
"configuration-themes": "自定义主题",
}
2
3
4
5
6
配置完毕后用户即可在setting.json
中进行配置,通过下列方式在插件中读取配置
loadConfig = () => {
const config = vscode.workspace.getConfiguration('highlight-my-word-api-demo').get('themes', {});
console.log("config", config);
};
2
3
4
5
监听配置变化
// extension.ts
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.workspace.onDidChangeConfiguration((e) => {
console.log(e);
})
);
}
2
3
4
5
6
7
8
代码中更新配置
updateConfig = () => {
vscode.workspace.getConfiguration('highlight-my-word-api-demo').update('themes', { value: '更新后的值' });
};
2
3
4
# 监听编辑器窗口变化
当有窗口新打开时需要着色新开的窗口,onDidChangeVisibleTextEditors
可监听变化后的窗口
// extension.ts
export function activate(context: vscode.ExtensionContext) {
vscode.window.onDidChangeVisibleTextEditors(editors => { console.log(editors.length); }),
);
}
2
3
4
5
6
7
通过前面的api即可实现可配置的自定义高亮内容,不过至此切换主题需要到setting.json
中进行配置,不是很友好。为了体验更愉快,再增加快捷切换的功能,用到了下面的api
# 底部状态栏
export const displayStatusBar = () => {
// 注意保存此对象以更新文案,控制显示与否等
const statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right);
statusBar.text = 'Highlight My Word';
statusBar.tooltip = '点击切换主题';
// 点击响应事件,绑定对应command的标识
statusBar.command = 'highlight-my-word-api-demo.changeTheme';
statusBar.show();
};
2
3
4
5
6
7
8
9
10
点击状态栏可以响应command
, 通过command调用一个快捷选择弹窗即可实现快捷切换主题
# 注册&实现command
packge.json配置
// package.json
{
...
"contributes": {
"commands": [
{
"command": "highlight-my-word-api-demo.changeTheme",
"title": "切换主题(changeTheme)"
}
]
}
}
2
3
4
5
6
7
8
9
10
11
12
注册
// extension.ts
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.commands.registerCommand('highlight-my-word-api-demo.changeTheme', showQuickPick),
);
}
2
3
4
5
6
7
showQuickPick
即下面展示快捷弹窗的方法
# 快捷选择框
const showQuickPick = () => {
vscode.window.showQuickPick([
'主题1',
'主题2',
], {
canPickMany: false,
placeHolder: "选择您的主题"
}).then((res) => {
console.log(res);
});
};
2
3
4
5
6
7
8
9
10
11
注意:即使什么都没选择,promise仍会回调,返回undefined
# 鼠标悬浮效果
下例演示鼠标悬停primary
单词时候悬浮限制指定内容
// extension.ts
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.languages.registerHoverProvider(['javascript', 'typescript'], {
provideHover: (document: vscode.TextDocument, position: vscode.Position, _: vscode.CancellationToken): vscode.ProviderResult<vscode.Hover> => {
// 得到鼠标悬浮处的单词
const word = document.getText(document.getWordRangeAtPosition(position));
if (word === 'primary') {
return new vscode.Hover('悬浮窗');
}
},
})
);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
最终通过上述api实现了最终的VSCode插件效果,关于详细的API用法可上官网 (opens new window)了解, 欢迎应用商店搜索highlight my word体验使用☘️☘️
# 附录
# 参考资源
[1] 小茗同学-vscode插件开发攻略 (opens new window)
[2] Highlighter-vscode (opens new window)
[3] VS官网 (opens new window)
[4] 少年,我把珍藏的这个 VSCode 插件 API 传给你了 (opens new window)
# 项目地址
[1] 本文demo github地址 (opens new window)
[2] 词语高亮插件 github地址 (opens new window)