vscode插件开发记录
需求
对.up文件解析,根据里面的中文指令:判断、循环指令,实现虚拟缩进显示。
环境搭建
1、安装node.js和vscode
2、安装Yeoman和vscode扩展生成器
npm install -g yo generator-code
3、创建新项目
yo code
按照提示创建项目框架。
技术解析
配置类型 vscode.WorkspaceConfiguration
注入一个配置类,可以根据配置文件来执行不同的策略(也算是一种策略模式)
constructor(){this.config = vscode.workspace.getConfiguration('upLanguage');this.updateDecorationStyles();}
getConfiguration(‘upLanguage’)是从package.json中获取配置
"contributes": {"configuration":{"title": "RCX UP Language","properties": {"upLanguage.indentGuideColors":{"type":"array","default": ["#ff6b6b30", "#4ecdc430", "#45b7d130", "#96ceb430", "#feca5730"],"description": "虚拟缩进参考线的颜色(按层级循环使用)"},"upLanguage.indentWidth":{"type":"number","default": 4,"description": "虚拟缩进的宽度(空格数)"}}}
这里获取到的就是配置indentGuideColors和indentWidth。vscode规定了配置的内容,有类型、默认值和描述。这里使用了贡献点模式,vscode作为宿主,提供了一种配置规范,插件则向vscode贡献自己的配置。
const colors = this.config.get<string[]>('indentGuideColors') || ['#ff6b6b30', '#4ecdc430', '#45b7d130', '#96ceb430', '#feca5730'];
this.indentWidth = this.config.get<number>('indentWidth') || 2;
配置获取代码如上所示,| | 提供默认值,当没有这个配置的时候使用默认值,增强了代码的健壮性。
this.decorationTypes = colors.map((color, index) => vscode.window.createTextEditorDecorationType({});
这里的map是数组的方法,遍历一个数组,返回一个新的数组。这里遍历颜色数组,创建一个有不同颜色的装饰器类型数组。不是数据类型Map。
装饰类型 vscode.TextEditorDecorationType
装饰器提供一个样式模板,规定了一个视觉规则。可以在指定的位置显示想要的样式。在这个项目中,就是利用装饰器来显示缩进,从而不干涉源文件。
createTextEditorDecorationType是返回一个装饰器的样式模板,DecorationType负责样式,而DecorationOption负责指定样式的位置。
const line = editor.document.lineAt(lineIndex);
// 装饰范围依然是行首的一个零宽度范围
const range = new vscode.Range(new vscode.Position(lineIndex, 0),new vscode.Position(lineIndex, 0));
// 为每个层级添加装饰
for (let i = 0; i < Math.min(level, this.decorationTypes.length); i++) {const decoration: vscode.DecorationOptions = {range: range,};decorations[i].push(decoration);
}
创建decorationOption,指定一个位置range。
editor.setDecorations(decorationType, decorations[index]);
再将decorationType和decorationOptions设置给editor。
核心思路就是创建缩进样式,指定显示位置,设置给editor。
export function activate(context: vscode.ExtensionContext) {console.log('UP Language Support 扩展已激活');const indentProvider = new UpIndentGuideProvider();// 监听活动编辑器变化let activeEditor = vscode.window.activeTextEditor;if (activeEditor && activeEditor.document.languageId === 'up') {indentProvider.updateIndentGuides(activeEditor);}// 事件订阅const subscriptions: vscode.Disposable[] = [// 编辑器切换事件vscode.window.onDidChangeActiveTextEditor(editor => {activeEditor = editor;if (editor && editor.document.languageId === 'up') {indentProvider.updateIndentGuides(editor);}}),// 文档内容变化事件(防抖处理)vscode.workspace.onDidChangeTextDocument(event => {if (activeEditor && event.document === activeEditor.document && event.document.languageId === 'up') {// 防抖:延迟100ms更新,避免频繁计算setTimeout(() => {indentProvider.updateIndentGuides(activeEditor!);}, 100);}}),// 配置变化事件vscode.workspace.onDidChangeConfiguration(event => {if (event.affectsConfiguration('upLanguage')) {indentProvider.onConfigChange();}}),// 注册命令:手动刷新缩进显示vscode.commands.registerCommand('upLanguage.refreshIndent', () => {const editor = vscode.window.activeTextEditor;if (editor && editor.document.languageId === 'up') {indentProvider.updateIndentGuides(editor);vscode.window.showInformationMessage('UP语言缩进显示已刷新');}})];// 注册所有订阅subscriptions.forEach(disposable => context.subscriptions.push(disposable));// 注册缩进提供器的清理方法context.subscriptions.push({dispose: () => indentProvider.dispose()});
}
在activate里注册一些事件回调,以及清理方法。
源码链接
仅作参考,代码大部分由ai生成,目前还存在bug。
