codekingpro/portable-devtools
114k
1"""2 pygments.lexers.shell3 ~~~~~~~~~~~~~~~~~~~~~4 5 Lexers for various shells.6 7 :copyright: Copyright 2006-2024 by the Pygments team, see AUTHORS.8 :license: BSD, see LICENSE for details.9"""10 11import re12 13from pygments.lexer import Lexer, RegexLexer, do_insertions, bygroups, \14 include, default, this, using, words, line_re15from pygments.token import Punctuation, Whitespace, \16 Text, Comment, Operator, Keyword, Name, String, Number, Generic17from pygments.util import shebang_matches18 19__all__ = ['BashLexer', 'BashSessionLexer', 'TcshLexer', 'BatchLexer',20 'SlurmBashLexer', 'MSDOSSessionLexer', 'PowerShellLexer',21 'PowerShellSessionLexer', 'TcshSessionLexer', 'FishShellLexer',22 'ExeclineLexer']23 24 25class BashLexer(RegexLexer):26 """27 Lexer for (ba|k|z|)sh shell scripts.28 """29 30 name = 'Bash'31 aliases = ['bash', 'sh', 'ksh', 'zsh', 'shell', 'openrc']32 filenames = ['*.sh', '*.ksh', '*.bash', '*.ebuild', '*.eclass',33 '*.exheres-0', '*.exlib', '*.zsh',34 '.bashrc', 'bashrc', '.bash_*', 'bash_*', 'zshrc', '.zshrc',35 '.kshrc', 'kshrc',36 'PKGBUILD']37 mimetypes = ['application/x-sh', 'application/x-shellscript', 'text/x-shellscript']38 url = 'https://en.wikipedia.org/wiki/Unix_shell'39 version_added = '0.6'40 41 tokens = {42 'root': [43 include('basic'),44 (r'`', String.Backtick, 'backticks'),45 include('data'),46 include('interp'),47 ],48 'interp': [49 (r'\$\(\(', Keyword, 'math'),50 (r'\$\(', Keyword, 'paren'),51 (r'\$\{#?', String.Interpol, 'curly'),52 (r'\$[a-zA-Z_]\w*', Name.Variable), # user variable53 (r'\$(?:\d+|[#$?!_*@-])', Name.Variable), # builtin54 (r'\$', Text),55 ],56 'basic': [57 (r'\b(if|fi|else|while|in|do|done|for|then|return|function|case|'58 r'select|break|continue|until|esac|elif)(\s*)\b',59 bygroups(Keyword, Whitespace)),60 (r'\b(alias|bg|bind|builtin|caller|cd|command|compgen|'61 r'complete|declare|dirs|disown|echo|enable|eval|exec|exit|'62 r'export|false|fc|fg|getopts|hash|help|history|jobs|kill|let|'63 r'local|logout|popd|printf|pushd|pwd|read|readonly|set|shift|'64 r'shopt|source|suspend|test|time|times|trap|true|type|typeset|'65 r'ulimit|umask|unalias|unset|wait)(?=[\s)`])',66 Name.Builtin),67 (r'\A#!.+\n', Comment.Hashbang),68 (r'#.*\n', Comment.Single),69 (r'\\[\w\W]', String.Escape),70 (r'(\b\w+)(\s*)(\+?=)', bygroups(Name.Variable, Whitespace, Operator)),71 (r'[\[\]{}()=]', Operator),72 (r'<<<', Operator), # here-string73 (r'<<-?\s*(\'?)\\?(\w+)[\w\W]+?\2', String),74 (r'&&|\|\|', Operator),75 ],76 'data': [77 (r'(?s)\$?"(\\.|[^"\\$])*"', String.Double),78 (r'"', String.Double, 'string'),79 (r"(?s)\$'(\\\\|\\[0-7]+|\\.|[^'\\])*'", String.Single),80 (r"(?s)'.*?'", String.Single),81 (r';', Punctuation),82 (r'&', Punctuation),83 (r'\|', Punctuation),84 (r'\s+', Whitespace),85 (r'\d+\b', Number),86 (r'[^=\s\[\]{}()$"\'`\\<&|;]+', Text),87 (r'<', Text),88 ],89 'string': [90 (r'"', String.Double, '#pop'),91 (r'(?s)(\\\\|\\[0-7]+|\\.|[^"\\$])+', String.Double),92 include('interp'),93 ],94 'curly': [95 (r'\}', String.Interpol, '#pop'),96 (r':-', Keyword),97 (r'\w+', Name.Variable),98 (r'[^}:"\'`$\\]+', Punctuation),99 (r':', Punctuation),100 include('root'),101 ],102 'paren': [103 (r'\)', Keyword, '#pop'),104 include('root'),105 ],106 'math': [107 (r'\)\)', Keyword, '#pop'),108 (r'\*\*|\|\||<<|>>|[-+*/%^|&<>]', Operator),109 (r'\d+#[\da-zA-Z]+', Number),110 (r'\d+#(?! )', Number),111 (r'0[xX][\da-fA-F]+', Number),112 (r'\d+', Number),113 (r'[a-zA-Z_]\w*', Name.Variable), # user variable114 include('root'),115 ],116 'backticks': [117 (r'`', String.Backtick, '#pop'),118 include('root'),119 ],120 }121 122 def analyse_text(text):123 if shebang_matches(text, r'(ba|z|)sh'):124 return 1125 if text.startswith('$ '):126 return 0.2127 128 129class SlurmBashLexer(BashLexer):130 """131 Lexer for (ba|k|z|)sh Slurm scripts.132 """133 134 name = 'Slurm'135 aliases = ['slurm', 'sbatch']136 filenames = ['*.sl']137 mimetypes = []138 version_added = '2.4'139 EXTRA_KEYWORDS = {'srun'}140 141 def get_tokens_unprocessed(self, text):142 for index, token, value in BashLexer.get_tokens_unprocessed(self, text):143 if token is Text and value in self.EXTRA_KEYWORDS:144 yield index, Name.Builtin, value145 elif token is Comment.Single and 'SBATCH' in value:146 yield index, Keyword.Pseudo, value147 else:148 yield index, token, value149 150 151class ShellSessionBaseLexer(Lexer):152 """153 Base lexer for shell sessions.154 155 .. versionadded:: 2.1156 """157 158 _bare_continuation = False159 _venv = re.compile(r'^(\([^)]*\))(\s*)')160 161 def get_tokens_unprocessed(self, text):162 innerlexer = self._innerLexerCls(**self.options)163 164 pos = 0165 curcode = ''166 insertions = []167 backslash_continuation = False168 169 for match in line_re.finditer(text):170 line = match.group()171 172 venv_match = self._venv.match(line)173 if venv_match:174 venv = venv_match.group(1)175 venv_whitespace = venv_match.group(2)176 insertions.append((len(curcode),177 [(0, Generic.Prompt.VirtualEnv, venv)]))178 if venv_whitespace:179 insertions.append((len(curcode),180 [(0, Text, venv_whitespace)]))181 line = line[venv_match.end():]182 183 m = self._ps1rgx.match(line)184 if m:185 # To support output lexers (say diff output), the output186 # needs to be broken by prompts whenever the output lexer187 # changes.188 if not insertions:189 pos = match.start()190 191 insertions.append((len(curcode),192 [(0, Generic.Prompt, m.group(1))]))193 curcode += m.group(2)194 backslash_continuation = curcode.endswith('\\\n')195 elif backslash_continuation:196 if line.startswith(self._ps2):197 insertions.append((len(curcode),198 [(0, Generic.Prompt,199 line[:len(self._ps2)])]))200 curcode += line[len(self._ps2):]201 else:202 curcode += line203 backslash_continuation = curcode.endswith('\\\n')204 elif self._bare_continuation and line.startswith(self._ps2):205 insertions.append((len(curcode),206 [(0, Generic.Prompt,207 line[:len(self._ps2)])]))208 curcode += line[len(self._ps2):]209 else:210 if insertions:211 toks = innerlexer.get_tokens_unprocessed(curcode)212 for i, t, v in do_insertions(insertions, toks):213 yield pos+i, t, v214 yield match.start(), Generic.Output, line215 insertions = []216 curcode = ''217 if insertions:218 for i, t, v in do_insertions(insertions,219 innerlexer.get_tokens_unprocessed(curcode)):220 yield pos+i, t, v221 222 223class BashSessionLexer(ShellSessionBaseLexer):224 """225 Lexer for Bash shell sessions, i.e. command lines, including a226 prompt, interspersed with output.227 """228 229 name = 'Bash Session'230 aliases = ['console', 'shell-session']231 filenames = ['*.sh-session', '*.shell-session']232 mimetypes = ['application/x-shell-session', 'application/x-sh-session']233 url = 'https://en.wikipedia.org/wiki/Unix_shell'234 version_added = '1.1'235 236 _innerLexerCls = BashLexer237 _ps1rgx = re.compile(238 r'^((?:(?:\[.*?\])|(?:\(\S+\))?(?:| |sh\S*?|\w+\S+[@:]\S+(?:\s+\S+)' \239 r'?|\[\S+[@:][^\n]+\].+))\s*[$#%]\s*)(.*\n?)')240 _ps2 = '> '241 242 243class BatchLexer(RegexLexer):244 """245 Lexer for the DOS/Windows Batch file format.246 """247 name = 'Batchfile'248 aliases = ['batch', 'bat', 'dosbatch', 'winbatch']249 filenames = ['*.bat', '*.cmd']250 mimetypes = ['application/x-dos-batch']251 url = 'https://en.wikipedia.org/wiki/Batch_file'252 version_added = '0.7'253 254 flags = re.MULTILINE | re.IGNORECASE255 256 _nl = r'\n\x1a'257 _punct = r'&<>|'258 _ws = r'\t\v\f\r ,;=\xa0'259 _nlws = r'\s\x1a\xa0,;='260 _space = rf'(?:(?:(?:\^[{_nl}])?[{_ws}])+)'261 _keyword_terminator = (rf'(?=(?:\^[{_nl}]?)?[{_ws}+./:[\\\]]|[{_nl}{_punct}(])')262 _token_terminator = rf'(?=\^?[{_ws}]|[{_punct}{_nl}])'263 _start_label = rf'((?:(?<=^[^:])|^[^:]?)[{_ws}]*)(:)'264 _label = rf'(?:(?:[^{_nlws}{_punct}+:^]|\^[{_nl}]?[\w\W])*)'265 _label_compound = rf'(?:(?:[^{_nlws}{_punct}+:^)]|\^[{_nl}]?[^)])*)'266 _number = rf'(?:-?(?:0[0-7]+|0x[\da-f]+|\d+){_token_terminator})'267 _opword = r'(?:equ|geq|gtr|leq|lss|neq)'268 _string = rf'(?:"[^{_nl}"]*(?:"|(?=[{_nl}])))'269 _variable = (r'(?:(?:%(?:\*|(?:~[a-z]*(?:\$[^:]+:)?)?\d|'270 rf'[^%:{_nl}]+(?::(?:~(?:-?\d+)?(?:,(?:-?\d+)?)?|(?:[^%{_nl}^]|'271 rf'\^[^%{_nl}])[^={_nl}]*=(?:[^%{_nl}^]|\^[^%{_nl}])*)?)?%))|'272 rf'(?:\^?![^!:{_nl}]+(?::(?:~(?:-?\d+)?(?:,(?:-?\d+)?)?|(?:'273 rf'[^!{_nl}^]|\^[^!{_nl}])[^={_nl}]*=(?:[^!{_nl}^]|\^[^!{_nl}])*)?)?\^?!))')274 _core_token = rf'(?:(?:(?:\^[{_nl}]?)?[^"{_nlws}{_punct}])+)'275 _core_token_compound = rf'(?:(?:(?:\^[{_nl}]?)?[^"{_nlws}{_punct})])+)'276 _token = rf'(?:[{_punct}]+|{_core_token})'277 _token_compound = rf'(?:[{_punct}]+|{_core_token_compound})'278 _stoken = (rf'(?:[{_punct}]+|(?:{_string}|{_variable}|{_core_token})+)')279 280 def _make_begin_state(compound, _core_token=_core_token,281 _core_token_compound=_core_token_compound,282 _keyword_terminator=_keyword_terminator,283 _nl=_nl, _punct=_punct, _string=_string,284 _space=_space, _start_label=_start_label,285 _stoken=_stoken, _token_terminator=_token_terminator,286 _variable=_variable, _ws=_ws):287 rest = '(?:{}|{}|[^"%{}{}{}])*'.format(_string, _variable, _nl, _punct,288 ')' if compound else '')289 rest_of_line = rf'(?:(?:[^{_nl}^]|\^[{_nl}]?[\w\W])*)'290 rest_of_line_compound = rf'(?:(?:[^{_nl}^)]|\^[{_nl}]?[^)])*)'291 set_space = rf'((?:(?:\^[{_nl}]?)?[^\S\n])*)'292 suffix = ''293 if compound:294 _keyword_terminator = rf'(?:(?=\))|{_keyword_terminator})'295 _token_terminator = rf'(?:(?=\))|{_token_terminator})'296 suffix = '/compound'297 return [298 ((r'\)', Punctuation, '#pop') if compound else299 (rf'\)((?=\()|{_token_terminator}){rest_of_line}',300 Comment.Single)),301 (rf'(?={_start_label})', Text, f'follow{suffix}'),302 (_space, using(this, state='text')),303 include(f'redirect{suffix}'),304 (rf'[{_nl}]+', Text),305 (r'\(', Punctuation, 'root/compound'),306 (r'@+', Punctuation),307 (rf'((?:for|if|rem)(?:(?=(?:\^[{_nl}]?)?/)|(?:(?!\^)|'308 rf'(?<=m))(?:(?=\()|{_token_terminator})))({_space}?{_core_token_compound if compound else _core_token}?(?:\^[{_nl}]?)?/(?:\^[{_nl}]?)?\?)',309 bygroups(Keyword, using(this, state='text')),310 f'follow{suffix}'),311 (rf'(goto{_keyword_terminator})({rest}(?:\^[{_nl}]?)?/(?:\^[{_nl}]?)?\?{rest})',312 bygroups(Keyword, using(this, state='text')),313 f'follow{suffix}'),314 (words(('assoc', 'break', 'cd', 'chdir', 'cls', 'color', 'copy',315 'date', 'del', 'dir', 'dpath', 'echo', 'endlocal', 'erase',316 'exit', 'ftype', 'keys', 'md', 'mkdir', 'mklink', 'move',317 'path', 'pause', 'popd', 'prompt', 'pushd', 'rd', 'ren',318 'rename', 'rmdir', 'setlocal', 'shift', 'start', 'time',319 'title', 'type', 'ver', 'verify', 'vol'),320 suffix=_keyword_terminator), Keyword, f'follow{suffix}'),321 (rf'(call)({_space}?)(:)',322 bygroups(Keyword, using(this, state='text'), Punctuation),323 f'call{suffix}'),324 (rf'call{_keyword_terminator}', Keyword),325 (rf'(for{_token_terminator}(?!\^))({_space})(/f{_token_terminator})',326 bygroups(Keyword, using(this, state='text'), Keyword),327 ('for/f', 'for')),328 (rf'(for{_token_terminator}(?!\^))({_space})(/l{_token_terminator})',329 bygroups(Keyword, using(this, state='text'), Keyword),330 ('for/l', 'for')),331 (rf'for{_token_terminator}(?!\^)', Keyword, ('for2', 'for')),332 (rf'(goto{_keyword_terminator})({_space}?)(:?)',333 bygroups(Keyword, using(this, state='text'), Punctuation),334 f'label{suffix}'),335 (rf'(if(?:(?=\()|{_token_terminator})(?!\^))({_space}?)((?:/i{_token_terminator})?)({_space}?)((?:not{_token_terminator})?)({_space}?)',336 bygroups(Keyword, using(this, state='text'), Keyword,337 using(this, state='text'), Keyword,338 using(this, state='text')), ('(?', 'if')),339 (rf'rem(((?=\()|{_token_terminator}){_space}?{_stoken}?.*|{_keyword_terminator}{rest_of_line_compound if compound else rest_of_line})',340 Comment.Single, f'follow{suffix}'),341 (rf'(set{_keyword_terminator}){set_space}(/a)',342 bygroups(Keyword, using(this, state='text'), Keyword),343 f'arithmetic{suffix}'),344 (r'(set{}){}((?:/p)?){}((?:(?:(?:\^[{}]?)?[^"{}{}^={}]|'345 r'\^[{}]?[^"=])+)?)((?:(?:\^[{}]?)?=)?)'.format(_keyword_terminator, set_space, set_space, _nl, _nl, _punct,346 ')' if compound else '', _nl, _nl),347 bygroups(Keyword, using(this, state='text'), Keyword,348 using(this, state='text'), using(this, state='variable'),349 Punctuation),350 f'follow{suffix}'),351 default(f'follow{suffix}')352 ]353 354 def _make_follow_state(compound, _label=_label,355 _label_compound=_label_compound, _nl=_nl,356 _space=_space, _start_label=_start_label,357 _token=_token, _token_compound=_token_compound,358 _ws=_ws):359 suffix = '/compound' if compound else ''360 state = []361 if compound:362 state.append((r'(?=\))', Text, '#pop'))363 state += [364 (rf'{_start_label}([{_ws}]*)({_label_compound if compound else _label})(.*)',365 bygroups(Text, Punctuation, Text, Name.Label, Comment.Single)),366 include(f'redirect{suffix}'),367 (rf'(?=[{_nl}])', Text, '#pop'),368 (r'\|\|?|&&?', Punctuation, '#pop'),369 include('text')370 ]371 return state372 373 def _make_arithmetic_state(compound, _nl=_nl, _punct=_punct,374 _string=_string, _variable=_variable,375 _ws=_ws, _nlws=_nlws):376 op = r'=+\-*/!~'377 state = []378 if compound:379 state.append((r'(?=\))', Text, '#pop'))380 state += [381 (r'0[0-7]+', Number.Oct),382 (r'0x[\da-f]+', Number.Hex),383 (r'\d+', Number.Integer),384 (r'[(),]+', Punctuation),385 (rf'([{op}]|%|\^\^)+', Operator),386 (r'({}|{}|(\^[{}]?)?[^(){}%\^"{}{}]|\^[{}]?{})+'.format(_string, _variable, _nl, op, _nlws, _punct, _nlws,387 r'[^)]' if compound else r'[\w\W]'),388 using(this, state='variable')),389 (r'(?=[\x00|&])', Text, '#pop'),390 include('follow')391 ]392 return state393 394 def _make_call_state(compound, _label=_label,395 _label_compound=_label_compound):396 state = []397 if compound:398 state.append((r'(?=\))', Text, '#pop'))399 state.append((r'(:?)(%s)' % (_label_compound if compound else _label),400 bygroups(Punctuation, Name.Label), '#pop'))401 return state402 403 def _make_label_state(compound, _label=_label,404 _label_compound=_label_compound, _nl=_nl,405 _punct=_punct, _string=_string, _variable=_variable):406 state = []407 if compound:408 state.append((r'(?=\))', Text, '#pop'))409 state.append((r'({}?)((?:{}|{}|\^[{}]?{}|[^"%^{}{}{}])*)'.format(_label_compound if compound else _label, _string,410 _variable, _nl, r'[^)]' if compound else r'[\w\W]', _nl,411 _punct, r')' if compound else ''),412 bygroups(Name.Label, Comment.Single), '#pop'))413 return state414 415 def _make_redirect_state(compound,416 _core_token_compound=_core_token_compound,417 _nl=_nl, _punct=_punct, _stoken=_stoken,418 _string=_string, _space=_space,419 _variable=_variable, _nlws=_nlws):420 stoken_compound = (rf'(?:[{_punct}]+|(?:{_string}|{_variable}|{_core_token_compound})+)')421 return [422 (rf'((?:(?<=[{_nlws}])\d)?)(>>?&|<&)([{_nlws}]*)(\d)',423 bygroups(Number.Integer, Punctuation, Text, Number.Integer)),424 (rf'((?:(?<=[{_nlws}])(?<!\^[{_nl}])\d)?)(>>?|<)({_space}?{stoken_compound if compound else _stoken})',425 bygroups(Number.Integer, Punctuation, using(this, state='text')))426 ]427 428 tokens = {429 'root': _make_begin_state(False),430 'follow': _make_follow_state(False),431 'arithmetic': _make_arithmetic_state(False),432 'call': _make_call_state(False),433 'label': _make_label_state(False),434 'redirect': _make_redirect_state(False),435 'root/compound': _make_begin_state(True),436 'follow/compound': _make_follow_state(True),437 'arithmetic/compound': _make_arithmetic_state(True),438 'call/compound': _make_call_state(True),439 'label/compound': _make_label_state(True),440 'redirect/compound': _make_redirect_state(True),441 'variable-or-escape': [442 (_variable, Name.Variable),443 (rf'%%|\^[{_nl}]?(\^!|[\w\W])', String.Escape)444 ],445 'string': [446 (r'"', String.Double, '#pop'),447 (_variable, Name.Variable),448 (r'\^!|%%', String.Escape),449 (rf'[^"%^{_nl}]+|[%^]', String.Double),450 default('#pop')451 ],452 'sqstring': [453 include('variable-or-escape'),454 (r'[^%]+|%', String.Single)455 ],456 'bqstring': [457 include('variable-or-escape'),458 (r'[^%]+|%', String.Backtick)459 ],460 'text': [461 (r'"', String.Double, 'string'),462 include('variable-or-escape'),463 (rf'[^"%^{_nlws}{_punct}\d)]+|.', Text)464 ],465 'variable': [466 (r'"', String.Double, 'string'),467 include('variable-or-escape'),468 (rf'[^"%^{_nl}]+|.', Name.Variable)469 ],470 'for': [471 (rf'({_space})(in)({_space})(\()',472 bygroups(using(this, state='text'), Keyword,473 using(this, state='text'), Punctuation), '#pop'),474 include('follow')475 ],476 'for2': [477 (r'\)', Punctuation),478 (rf'({_space})(do{_token_terminator})',479 bygroups(using(this, state='text'), Keyword), '#pop'),480 (rf'[{_nl}]+', Text),481 include('follow')482 ],483 'for/f': [484 (rf'(")((?:{_variable}|[^"])*?")([{_nlws}]*)(\))',485 bygroups(String.Double, using(this, state='string'), Text,486 Punctuation)),487 (r'"', String.Double, ('#pop', 'for2', 'string')),488 (rf"('(?:%%|{_variable}|[\w\W])*?')([{_nlws}]*)(\))",489 bygroups(using(this, state='sqstring'), Text, Punctuation)),490 (rf'(`(?:%%|{_variable}|[\w\W])*?`)([{_nlws}]*)(\))',491 bygroups(using(this, state='bqstring'), Text, Punctuation)),492 include('for2')493 ],494 'for/l': [495 (r'-?\d+', Number.Integer),496 include('for2')497 ],498 'if': [499 (rf'((?:cmdextversion|errorlevel){_token_terminator})({_space})(\d+)',500 bygroups(Keyword, using(this, state='text'),501 Number.Integer), '#pop'),502 (rf'(defined{_token_terminator})({_space})({_stoken})',503 bygroups(Keyword, using(this, state='text'),504 using(this, state='variable')), '#pop'),505 (rf'(exist{_token_terminator})({_space}{_stoken})',506 bygroups(Keyword, using(this, state='text')), '#pop'),507 (rf'({_number}{_space})({_opword})({_space}{_number})',508 bygroups(using(this, state='arithmetic'), Operator.Word,509 using(this, state='arithmetic')), '#pop'),510 (_stoken, using(this, state='text'), ('#pop', 'if2')),511 ],512 'if2': [513 (rf'({_space}?)(==)({_space}?{_stoken})',514 bygroups(using(this, state='text'), Operator,515 using(this, state='text')), '#pop'),516 (rf'({_space})({_opword})({_space}{_stoken})',517 bygroups(using(this, state='text'), Operator.Word,518 using(this, state='text')), '#pop')519 ],520 '(?': [521 (_space, using(this, state='text')),522 (r'\(', Punctuation, ('#pop', 'else?', 'root/compound')),523 default('#pop')524 ],525 'else?': [526 (_space, using(this, state='text')),527 (rf'else{_token_terminator}', Keyword, '#pop'),528 default('#pop')529 ]530 }531 532 533class MSDOSSessionLexer(ShellSessionBaseLexer):534 """535 Lexer for MS DOS shell sessions, i.e. command lines, including a536 prompt, interspersed with output.537 """538 539 name = 'MSDOS Session'540 aliases = ['doscon']541 filenames = []542 mimetypes = []543 url = 'https://en.wikipedia.org/wiki/MS-DOS'544 version_added = '2.1'545 546 _innerLexerCls = BatchLexer547 _ps1rgx = re.compile(r'^([^>]*>)(.*\n?)')548 _ps2 = 'More? '549 550 551class TcshLexer(RegexLexer):552 """553 Lexer for tcsh scripts.554 """555 556 name = 'Tcsh'557 aliases = ['tcsh', 'csh']558 filenames = ['*.tcsh', '*.csh']559 mimetypes = ['application/x-csh']560 url = 'https://www.tcsh.org'561 version_added = '0.10'562 563 tokens = {564 'root': [565 include('basic'),566 (r'\$\(', Keyword, 'paren'),567 (r'\$\{#?', Keyword, 'curly'),568 (r'`', String.Backtick, 'backticks'),569 include('data'),570 ],571 'basic': [572 (r'\b(if|endif|else|while|then|foreach|case|default|'573 r'break|continue|goto|breaksw|end|switch|endsw)\s*\b',574 Keyword),575 (r'\b(alias|alloc|bg|bindkey|builtins|bye|caller|cd|chdir|'576 r'complete|dirs|echo|echotc|eval|exec|exit|fg|filetest|getxvers|'577 r'glob|getspath|hashstat|history|hup|inlib|jobs|kill|'578 r'limit|log|login|logout|ls-F|migrate|newgrp|nice|nohup|notify|'579 r'onintr|popd|printenv|pushd|rehash|repeat|rootnode|popd|pushd|'580 r'set|shift|sched|setenv|setpath|settc|setty|setxvers|shift|'581 r'source|stop|suspend|source|suspend|telltc|time|'582 r'umask|unalias|uncomplete|unhash|universe|unlimit|unset|unsetenv|'583 r'ver|wait|warp|watchlog|where|which)\s*\b',584 Name.Builtin),585 (r'#.*', Comment),586 (r'\\[\w\W]', String.Escape),587 (r'(\b\w+)(\s*)(=)', bygroups(Name.Variable, Text, Operator)),588 (r'[\[\]{}()=]+', Operator),589 (r'<<\s*(\'?)\\?(\w+)[\w\W]+?\2', String),590 (r';', Punctuation),591 ],592 'data': [593 (r'(?s)"(\\\\|\\[0-7]+|\\.|[^"\\])*"', String.Double),594 (r"(?s)'(\\\\|\\[0-7]+|\\.|[^'\\])*'", String.Single),595 (r'\s+', Text),596 (r'[^=\s\[\]{}()$"\'`\\;#]+', Text),597 (r'\d+(?= |\Z)', Number),598 (r'\$#?(\w+|.)', Name.Variable),599 ],600 'curly': [601 (r'\}', Keyword, '#pop'),602 (r':-', Keyword),603 (r'\w+', Name.Variable),604 (r'[^}:"\'`$]+', Punctuation),605 (r':', Punctuation),606 include('root'),607 ],608 'paren': [609 (r'\)', Keyword, '#pop'),610 include('root'),611 ],612 'backticks': [613 (r'`', String.Backtick, '#pop'),614 include('root'),615 ],616 }617 618 619class TcshSessionLexer(ShellSessionBaseLexer):620 """621 Lexer for Tcsh sessions, i.e. command lines, including a622 prompt, interspersed with output.623 """624 625 name = 'Tcsh Session'626 aliases = ['tcshcon']627 filenames = []628 mimetypes = []629 url = 'https://www.tcsh.org'630 version_added = '2.1'631 632 _innerLexerCls = TcshLexer633 _ps1rgx = re.compile(r'^([^>]+>)(.*\n?)')634 _ps2 = '? '635 636 637class PowerShellLexer(RegexLexer):638 """639 For Windows PowerShell code.640 """641 name = 'PowerShell'642 aliases = ['powershell', 'pwsh', 'posh', 'ps1', 'psm1']643 filenames = ['*.ps1', '*.psm1']644 mimetypes = ['text/x-powershell']645 url = 'https://learn.microsoft.com/en-us/powershell'646 version_added = '1.5'647 648 flags = re.DOTALL | re.IGNORECASE | re.MULTILINE649 650 keywords = (651 'while validateset validaterange validatepattern validatelength '652 'validatecount until trap switch return ref process param parameter in '653 'if global: local: function foreach for finally filter end elseif else '654 'dynamicparam do default continue cmdletbinding break begin alias \\? '655 '% #script #private #local #global mandatory parametersetname position '656 'valuefrompipeline valuefrompipelinebypropertyname '657 'valuefromremainingarguments helpmessage try catch throw').split()658 659 operators = (660 'and as band bnot bor bxor casesensitive ccontains ceq cge cgt cle '661 'clike clt cmatch cne cnotcontains cnotlike cnotmatch contains '662 'creplace eq exact f file ge gt icontains ieq ige igt ile ilike ilt '663 'imatch ine inotcontains inotlike inotmatch ireplace is isnot le like '664 'lt match ne not notcontains notlike notmatch or regex replace '665 'wildcard').split()666 667 verbs = (668 'write where watch wait use update unregister unpublish unprotect '669 'unlock uninstall undo unblock trace test tee take sync switch '670 'suspend submit stop step start split sort skip show set send select '671 'search scroll save revoke resume restore restart resolve resize '672 'reset request repair rename remove register redo receive read push '673 'publish protect pop ping out optimize open new move mount merge '674 'measure lock limit join invoke install initialize import hide group '675 'grant get format foreach find export expand exit enter enable edit '676 'dismount disconnect disable deny debug cxnew copy convertto '677 'convertfrom convert connect confirm compress complete compare close '678 'clear checkpoint block backup assert approve aggregate add').split()679 680 aliases_ = (681 'ac asnp cat cd cfs chdir clc clear clhy cli clp cls clv cnsn '682 'compare copy cp cpi cpp curl cvpa dbp del diff dir dnsn ebp echo epal '683 'epcsv epsn erase etsn exsn fc fhx fl foreach ft fw gal gbp gc gci gcm '684 'gcs gdr ghy gi gjb gl gm gmo gp gps gpv group gsn gsnp gsv gu gv gwmi '685 'h history icm iex ihy ii ipal ipcsv ipmo ipsn irm ise iwmi iwr kill lp '686 'ls man md measure mi mount move mp mv nal ndr ni nmo npssc nsn nv ogv '687 'oh popd ps pushd pwd r rbp rcjb rcsn rd rdr ren ri rjb rm rmdir rmo '688 'rni rnp rp rsn rsnp rujb rv rvpa rwmi sajb sal saps sasv sbp sc select '689 'set shcm si sl sleep sls sort sp spjb spps spsv start sujb sv swmi tee '690 'trcm type wget where wjb write').split()691 692 commenthelp = (693 'component description example externalhelp forwardhelpcategory '694 'forwardhelptargetname functionality inputs link '695 'notes outputs parameter remotehelprunspace role synopsis').split()696 697 tokens = {698 'root': [699 # we need to count pairs of parentheses for correct highlight700 # of '$(...)' blocks in strings701 (r'\(', Punctuation, 'child'),702 (r'\s+', Text),703 (r'^(\s*#[#\s]*)(\.(?:{}))([^\n]*$)'.format('|'.join(commenthelp)),704 bygroups(Comment, String.Doc, Comment)),705 (r'#[^\n]*?$', Comment),706 (r'(<|<)#', Comment.Multiline, 'multline'),707 (r'@"\n', String.Heredoc, 'heredoc-double'),708 (r"@'\n.*?\n'@", String.Heredoc),709 # escaped syntax710 (r'`[\'"$@-]', Punctuation),711 (r'"', String.Double, 'string'),712 (r"'([^']|'')*'", String.Single),713 (r'(\$|@@|@)((global|script|private|env):)?\w+',714 Name.Variable),715 (r'({})\b'.format('|'.join(keywords)), Keyword),716 (r'-({})\b'.format('|'.join(operators)), Operator),717 (r'({})-[a-z_]\w*\b'.format('|'.join(verbs)), Name.Builtin),718 (r'({})\s'.format('|'.join(aliases_)), Name.Builtin),719 (r'\[[a-z_\[][\w. `,\[\]]*\]', Name.Constant), # .net [type]s720 (r'-[a-z_]\w*', Name),721 (r'\w+', Name),722 (r'[.,;:@{}\[\]$()=+*/\\&%!~?^`|<>-]', Punctuation),723 ],724 'child': [725 (r'\)', Punctuation, '#pop'),726 include('root'),727 ],728 'multline': [729 (r'[^#&.]+', Comment.Multiline),730 (r'#(>|>)', Comment.Multiline, '#pop'),731 (r'\.({})'.format('|'.join(commenthelp)), String.Doc),732 (r'[#&.]', Comment.Multiline),733 ],734 'string': [735 (r"`[0abfnrtv'\"$`]", String.Escape),736 (r'[^$`"]+', String.Double),737 (r'\$\(', Punctuation, 'child'),738 (r'""', String.Double),739 (r'[`$]', String.Double),740 (r'"', String.Double, '#pop'),741 ],742 'heredoc-double': [743 (r'\n"@', String.Heredoc, '#pop'),744 (r'\$\(', Punctuation, 'child'),745 (r'[^@\n]+"]', String.Heredoc),746 (r".", String.Heredoc),747 ]748 }749 750 751class PowerShellSessionLexer(ShellSessionBaseLexer):752 """753 Lexer for PowerShell sessions, i.e. command lines, including a754 prompt, interspersed with output.755 """756 757 name = 'PowerShell Session'758 aliases = ['pwsh-session', 'ps1con']759 filenames = []760 mimetypes = []761 url = 'https://learn.microsoft.com/en-us/powershell'762 version_added = '2.1'763 764 _innerLexerCls = PowerShellLexer765 _bare_continuation = True766 _ps1rgx = re.compile(r'^((?:\[[^]]+\]: )?PS[^>]*> ?)(.*\n?)')767 _ps2 = '> '768 769 770class FishShellLexer(RegexLexer):771 """772 Lexer for Fish shell scripts.773 """774 775 name = 'Fish'776 aliases = ['fish', 'fishshell']777 filenames = ['*.fish', '*.load']778 mimetypes = ['application/x-fish']779 url = 'https://fishshell.com'780 version_added = '2.1'781 782 tokens = {783 'root': [784 include('basic'),785 include('data'),786 include('interp'),787 ],788 'interp': [789 (r'\$\(\(', Keyword, 'math'),790 (r'\(', Keyword, 'paren'),791 (r'\$#?(\w+|.)', Name.Variable),792 ],793 'basic': [794 (r'\b(begin|end|if|else|while|break|for|in|return|function|block|'795 r'case|continue|switch|not|and|or|set|echo|exit|pwd|true|false|'796 r'cd|count|test)(\s*)\b',797 bygroups(Keyword, Text)),798 (r'\b(alias|bg|bind|breakpoint|builtin|command|commandline|'799 r'complete|contains|dirh|dirs|emit|eval|exec|fg|fish|fish_config|'800 r'fish_indent|fish_pager|fish_prompt|fish_right_prompt|'801 r'fish_update_completions|fishd|funced|funcsave|functions|help|'802 r'history|isatty|jobs|math|mimedb|nextd|open|popd|prevd|psub|'803 r'pushd|random|read|set_color|source|status|trap|type|ulimit|'804 r'umask|vared|fc|getopts|hash|kill|printf|time|wait)\s*\b(?!\.)',805 Name.Builtin),806 (r'#.*\n', Comment),807 (r'\\[\w\W]', String.Escape),808 (r'(\b\w+)(\s*)(=)', bygroups(Name.Variable, Whitespace, Operator)),809 (r'[\[\]()=]', Operator),810 (r'<<-?\s*(\'?)\\?(\w+)[\w\W]+?\2', String),811 ],812 'data': [813 (r'(?s)\$?"(\\\\|\\[0-7]+|\\.|[^"\\$])*"', String.Double),814 (r'"', String.Double, 'string'),815 (r"(?s)\$'(\\\\|\\[0-7]+|\\.|[^'\\])*'", String.Single),816 (r"(?s)'.*?'", String.Single),817 (r';', Punctuation),818 (r'&|\||\^|<|>', Operator),819 (r'\s+', Text),820 (r'\d+(?= |\Z)', Number),821 (r'[^=\s\[\]{}()$"\'`\\<&|;]+', Text),822 ],823 'string': [824 (r'"', String.Double, '#pop'),825 (r'(?s)(\\\\|\\[0-7]+|\\.|[^"\\$])+', String.Double),826 include('interp'),827 ],828 'paren': [829 (r'\)', Keyword, '#pop'),830 include('root'),831 ],832 'math': [833 (r'\)\)', Keyword, '#pop'),834 (r'[-+*/%^|&]|\*\*|\|\|', Operator),835 (r'\d+#\d+', Number),836 (r'\d+#(?! )', Number),837 (r'\d+', Number),838 include('root'),839 ],840 }841 842class ExeclineLexer(RegexLexer):843 """844 Lexer for Laurent Bercot's execline language.845 """846 847 name = 'execline'848 aliases = ['execline']849 filenames = ['*.exec']850 url = 'https://skarnet.org/software/execline'851 version_added = '2.7'852 853 tokens = {854 'root': [855 include('basic'),856 include('data'),857 include('interp')858 ],859 'interp': [860 (r'\$\{', String.Interpol, 'curly'),861 (r'\$[\w@#]+', Name.Variable), # user variable862 (r'\$', Text),863 ],864 'basic': [865 (r'\b(background|backtick|cd|define|dollarat|elgetopt|'866 r'elgetpositionals|elglob|emptyenv|envfile|exec|execlineb|'867 r'exit|export|fdblock|fdclose|fdmove|fdreserve|fdswap|'868 r'forbacktickx|foreground|forstdin|forx|getcwd|getpid|heredoc|'869 r'homeof|if|ifelse|ifte|ifthenelse|importas|loopwhilex|'870 r'multidefine|multisubstitute|pipeline|piperw|posix-cd|'871 r'redirfd|runblock|shift|trap|tryexec|umask|unexport|wait|'872 r'withstdinas)\b', Name.Builtin),873 (r'\A#!.+\n', Comment.Hashbang),874 (r'#.*\n', Comment.Single),875 (r'[{}]', Operator)876 ],877 'data': [878 (r'(?s)"(\\.|[^"\\$])*"', String.Double),879 (r'"', String.Double, 'string'),880 (r'\s+', Text),881 (r'[^\s{}$"\\]+', Text)882 ],883 'string': [884 (r'"', String.Double, '#pop'),885 (r'(?s)(\\\\|\\.|[^"\\$])+', String.Double),886 include('interp'),887 ],888 'curly': [889 (r'\}', String.Interpol, '#pop'),890 (r'[\w#@]+', Name.Variable),891 include('root')892 ]893 894 }895 896 def analyse_text(text):897 if shebang_matches(text, r'execlineb'):898 return 1899 