如何用TM语言定义正则表达式变量?

4 textmate visual-studio-code

在 sublime-syntax 文件中,您可以定义在正则表达式中使用的变量(例如- match: "{{SOME_VARIABLE}}")。看起来在tmLanguage ( https://macromates.com )中不能,但是荧光笔经常扩展变量,那么是否有一个实用程序可以为 TM 语言描述符添加这样的变量支持,以便它可以与 VSCode 一起使用?我用搜索引擎什么也没找到。

小智 5

我也在寻找这个功能,因为正则表达式很快就会变得又长又复杂,特别是如果用 JSON 编写 tmLanguage 文件,这会迫使您使用 \\ 转义一些字符。

textmate 似乎不支持开箱即用。但是,如果您不介意进行一些预处理,则可以获得变量支持。

我在浏览Microsoft TypeScript TmLanguage GitHub 存储库时找到了这种解决方案。他们在 YAML 中定义了 Typescript 语法,这种语法更具可读性,并且只需要一个反斜杠来转义字符。在此 YAML 文件中,他们为常用模式定义“变量”,例如:

variables:
  startOfIdentifier: (?<![_$[:alnum:]])(?:(?<=\.\.\.)|(?<!\.))
  endOfIdentifier: (?![_$[:alnum:]])(?:(?=\.\.\.)|(?!\.))
  propertyAccess: (?:(\.)|(\?\.(?!\s*[[:digit:]])))
  propertyAccessPreIdentifier: \??\.\s*
  identifier: '[_$[:alpha:]][_$[:alnum:]]*'
  constantIdentifier: '[[:upper:]][_$[:digit:][:upper:]]*'
  propertyIdentifier: '\#?{{identifier}}'
  constantPropertyIdentifier: '\#?{{constantIdentifier}}'
  label: ({{identifier}})\s*(:)
Run Code Online (Sandbox Code Playgroud)

然后他们在模式定义中重用这些“变量”(甚至在其他变量中,如果你看上面,变量label使用identifier变量),例如:

enum-declaration:
    name: meta.enum.declaration.ts
    begin: '{{startOfDeclaration}}(?:\b(const)\s+)?\b(enum)\s+({{identifier}})'
    beginCaptures:
      '1': { name: keyword.control.export.ts }
      '2': { name: storage.modifier.ts}
      '3': { name: storage.modifier.ts}
      '4': { name: storage.type.enum.ts }
      '5': { name: entity.name.type.enum.ts } 
Run Code Online (Sandbox Code Playgroud)

最后,他们使用构建脚本将此 YAML 语法转换为 plist 或 json 语法。在此构建脚本中,他们从语法中删除了“variables”属性,因为它不是 tmLanguage 规范的一部分,并且它们循环遍历变量定义以替换它们{{variable}}在其他变量或begin, end,match模式中的出现 ( )。

function replacePatternVariables(pattern: string, variableReplacers: VariableReplacer[]) {
    let result = pattern;
    for (const [variableName, value] of variableReplacers) {
        result = result.replace(variableName, value);
    }
    return result;
}

type VariableReplacer = [RegExp, string];
function updateGrammarVariables(grammar: TmGrammar, variables: MapLike<string>) {
    delete grammar.variables;
    const variableReplacers: VariableReplacer[] = [];
    for (const variableName in variables) {
        // Replace the pattern with earlier variables
        const pattern = replacePatternVariables(variables[variableName], variableReplacers);
        variableReplacers.push([new RegExp(`{{${variableName}}}`, "gim"), pattern]);
    }
    transformGrammarRepository(
        grammar,
        ["begin", "end", "match"],
        pattern => replacePatternVariables(pattern, variableReplacers)
    );
    return grammar;
}
Run Code Online (Sandbox Code Playgroud)

不完全是你(和我)正在寻找的东西,但如果你的语法足够大,它会有所帮助。如果语法不够大,那么我不会使用此预处理。