尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Eclipse Theia 变量解析器(@theia/variable-resolver)完全指南:自定义变量注入与字符串替换实战

Eclipse Theia 变量解析器(@theia/variable-resolver)完全指南:自定义变量注入与字符串替换实战 IDE代码编辑器开发工具前端桌面应用插件系统后端AI 应用【免费下载链接】theiaEclipse Theia is a cloud desktop IDE framework implemented in TypeScript.项目地址https://gitcode.com/gh_mirrors/th/theia点击查看免费下载theia/variable-resolver是 Eclipse Theia 中负责变量替换机制的扩展允许在任何字符串中通过${variableName}语法引用并解析运行时变量。本指南以 packages/variable-resolver/README.md 为核心结合该包的源码与测试讲解如何贡献自定义变量、如何使用VariableResolverService解析字符串、内置变量清单以及:参数语法与 input 输入变量的进阶用法读完即可在自己的 Theia 扩展中实现可复用的变量注入能力。一、扩展概览变量替换机制是什么theia/variable-resolver是一个仅包含前端browser逻辑的 Theia 扩展其package.json中通过theiaExtensions.frontend声明入口模块为lib/browser/variable-resolver-frontend-module见 packages/variable-resolver/package.json。它解决的核心问题与 IDE 场景高度相关很多配置字符串如任务命令、调试配置、launch 参数需要在运行时插入当前打开的文件名当前光标行号某个环境变量等动态值。该扩展提供统一的${variableName}占位符语法与解析服务把谁来提供值变量贡献者和在哪里替换解析服务解耦变量贡献点Variable Contribution Point任何扩展都可以注册自己的变量供全应用使用变量解析服务Variable Resolver Service给定一段字符串找出所有${...}占位符并逐一替换为实际值内置变量execPath、pathSeparator、env、config、command、input等常用变量已由该扩展预置。从源码结构看包内核心文件分为三组src/common/variable-types.ts 定义公共类型src/browser/variable.ts 定义变量注册核心src/browser/variable-resolver-service.ts 实现解析算法。二、变量贡献点让扩展注册自己的变量2.1 核心接口Variable 与 VariableContribution注册变量的前提是理解两个核心类型定义于 packages/variable-resolver/src/browser/variable.tsVariable一个可解析的变量对象包含name必填变量的唯一名称解析字符串中${name}即引用它description?可选人类可读的描述会显示在变量列表命令中resolve(...)必填把变量解析为字符串值签名是resolve(context?, argument?, configurationSection?, commandIdVariables?, configuration?): MaybePromiseany即它可以同步返回值也可以返回一个 Promise 异步解析。VariableContribution贡献点接口仅含一个方法registerVariables(variables: VariableRegistry): void扩展通过实现它把变量批量注册进注册表。VariableRegistry同文件 variable.ts内部用Mapstring, Variable保存变量提供registerVariable(variable)注册单个变量若同名变量已存在则打印警告并返回Disposable.NULL不覆盖已有变量registerVariables(variables)批量注册返回可注销的Disposable[]getVariable(name)/getVariables()按名称查询或列出全部变量。注册表返回的Disposable可用于在扩展卸载时注销变量体现了 Theia 一贯的可组合、可释放设计。2.2 实战示例贡献${file}与${lineNumber}README 给出了一个完整示例实现EditorVariableContribution贡献两个变量——${file}返回当前编辑器中打开的文件名${lineNumber}返回当前文件中的光标行号injectable() export class EditorVariableContribution implements VariableContribution { constructor( inject(EditorManager) protected readonly editorManager: EditorManager ) { } registerVariables(variables: VariableRegistry): void { variables.registerVariable({ name: file, description: The name of the file opened in the current editor, resolve: () { const currentEditor this.getCurrentEditor(); if (currentEditor) { return currentEditor.uri.displayName; } return undefined; } }); variables.registerVariable({ name: lineNumber, description: The current line number in the current file, resolve: () { const currentEditor this.getCurrentEditor(); if (currentEditor) { return ${currentEditor.cursor.line 1}; } return undefined; } }); } protected getCurrentEditor(): TextEditor | undefined { const currentEditor this.editorManager.currentEditor; if (currentEditor) { return currentEditor.editor; } return undefined; } }需要注意几个关键约定返回值语义一个 Variable 被解析为MaybePromisestring | undefined即可以同步返回也可以async返回 Promise当变量无法解析时返回undefined解析器会保留原样见下文解析算法而不是报错或插入空串。依赖注入类使用injectable()装饰并通过inject(EditorManager)注入所需服务——这是 Theia基于 InversifyJS的标准写法。行号从 1 开始cursor.line是 0 基的示例中1转成用户可见的 1 基行号。2.3 变量注册的装配过程从源码看变量的收集与注册是在前端启动时完成的。src/browser/variable-resolver-frontend-contribution.ts 的onStart()中通过ContributionProviderVariableContribution取到所有实现VariableContribution的类逐个调用registerVariables(this.variableRegistry)。依赖装配定义在 src/browser/variable-resolver-frontend-module.tsVariableRegistry、VariableResolverService以单例绑定并用bindRootContributionProvider(bind, VariableContribution)建立贡献点CommonVariableContribution内置变量提供者也被绑定为该贡献点的实现。因此任何扩展只要在 DI 容器中把自己绑定为VariableContribution其变量就会在应用启动时自动注册。三、使用 VariableResolverService 解析字符串3.1 基本用法注册好变量后就可以通过VariableResolverService把字符串中的占位符替换为实际值。README 给出的服务端调用示例injectable() export class MyService { constructor( inject(VariableResolverService) protected readonly variableResolver: VariableResolverService ) { } async resolve(): Promisevoid { const text cursor is in file ${file} on line ${lineNumber}; const resolved await this.variableResolver.resolve(text); console.log(resolved); } }假设当前打开的是package.json且光标在第 5 行则输出cursor is in file package.json on line 5resolveT(value: T, options?: VariableResolveOptions): PromiseT | undefined是该服务的核心 API见 src/browser/variable-resolver-service.ts。3.2 解析算法与未知变量保留原样规则VariableResolverService使用正则/\$\{(.*?)\}/g匹配字符串中的占位符见 variable-resolver-service.ts解析过程分为两步doResolveString/resolveVariables先遍历字符串找出所有变量名通过Context.resolve(name)逐个触发变量解析并把结果缓存到 Map 中再用String.prototype.replace把每个占位符替换为解析值。关键行为可由 variable-resolver-service.spec.ts 的测试直接验证已注册变量被替换resolve(file: ${file}; line: ${lineNumber})解析为file: package.json; line: 6未知变量原样保留resolve(workspace: ${workspaceRoot}; file: ${file})得到workspace: ${workspaceRoot}; file: package.json——因为workspaceRoot未注册占位符原样输出支持数组resolveArray(value, options)可解析字符串数组中的每个元素该方法自 1.28.0 起标记为 deprecated建议统一使用resolve对象与嵌套结构doResolve对字符串、数组、对象递归处理doResolveObject/doResolveArray因此整个配置对象也可以整体传入解析取消语义当某个变量的 resolve 抛出cancelled()时整个resolve返回undefined测试 variable-resolver-service.spec.ts 验证了该行为且服务永不复用never rejects异常性错误——普通异常会被捕获、记日志并把该变量置为undefined。此外Context会把解析结果中bigint、boolean、number、string类型统一转为字符串后缓存见 variable-resolver-service.ts其他类型如对象、undefined视为无法解析。3.3 变量参数argument语法${name:argument}Context.resolve会先用:拆分变量名name.split(:, 2)见 variable-resolver-service.ts冒号前是变量名冒号后是传给resolve的argument参数。这一机制让同一个变量可以根据参数返回不同值。最典型的例子是内置变量${env:VAR_NAME}与${config:preferenceName}env变量收到环境变量名参数后返回其值config变量收到偏好项名称后返回该偏好值见下文内置变量。3.4 解析选项VariableResolveOptionsresolve的第二个参数options支持以下字段见 variable-resolver-service.ts选项字段类型说明contextURI解析上下文 URI会被传给变量的resolve(context)供变量按资源上下文取值configurationSectionstring用于解析 input 变量时定位配置节如launch对应 VS Code 的 input variablescommandIdVariablesCommandIdVariables变量名到命令 id 的映射见 src/common/variable-types.ts用于${command:...}场景configurationunknown附加配置对象会原样传给变量 resolve 的最后一个参数四、内置变量一览开箱即用的能力该扩展自带一个CommonVariableContributionsrc/browser/common-variable-contribution.ts注册了以下常用变量你的扩展可以直接使用变量参数argument解析结果${execPath}无当前应用的执行文件路径来自EnvVariablesServer.getExecPath()${pathSeparator}无路径分隔符Windows 后端为\其他平台为/基于OS.backend.isWindows${env:NAME}环境变量名指定环境变量的值取不到时返回空字符串${config:prefName}偏好项名称当前资源上下文中该偏好项的值无参数时返回undefined${command:commandId}命令 id执行指定命令并返回其结果若命令返回null则抛出cancelled()此时整体解析返回undefined。还支持通过commandIdVariables做变量名到命令 id 的映射${input:inputId}input 的 id解析为配置中定义的 input 交互输入详见下节这些内置变量与 VS Code 的 variables reference 高度兼容源码注释中明确引用了 VS Code 的相关贡献点与实现对从 VS Code 迁移插件生态的开发者也十分友好。五、进阶input 输入变量promptString / pickString / command${input:id}允许在解析时向用户弹出交互式输入从而把运行时用户输入注入字符串。输入的定义放在配置的inputs数组里支持三种类型类型定义见 src/browser/variable-input.tsJSON Schema 见 src/browser/variable-input-schema.tstype必需字段可选字段行为promptStringid、type、descriptiondefault弹出输入框description作为提示语default为预填值pickStringid、type、description、optionsdefault弹出选择列表options为候选项默认项在列表顶部并标注 Defaultcommandid、type、commandargs执行command指定的命令args作为参数传入以launch配置为例的典型写法对应configurationSection定位{ version: 0.2.0, configurations: [ { type: node, request: launch, name: Launch Program, program: ${input:pickFile} } ], inputs: [ { id: pickFile, type: promptString, description: Enter the path to the entry file, default: src/index.js } ] }从 common-variable-contribution.ts 的实现看input变量会读取configurationSection指定的配置节找到id匹配的 input 定义promptString通过QuickInputService.input弹出输入框pickString通过showQuickPick展示选择列表默认项排最前并带 Default 描述command则直接executeCommand执行命令并返回其结果。六、交互式辅助列出全部已注册变量除了在代码中解析该扩展还提供命令面板辅助功能。VariableResolverFrontendContribution注册了命令variable.list显示名为 Variable: List All见 variable-resolver-frontend-contribution.ts。在命令面板中执行它会弹出快速选择列表展示所有已注册变量格式为${name} 描述选中某个变量后还可以进一步输入该变量的参数argument并立即解析出当前值展示给你实现见 src/browser/variable-quick-open-service.ts。这对调试自己的变量是否注册成功、参数是否生效非常实用。七、扩展自身的测试解析行为的可验证依据theia/variable-resolver自带单元测试 src/browser/variable-resolver-service.spec.ts直接印证了本文前述的解析规则已知变量在文本中被替换file: ${file}; line: ${lineNumber}→file: package.json; line: 6字符串数组中的每个元素都被解析未知变量${workspaceRoot}被原样保留变量 resolve 抛出cancelled()时整个解析返回undefined。测试使用 InversifyJS 容器绑定VariableRegistry、VariableResolverService与 mock 的ILogger再注册file、lineNumber两个模拟变量后执行断言。若你想为本包或依赖该服务的其他包新增变量行为可参照此测试结构快速编写验证用例。八、小结与最佳实践贡献变量实现VariableContribution.registerVariables通过variables.registerVariable({ name, description, resolve })注册并把类绑定为VariableContribution即可自动生效解析字符串注入VariableResolverService调用await resolver.resolve(text)解析选项通过VariableResolveOptionscontext、configurationSection、commandIdVariables、configuration传入善用参数语法${name:argument}让一个变量服务多种取值场景如${env:...}、${config:...}、${command:...}、${input:...}未知变量不报错未注册的变量占位符会原样保留在结果中避免解析失败导致整条配置不可用交互输入用 input需要运行时向用户询问值时优先考虑promptString/pickString/command三类 input 定义排查问题使用命令面板中的 Variable: List Allvariable.list查看已注册变量并实测解析结果。至此你已经掌握了theia/variable-resolver从变量注册、字符串解析到内置变量与 input 输入的完整链路可以立即在自己的 Theia 扩展中落地${...}变量注入能力。赞分享IDE代码编辑器开发工具前端桌面应用插件系统后端AI 应用【免费下载链接】theiaEclipse Theia is a cloud desktop IDE framework implemented in TypeScript.项目地址https://gitcode.com/gh_mirrors/th/theia点击查看免费下载相关推荐Apache APISIX 变量Variable详解内置变量体系与自定义变量注册实战Apache APISIX 变量Variable详解内置变量体系与自定义变量注册实战 Apache APISIX 在继承 NGINX 变量 http://后端微服务云原生Eclipse Theia 工作区搜索扩展 theia/search-in-workspace 实战指南从全文检索到批量替换Eclipse Theia 工作区搜索扩展 theia/search in workspace 实战指南从全文检索到批量替换 theia/search iIDE代码编辑器开发工具前端桌面应用插件系统后端AI 应用Eclipse Theia实战构建自定义IDE应用Eclipse Theia实战构建自定义IDE应用 本文详细介绍了如何使用Eclipse Theia框架构建功能完整的自定义浏览器IDE应用。内容涵盖TheiIDE代码编辑器开发工具前端桌面应用插件系统后端AI 应用上一篇忘记密码不用愁authentik用户自助管理完全指南下一篇2d-extras源码解析深入理解Scriptable Tiles的实现原理创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表