使用开始和结束正则表达式选择一个词

Selecting a word using starting and ending regex

我有这个 .feature 文件,语法使用以下模式着色:

[
    {
        "match": '#(.*)$'
        "name": 'comment.line.gherkin'
    }
    {
        "match": '^\.\.\.(.*)$'
        "name": 'comment.line.gherkin'
    }
    {
        "match": '(^\*\*\*.*?\*\*\*)|((?<=^\|)\s+\*\*\*.*?\*\*\*)'
        "name": 'support.class.gherkin'
    }
    {
        "match": '($\{.*?\})|(@\{.*?\})'
        "name": 'string.single.qoute.gherkin'
    }
    {
        "match": '\s*(Scenario\:|Feature\:|Scenario Outline\:|Background\:|Examples\:)'
        "name": 'keyword.gherkin'
    }
    {
        "match": '\s*(Given|Then|When|And|But)'
        "name": 'support.class.gherkin'
    }
    {
        "match": '(?<=\s|^)(@[A-Za-z0-9_\-]+)'
        "name": 'entity.name.function.decorator.gherkin'
    }
    {
        "begin": '(^[^ \t\*\n\|]+)|((?<=^\|)\s+[^ \t\*\n\|]+)'
        "end": '\s{2}|\t|$|\s+(?=\|)'
        "name": 'keyword.gherkin'
    }
    {
        "match": '\s(\d*)\s'
        "name": 'entity.name.function.decorator.gherkin'
    }
    {
        "match": '(\<\w+\>)'
        "name": 'constant.character.escape.feature'
    }
    {
        "match": "(\s\'.*?[^\']\'\s)"
        "name": 'string.single.qoute.gherkin'
    }
    {
        "match": '(\s\".*?[^\"]\"\s)'
        "name": 'string.double.qoute.gherkin'
    }
    {
        "match": "\[(\'.*?[^\']\')\]"
        "name": 'constant.character.escape.feature'
    }
    {
        "match": '(\[[^]]*\])'
        "name": 'constant.numeric.gherkin'
    }
    {
        "match": '\|\s(.*)\s\|'
        "name": 'constant.numeric.gherkin'
    }
]

问题是,当我尝试使用此语法突出显示(没有完全遵循小黄瓜结构)编写小文件时,正则表达式模式会突出显示 'keyword.gherkin' 下的所有内容,直到找到关键字。 这是困扰我的模式:

      {
          "begin": '(^[^ \t\*\n\|]+)|((?<=^\|)\s+[^ \t\*\n\|]+)'
          "end": '\s{2}|\t|$|\s+(?=\|)'
          "name": 'keyword.gherkin'
      }

如果我删除这些行,它可以满足我的需要,但我会在文件中丢失一些突出显示的文本,例如 |1|2|3| 这并不是真正的解决方案。

举个例子吧。

记住那些正则表达式是不断被评估的。

我开始在文档中输入单词 Feature:,当我输入时,它以红色突出显示。一旦我完成并继续写作,例如 Feature: do something"Feature:" 为红色,其余文本变为标准颜色。 那将是正确的行为。

例如,如果在文档的开头我开始输入 will do something,它会以红色突出显示,但不应该是因为其中没有任何 gherking 关键字。

"name":在模式中所做的是建立语法颜色,因此不相关。

我已经尝试对模式进行多次修改,但都没有成功。

这是一个文件示例:https://regex101.com/r/qU5mY5/3

我是不是定位错了模式?如果没有,谁能给我一些启发?

第一期

不需要的文本在不应该的时候以红色突出显示 (will do something)。

正如您正确指出的那样,问题位于第二部分的第一部分 keyword-regex,具体为:

"begin": '(^[^ \t\*\n\|]+)|...'

它匹配从开始的所有内容,即:

  • 一个space' '
  • 一个选项卡\t
  • 一颗字面的星星*
  • 一个换行符\n
  • 一根烟斗|

因此,如果一行 will do something 开始 ,它将匹配直到正则表达式引擎没有遇到 end-regex: 两个 spaces \s{2} 或制表符 \t 或行尾 $"one or more spaces"通过管道 \s+(?=\|).

第二期

如果要匹配以 |1|2|3| 开头的行,则必须修改 begin-regex 的第二部分,可选 spaces \s* 像这样:

 "begin": '...|((?<=^\|)\s*[^ \t\*\n\|]+)'

说明这些行为的在线模拟 HERE


这可能会为您提供足够的信息来解决您的问题,但如果您需要特定的解决方案,我需要更多详细信息,了解 gherkin 关键字 与以下之一的区别:

'\s*(Scenario\:|Feature\:|Scenario Outline\:|Background\:|Examples\:)'

PS:可能在上面的正则表达式中,冒号不需要转义,可以分组。此外,如果两个字符串有共同的子字符串,则将最长的放在最前面以正确匹配(或者总是在 OR-list 中从最长到最短的顺序排列元素以允许最长的字符串发生时匹配):

"match": '\s*(Scenario Outline|Background|Examples|Scenario|Feature):'

更新

我已经在线更新了正则表达式以匹配 管道 tables。对于我读过的内容和你的例子,下一个正则表达式应该适合你:

 {
     "begin": '(\|\s+[^ \t\*\n\|]+)'
     "end": '($|\s{2}|\t|\s+(?=\|))'
     "name": 'keyword.gherkin'
 }

在线更新版本HERE

更新 2

阅读你链接的 gherking 文档我决定你想要 placeholder 你可能会在 pipe-table header 突出显示为 keyword.gherkin(红色),而不是 table 的数值必须突出显示作为 constant.numeric.gherkin。如果是这样,你必须用这个替换两者:

 {
     "match": '\|(\s*[a-zA-Z][\w\']+\s*\|)+\s*$'
     "name": 'keyword.gherkin'
 }
 {
     "match": '\|(\s*[\d\.]+\s*\|)+\s*$'
     "name": 'constant.numeric.gherkin'
 }

keyword.gherkin 匹配任何管道序列 | h1 | h2 |...| hn | 与 header 由 单词组成 以字母 [a-zA-Z] 开头(后面可以跟字母、数字、下划线 _ 或单引号 ').

第二个 (constant.numeric.gherkin) 与管道序列 | N1 | N2 | ... | Nn | 类似,但字段只能是数字(十进制形式也是 123.25)。

更新 3

查看您的示例文件,我们可以完全删除 'keyword.gherkin' 正则表达式并更新 'constant.numeric.gherkin' 正则表达式如下:

{
    "match": '\|(.+\|)+'
    "name": 'constant.numeric.gherkin'
}

PS:这个正则表达式突出了 pipe-tables,不管里面的字符是什么。它不再是 "numeric" 唯一的正则表达式,但我认为它是您所需要的。