我可以将范围信息添加到在<LANG>旺盛的 ctag 中使用"--regex-"生成的标签吗?



从技术上讲,我在vim中使用Tagbar来查看文件的标记,但这个问题通常适用于v5.8中的丰富标记。

假设我有以下python文件,称之为foo.py:

class foo:
    def bar(baz):
        print(baz)

让我们运行ctags: ctags foo.py。生成的tags文件如下所示:

!_ some ctags version / formatting stuff not worth pasting
bar foo.py  /^    def bar(baz):$/;" m   class:foo
foo foo.py  /^class foo:$/;"    c

我感兴趣的位是第二行的最后一个字段class:foo。这就是bar()函数的作用域。如果我在vim中使用标签栏,它会相应地在类中嵌套函数。

现在假设我要在~/.ctags中添加对新语言的支持。实际上,我正在添加对这个puppet文件的支持:

class foo {
    include bar
}

假设我使用以下~/.ctags参数。"import"正则表达式很丑(errr…对于正则表达式来说很丑),但对于这个例子来说它已经足够完成工作了:

--langdef=puppet
--langmap=puppet:.pp
--regex-puppet=/^class[ t]*([:a-zA-Z0-9_-]+)[ t]*/1/c,class,classes/
--regex-puppet=/^    include[ t]*([:a-zA-Z0-9_-]+)/1/i,include,includes/

在我的tags文件中生成以下标记:

bar foo.pp  /^    include bar$/;"   i
foo foo.pp  /^class foo {$/;"   c

注意这两行都不包含作用域信息。我的问题是:我是否可以构造--regex-puppet参数或--regex-<LANG>行来收集有关标记范围的信息?也许声明符合条件A的标签总是符合条件B的标签的作用域父?

man ctags建议没有明确的方法来添加任意范围信息,但我可能忽略了另一个解决方案(为了强调,稍微剪短):

--regex-<LANG>=/regexp/replacement/[kind-spec/][flags]
        Unless modified by flags, regexp is interpreted as a Posix extended regular expression. The replacement should expand for all matching lines  to  a  non-empty  string  of
        characters,  or  a  warning message will be reported. An optional kind specifier for tags matching regexp may follow replacement, which will determine what kind of tag is
        reported in the "kind" extension field (see TAG FILE FORMAT, below). The full form of kind-spec is in the form of a single letter, a comma, a  name  (without  spaces),  a
        comma, a description, followed by a separator, which specify the short and long forms of the kind value and its textual description (displayed using --list-kinds). Either
        the kind name and/or the description may be omitted. If kind-spec is omitted, it defaults to "r,regex". Finally, flags are one or more single-letter characters having the
        following effect upon the interpretation of regexp:
           b   The pattern is interpreted as a Posix basic regular expression.
           e   The pattern is interpreted as a Posix extended regular expression (default).
           i   The regular expression is to be applied in a case-insensitive manner.

不,不幸的是,在标签中支持正则表达式模式是不可能的。让标签生成正确作用域的唯一方法是在c中编写解析器作为额外的模块。如果我有时间,我想添加对更好地处理新语言标签的支持,但到目前为止还没有解决,我也仍然不确定最好的方法。

如果您对标签栏支持最感兴趣,那么还有另一种方法:Tagbar支持任意标签生成程序,只要它们的输出与标签的输出兼容,因此您可以用Python编写一个简单的解析器,并配置Tagbar来使用它。看看:h tagbar-extend(特别是最后一小节"编写您自己的标记生成程序"),如果这是您的选择。

我正在通用标签项目中开发这样的功能:https://github.com/universal-ctags/ctags/pull/562.

不要期望太高;Regex解析器不足以处理复杂的语法。新特性适用于语法简单的语言。)

示例1::

$ cat /tmp/input.foo
class foo:
def bar(baz):
    print(baz)
class goo:
def gar(gaz):
    print(gaz)
$ cat /tmp/foo.ctags
--langdef=foo
    --map-foo=+.foo
    --regex-foo=/^class[[:blank:]]+([[:alpha:]]+):/1/c,class/{scope=set}
    --regex-foo=/^[[:blank:]]+def[[:blank:]]+([[:alpha:]]+).*:/1/d,definition/{scope=ref}
$ ~/var/ctags/ctags --options=/tmp/foo.ctags -o - /tmp/input.foo
bar /tmp/input.foo  /^    def bar(baz):$/;" d   class:foo
foo /tmp/input.foo  /^class foo:$/;"    c
gar /tmp/input.foo  /^    def gar(gaz):$/;" d   class:goo
goo /tmp/input.foo  /^class goo:$/;"    c

示例2::

$ cat /tmp/input.pp
class foo {
include bar
}
$ cat /tmp/pp.ctags
--langdef=pp
    --map-pp=+.pp
    --regex-pp=/^class[[:blank:]]*([[:alnum:]]+)[[[:blank:]]]*{/1/c,class,classes/{scope=push}
    --regex-pp=/^[[:blank:]]*include[[:blank:]]*([[:alnum:]]+).*/1/i,include,includes/{scope=ref}
    --regex-pp=/^[[:blank:]]*}.*//{scope=pop}{exclusive}
$ ~/var/ctags/ctags --options=/tmp/pp.ctags -o - /tmp/input.pp
bar /tmp/input.pp   /^    include bar$/;"   i   class:foo
foo /tmp/input.pp   /^class foo {$/;"   c

最新更新