为什么';Vims errorformat接受正则表达式吗?

为什么';Vims errorformat接受正则表达式吗?,vim,Vim,Vims errorformat(用于解析编译/构建错误)使用c中的一种神秘格式来解析错误 尝试为nant设置错误格式似乎几乎是不可能的,我已经尝试了很多个小时,但都没有成功。我也从我的搜索中看到很多人似乎也有同样的问题。解决这个问题的正则表达式需要几分钟的时间来编写 那么为什么vim仍然使用这种格式呢?很可能C解析器的速度更快,但这似乎与最多每隔几分钟发生一次的事情无关。这是一个很好的理由还是仅仅是一个历史产物?lol试着找个时间看看实际的vim源代码。这是一个C代码的巢穴,如此古老和晦涩,你

Vims errorformat(用于解析编译/构建错误)使用c中的一种神秘格式来解析错误

尝试为nant设置错误格式似乎几乎是不可能的,我已经尝试了很多个小时,但都没有成功。我也从我的搜索中看到很多人似乎也有同样的问题。解决这个问题的正则表达式需要几分钟的时间来编写


那么为什么vim仍然使用这种格式呢?很可能C解析器的速度更快,但这似乎与最多每隔几分钟发生一次的事情无关。这是一个很好的理由还是仅仅是一个历史产物?

lol试着找个时间看看实际的vim源代码。这是一个C代码的巢穴,如此古老和晦涩,你会认为你在进行考古挖掘

至于vim为什么使用C解析器,有很多很好的理由可以从它的通用性开始。但真正的原因是,在过去20年的某个时候,有人编写它来使用C解析器,并且它可以工作。没有人会改变什么是有效的


如果它对您不起作用,vim社区将告诉您自己编写。愚蠢的开源混蛋。

不是Vim使用了C语言中的一种神秘格式,而是它使用了scanf的思想,这是一个C函数。这意味着与错误消息匹配的字符串由3部分组成:

  • 空白
  • 人物
  • 转换规范
空白是您的制表符和空格。字符是字母、数字和其他普通的东西。转换规范是以“%”(百分比)字符开头的序列。在scanf中,您通常会将输入字符串与%d或%f匹配,以转换为整数或浮点数。使用Vim的错误格式,您可以在输入字符串(错误消息)中搜索文件、行和其他特定于编译器的信息

如果您使用scanf从字符串“99瓶啤酒”中提取整数,那么您将使用:

int i;
scanf("%d bottles of beer", &i); // i would be 99, string read from stdin
现在有了Vim的错误格式,它变得有点棘手,但它确实试图轻松地匹配更复杂的模式。例如多行错误消息、文件名、更改目录等。errorformat帮助中的一个示例非常有用:

1  Error 275
2  line 42
3  column 3
4  ' ' expected after '--'

The appropriate error format string has to look like this:

  :set efm=%EError\ %n,%Cline\ %l,%Ccolumn\ %c,%Z%m
此处%E告诉Vim这是多行错误消息的开始。%n是一个错误号。%C是多行消息的延续,其中%l是行号,%C是列号。%Z标记多行消息的结尾,%m与状态行中显示的错误消息相匹配。你需要用反斜杠来避开空格,这会增加一点额外的怪异

虽然使用正则表达式一开始似乎更容易,但这种迷你语言是专门设计用来帮助匹配编译器错误的。这里有很多捷径。我的意思是,您不必考虑匹配多行、多个数字、匹配路径名(只需使用%f)


另一个想法是:如果只使用普通的regexp,如何将数字映射为行号,或将字符串映射为文件或错误消息?按组位置?这可能行得通,但不会很灵活。另一种方法是命名为capture groups,但无论如何,这种语法看起来很像一种简写。实际上,您可以使用regexp通配符,例如
*
——在这种语言中,它是
%.%#
编写的


好的,所以它不是完美的。但这也不是不可能的,而且有其自身的道理。陷入困境,阅读帮助并停止抱怨!:-)

我建议为您的编译器编写一个后处理过滤器,它使用正则表达式或任何东西,并以一种简单的格式输出消息,这很容易为它编写
errorformat
。为什么要学习一些新的、巴洛克式的、单一用途的语言,除非你必须学习?

根据
:help quickfix

还可以指定(几乎)任何Vim支持的常规 格式字符串中的表达式


然而,文档很混乱,我没有花太多时间来验证它的工作情况和用处。您仍然需要使用类似scanf的代码来提取文件名等。

使用这些代码很麻烦,但需要明确的是:您可以使用正则表达式(大多数情况下)

从文档中:

Pattern matching

The scanf()-like "%*[]" notation is supported for backward-compatibility
with previous versions of Vim.  However, it is also possible to specify
(nearly) any Vim supported regular expression in format strings.
Since meta characters of the regular expression language can be part of
ordinary matching strings or file names (and therefore internally have to
be escaped), meta symbols have to be written with leading '%':
    %\      The single '\' character.  Note that this has to be
            escaped ("%\\") in ":set errorformat=" definitions.
    %.      The single '.' character.
    %#      The single '*'(!) character.
    %^      The single '^' character.  Note that this is not
            useful, the pattern already matches start of line.
    %$      The single '$' character.  Note that this is not
            useful, the pattern already matches end of line.
    %[      The single '[' character for a [] character range.
    %~      The single '~' character.
When using character classes in expressions (see |/\i| for an overview),
terms containing the "\+" quantifier can be written in the scanf() "%*"
notation.  Example: "%\\d%\\+" ("\d\+", "any number") is equivalent to "%*\\d".
Important note: The \(...\) grouping of sub-matches can not be used in format
specifications because it is reserved for internal conversions.

“另一个想法是:如果只使用普通的regexp?按组位置?”,那么如何将数字映射为表示行号的数字,或将字符串映射为表示文件或错误消息的数字?”。好的解释。您必须匹配该行的全部内容吗?或者它会像正则表达式一样在任何地方匹配它吗?我已经在那里对命名的捕获组进行了评论。比赛要求你完全准确。消息中出现的任何您没有想到的额外内容都会导致匹配失败。为了避免这种情况,你可以像在正则表达式中使用一样使用通配符习惯用法
%.%#
。你可能想把它调小一点-如果没有其他的,这将为我们版主节省一点工作-pI在很久以后才解决了这个问题,结果并不是regex符号让我困惑:对于未来的读者:上面评论中提到的文章的固定链接: