batchLanguage top-level constant

Grammar const batchLanguage

Windows batch files (.bat, .cmd).

Implementation

const batchLanguage = Grammar(
  name: 'batch',
  aliases: ['bat', 'cmd', 'dos'],
  fileExtensions: ['bat', 'cmd'],
  caseInsensitive: true,
  signatures: [
    r'^@echo\s+off\s*$',
    r'^\s*(?:setlocal|endlocal)\b',
    r'%~dp0',
    r'^\s*goto\s+:?\w+',
    r'^\s*rem\s',
  ],
  rules: [
    // `REM …` and `:: …` comments, at the start of a statement.
    TokenRule(r'^[ \t]*@?rem(?:[ \t].*)?$', scope: Scopes.comment),
    TokenRule(r'(?<=&)[ \t]*rem(?:[ \t].*)?$', scope: Scopes.comment),
    TokenRule(r'^[ \t]*::.*$', scope: Scopes.comment),
    // Labels: `:loop`.
    TokenRule(r'^[ \t]*:[A-Za-z_][\w.-]*', scope: Scopes.function),
    TokenRule(r'^[ \t]*@', scope: Scopes.operator),
    // Label targets: `goto :done`, `call :sub`.
    TokenRule(
      r'(?<=\b(?:goto|call)[ \t]{1,4}):?(?!eof\b)[A-Za-z_][\w.-]*',
      scope: Scopes.function,
    ),
    QuotedString('"', escape: null, rules: [IncludeRule('variables')]),
    IncludeRule('variables'),
    TokenRule(r'\^[\s\S]', scope: Scopes.stringEscape),
    // Switches: `/b`, `/i`, `/?`.
    TokenRule(r'(?<=\s)/[A-Za-z?][\w:-]*', scope: Scopes.attribute),
    TokenRule(r'(?<![\w%!.])\d+(?![\w.])', scope: Scopes.number),
    KeywordRule({
      Scopes.keyword: [
        'if', 'else', 'goto', 'call', 'exit', 'for', 'in', 'do', 'not', //
        'exist', 'defined', 'errorlevel', 'equ', 'neq', 'lss', 'leq',
        'gtr', 'geq', 'setlocal', 'endlocal', 'shift', 'enabledelayedexpansion',
        'enableextensions', 'disabledelayedexpansion', 'eof',
      ],
      Scopes.function: [
        'echo', 'set', 'cd', 'chdir', 'pushd', 'popd', 'md', 'mkdir', 'rd', //
        'rmdir', 'del', 'erase', 'copy', 'xcopy', 'robocopy', 'move', 'ren',
        'rename', 'type', 'start', 'pause', 'cls', 'title', 'color',
        'choice', 'timeout', 'find', 'findstr', 'where', 'tasklist',
        'taskkill', 'dir', 'path', 'prompt', 'ver', 'vol', 'assoc',
        'mklink', 'attrib', 'powershell',
      ],
      Scopes.literal: ['nul', 'con', 'on', 'off'],
    }, word: r'(?<![\w%!.\\/-])[A-Za-z_][\w-]*'),
    TokenRule(r'==|&&|\|\||[<>]{1,2}|[|&=]', scope: Scopes.operator),
  ],
  repository: {
    'variables': [
      // `%%i` loop variables and `%~dp0`-style parameters.
      TokenRule(r'%%~?[a-z]*[A-Za-z]', scope: Scopes.variable),
      TokenRule(r'%~[a-z$:]*[0-9]|%[0-9*]', scope: Scopes.variable),
      // `%NAME%`, `%NAME:~0,5%`, `%NAME:a=b%`, and delayed `!NAME!`.
      TokenRule(
        r'%[A-Za-z_][\w#$@.()-]*(?::[^%\n]*)?%',
        scope: Scopes.variable,
      ),
      TokenRule(
        r'![A-Za-z_][\w#$@.()-]*(?::[^!\n]*)?!',
        scope: Scopes.variable,
      ),
    ],
  },
);