添加缩进查询
Helix 使用 tree-sitter 来正确缩进新行。这需要一个 tree-sitter 语法和一个 indent.scm
查询文件,该文件放在
runtime/queries/{language}/indents.scm
下。
行的缩进是通过从新行开头的最低节点遍历语法树来计算的。当被查询捕获时,这些节点中的每一个都构成了总缩进(以何种方式取决于捕获的名称)。
请注意,这些添加的缩进从哪里开始很重要。例如,从同一行开始增加多个缩进级别只会使总缩进级别增加 1。
作用域
添加的缩进并不总是应用于整个节点。例如,在大多数情况下,当一个节点应该缩进时,我们实际上只希望缩进除第一行以外的所有内容。
为此,存在几个作用域(如果需要,将来可能会添加更多作用域):
all
:适用于捕获的整个节点。只有当捕获的节点是这行的第一个节点时,这与tail
不同。tail
:适用于捕获节点的第一行以外的所有内容。
每种捕获类型都有一个默认作用域,该作用域在大多数情况下都应该是正确的。当需要不同的作用域时,可以在模式中的任何位置使用 #set!
声明来更改:
(assignment_expression
right: (_) @indent
(#set! "scope" "all"))
捕获类型
@indent
:默认作用域为tail
;缩进级别加 1;同一行多次出现时不叠加。如果同一行上至少捕获一个@indent
和一个@outdent
,则缩进级别根本不会改变。@outdent
:默认作用域为all
;缩进级别减 1,规则与@indent
相同。@extend
:将该节点的范围扩展到行尾,以及缩进超过该节点所在行的行。这对于像 Python 这样的语言很有用,在这种语言中,出于缩进的目的,一些节点(如函数或类)还应该包含紧跟在它们后面的缩进行。@extend.pre-once
:阻止该节点的祖级节点的第一次扩展。例如,在 Python 中,返回表达式总是结束它所在的块。注意,这只会停止下一次@extend
捕获的扩展。如果捕获了多个祖级,则仅阻止最里面的祖级的扩展。所有其他祖级都不受影响(无论最里面的祖先是否实际上已经被扩展)。
谓词
在某些情况下,S-表达式不能准确表达应该匹配什么模式。为此,tree-sitter 程序允许谓词 (predicates) 出现在模式中的任何位置,类似于
#set!
声明的工作方式:
(some_kind
(child_kind) @indent
(#predicate? arg1 arg2 ...)
)
参数的数量取决于使用的谓词。每个参数要么是一个捕获(如 @name
),要么是一个字符串(如 "某个字符串"
)。tree-sitter 支持以下谓词:
#eq?
/#not-eq?
:第一个参数(捕获)必须/不能等于第二个参数(捕获或字符串)。#match?
/#not-match?
:第一个参数(捕获)必须/不能与第二个参数(字符串)中给出的正则表达式匹配。
此外,我们还支持一些用于缩进查询的自定义的谓词:
#not-kind-eq?
:第一个参数(捕获)的类型不能等于第二个参数(字符串)。#same-line?
/#not-same-line?
:两个参数的捕获必须/不能从同一行开始。