如何为 Helix 编写 tags.scm 查询实现文档与工作区符号选择器
2026/9/11 15:08:59 网站建设 项目流程

如何为 Helix 编写 tags.scm 查询实现文档与工作区符号选择器

【免费下载链接】helixA post-modern modal text editor.项目地址: https://gitcode.com/GitHub_Trending/he/helix

Helix 对没有语言服务器(LSP)配合的语言,可以基于 tree-sitter 语法树提供 LSP 式的文档符号和工作区符号选择器,前提是你要为该语言编写一个tags.scm查询文件。这篇文章的任务就是:为一个已有 tree-sitter grammar 的语言写出tags.scm,让 Helix 的Space-s(文档符号)和Space-S(工作区符号)选择器能列出该语言的函数、类、模块等符号及它们的引用位置。

前置条件:该语言已经有可用的 tree-sitter grammar,并在 Helix 中配置了 grammar(即languages.toml中有对应的[[grammar]]条目)。

查询文件放在哪里

按 tags 指南 的说明,文件位置分两种情况:

  • 正式向 Helix 贡献时,放在runtime/queries/{language}/tags.scm(其中{language}是语言名,与languages.toml中的name一致),例如仓库自带的 Picat 示例 就位于runtime/queries/picat/tags.scm
  • 本地测试阶段,可以把查询文件放到本机的 runtime 目录,文档以 Linux 为例:~/.config/helix/runtime

tags.scm是 查询文件列表 中可选的文件之一(只有highlights.scm是必需的),其用途一栏写的是 "document/workspace symbol pickers"。如果你在开发中使用自己维护的runtime目录,按 语言添加指南 的常见问题一节,需要把环境变量HELIX_RUNTIME指向该runtime目录,否则 Helix 可能找不到你的查询。

编写 @definition.* 捕获:定义符号

tags.scm的核心工作是把语法树中"有意义的节点"打上捕获。第一类捕获是@definition.*,标记一个符号的定义位置。文档符号选择器只识别以下捕获名,列表外的捕获名会被忽略:

捕获名
definition.class
definition.constant
definition.enum
definition.field
definition.function
definition.interface
definition.macro
definition.module
definition.section
definition.struct
definition.type

因此规则是:语言特有的构造应映射到上表中最接近的种类,而不是自创新捕获名。

写规则时遵守两个约定:

  1. @definition.*捕获整个定义节点;
  2. 同一个匹配中再用@name捕获该定义内部的名字标识符节点。

文档给出的示例(以function_definition/class_definition节点为例):

(function_definition name: (identifier) @name) @definition.function (class_definition name: (identifier) @name) @definition.class

对照仓库中真实的 Picat 查询,可以看到一个更完整的定义模式:多个构造(function_definitionpredicate_definitionactor_definition)通过[...]列表归入同一个@definition.function捕获,并用name: (_) @name捕获名字节点;文件末尾还有(module_declaration (_) @name) @definition.module这样的模块定义。

编写 @reference.* 捕获:引用位置

第二类捕获标记调用点或类型引用,供工作区符号搜索定位用途(usages)。常见变体是@reference.call(函数调用)和@reference.class(类引用),同样用@name捕获标识符:

(call function: (identifier) @name) @reference.call

Picat 示例中的对应写法是(function_call function: (_) @name @reference.call)

验证查询是否可用

查询写好后,有两层验证:

  1. 编译期检查:在 Helix 源码仓库中运行

    cargo xtask query-check [language]

    [language]替换为你的语言名。该命令校验查询文件能否针对对应 grammar 编译通过——语言添加指南 要求所有查询文件都能通过这一检查。

  2. 效果检查:用 Helix 打开该语言的文件,按Space-s打开文档符号选择器、Space-S打开工作区符号选择器(见 键位表 中 space 模式条目,两者都标注为LSPorTS,即语言服务器不可用时回退到 tree-sitter 的tags.scm)。如果选择器里列出了你在查询中标记的定义与引用,说明查询生效。

另外,如果你在切换分支或新增 grammar 后运行 Helix 出现错误,按同一指南的常见问题一节执行hx --grammar fetch拉取 grammar、hx --grammar build重建过期 grammar。

限制

  • 只有@definition.*列表中列出的捕获名会被符号选择器识别,其余捕获名一律忽略。
  • tags.scm本身不决定符号选择器的按键与过滤行为;选择器文档 说明工作区符号选择器会把搜索词直接传给语言服务器,而基于语法的符号路径(TS 回退)由本文的查询决定内容。

下一步如果你需要为该语言补齐高亮或嵌入语法,可继续参考 查询文件对照表 中的highlights.scminjections.scm等条目,并同样用cargo xtask query-check [language]校验。

【免费下载链接】helixA post-modern modal text editor.项目地址: https://gitcode.com/GitHub_Trending/he/helix

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询