Как определить переменные регулярного выражения в языке TM? - PullRequest
0 голосов
/ 05 мая 2020

В файле возвышенного синтаксиса вы можете определить переменные для использования в регулярных выражениях (например, - match: "{{SOME_VARIABLE}}"). Похоже, вы не можете использовать tmLanguage (https://macromates.com), но маркеры часто расширяют переменные, а есть утилита, которая добавляет такую ​​поддержку переменных для дескриптора языка TM, так его можно использовать с VSCode? Я ничего не нашел в поисковике.

1 Ответ

1 голос
/ 10 июля 2020

Я тоже искал эту функциональность, поскольку регулярные выражения очень быстро становятся длинными и сложными, особенно если вы пишете файл tmLanguage в JSON, что заставляет вас экранировать некоторые символы с помощью \\.

It похоже, не поддерживается textmate из коробки. Однако у вас может быть поддержка переменных, если вы не против некоторой предварительной обработки.

Я нашел такое решение при просмотре репозитория Microsoft TypeScript TmLanguage GitHub . Они определяют грамматику Typescript в YAML , которая более удобна для чтения и требует только одного анти-sla sh для экранирования символов. В этом 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*(:)

Затем они повторно используют эти «переменные» в определениях шаблонов (или даже в других переменных, если вы посмотрите выше, Переменная 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 } 

И, наконец, они используют скрипт сборки для преобразования этой грамматики YAML в plist или json грамматику. В этом сценарии сборки они удаляют свойство «переменные» из грамматики, поскольку оно не является частью tmLanguage spe c, и они l oop над определениями переменных, чтобы заменить их вхождения ({{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;
}

Не совсем то, что вы (и я) искали, но если ваша грамматика достаточно обширна, это поможет. Если грамматика недостаточно велика, я бы не стал использовать эту предварительную обработку.

...