ThirdParty/Pygments/pygments/lexers/shell.py

changeset 4697
c2e9bf425554
parent 4172
4f20dba37ab6
child 5072
aab59042fefb
equal deleted inserted replaced
4696:bf4d19a7cade 4697:c2e9bf425554
3 pygments.lexers.shell 3 pygments.lexers.shell
4 ~~~~~~~~~~~~~~~~~~~~~ 4 ~~~~~~~~~~~~~~~~~~~~~
5 5
6 Lexers for various shells. 6 Lexers for various shells.
7 7
8 :copyright: Copyright 2006-2014 by the Pygments team, see AUTHORS. 8 :copyright: Copyright 2006-2015 by the Pygments team, see AUTHORS.
9 :license: BSD, see LICENSE for details. 9 :license: BSD, see LICENSE for details.
10 """ 10 """
11 11
12 import re 12 import re
13 13
14 from pygments.lexer import Lexer, RegexLexer, do_insertions, bygroups, include 14 from pygments.lexer import Lexer, RegexLexer, do_insertions, bygroups, \
15 include, default, this, using, words
15 from pygments.token import Punctuation, \ 16 from pygments.token import Punctuation, \
16 Text, Comment, Operator, Keyword, Name, String, Number, Generic 17 Text, Comment, Operator, Keyword, Name, String, Number, Generic
17 from pygments.util import shebang_matches 18 from pygments.util import shebang_matches
18 19
19 20
20 __all__ = ['BashLexer', 'BashSessionLexer', 'TcshLexer', 'BatchLexer', 21 __all__ = ['BashLexer', 'BashSessionLexer', 'TcshLexer', 'BatchLexer',
21 'PowerShellLexer', 'ShellSessionLexer'] 22 'MSDOSSessionLexer', 'PowerShellLexer',
22 23 'PowerShellSessionLexer', 'TcshSessionLexer', 'FishShellLexer']
23 line_re = re.compile('.*?\n') 24
25 line_re = re.compile('.*?\n')
24 26
25 27
26 class BashLexer(RegexLexer): 28 class BashLexer(RegexLexer):
27 """ 29 """
28 Lexer for (ba|k|)sh shell scripts. 30 Lexer for (ba|k|)sh shell scripts.
45 ], 47 ],
46 'interp': [ 48 'interp': [
47 (r'\$\(\(', Keyword, 'math'), 49 (r'\$\(\(', Keyword, 'math'),
48 (r'\$\(', Keyword, 'paren'), 50 (r'\$\(', Keyword, 'paren'),
49 (r'\$\{#?', String.Interpol, 'curly'), 51 (r'\$\{#?', String.Interpol, 'curly'),
50 (r'\$#?(\w+|.)', Name.Variable), 52 (r'\$[a-fA-F_][a-fA-F0-9_]*', Name.Variable), # user variable
53 (r'\$(?:\d+|[#$?!_*@-])', Name.Variable), # builtin
54 (r'\$', Text),
51 ], 55 ],
52 'basic': [ 56 'basic': [
53 (r'\b(if|fi|else|while|do|done|for|then|return|function|case|' 57 (r'\b(if|fi|else|while|do|done|for|then|return|function|case|'
54 r'select|continue|until|esac|elif)(\s*)\b', 58 r'select|continue|until|esac|elif)(\s*)\b',
55 bygroups(Keyword, Text)), 59 bygroups(Keyword, Text)),
56 (r'\b(alias|bg|bind|break|builtin|caller|cd|command|compgen|' 60 (r'\b(alias|bg|bind|break|builtin|caller|cd|command|compgen|'
57 r'complete|declare|dirs|disown|echo|enable|eval|exec|exit|' 61 r'complete|declare|dirs|disown|echo|enable|eval|exec|exit|'
58 r'export|false|fc|fg|getopts|hash|help|history|jobs|kill|let|' 62 r'export|false|fc|fg|getopts|hash|help|history|jobs|kill|let|'
59 r'local|logout|popd|printf|pushd|pwd|read|readonly|set|shift|' 63 r'local|logout|popd|printf|pushd|pwd|read|readonly|set|shift|'
60 r'shopt|source|suspend|test|time|times|trap|true|type|typeset|' 64 r'shopt|source|suspend|test|time|times|trap|true|type|typeset|'
61 r'ulimit|umask|unalias|unset|wait)\s*\b(?!\.)', 65 r'ulimit|umask|unalias|unset|wait)(?=[\s)`])',
62 Name.Builtin), 66 Name.Builtin),
63 (r'#.*\n', Comment), 67 (r'\A#!.+\n', Comment.Hashbang),
68 (r'#.*\n', Comment.Single),
64 (r'\\[\w\W]', String.Escape), 69 (r'\\[\w\W]', String.Escape),
65 (r'(\b\w+)(\s*)(=)', bygroups(Name.Variable, Text, Operator)), 70 (r'(\b\w+)(\s*)(=)', bygroups(Name.Variable, Text, Operator)),
66 (r'[\[\]{}()=]', Operator), 71 (r'[\[\]{}()=]', Operator),
67 (r'<<<', Operator), # here-string 72 (r'<<<', Operator), # here-string
68 (r'<<-?\s*(\'?)\\?(\w+)[\w\W]+?\2', String), 73 (r'<<-?\s*(\'?)\\?(\w+)[\w\W]+?\2', String),
117 return 1 122 return 1
118 if text.startswith('$ '): 123 if text.startswith('$ '):
119 return 0.2 124 return 0.2
120 125
121 126
122 class BashSessionLexer(Lexer): 127 class ShellSessionBaseLexer(Lexer):
123 """ 128 """
124 Lexer for simplistic shell sessions. 129 Base lexer for simplistic shell sessions.
125 130
126 .. versionadded:: 1.1 131 .. versionadded:: 2.1
127 """ 132 """
128
129 name = 'Bash Session'
130 aliases = ['console']
131 filenames = ['*.sh-session']
132 mimetypes = ['application/x-shell-session']
133
134 def get_tokens_unprocessed(self, text): 133 def get_tokens_unprocessed(self, text):
135 bashlexer = BashLexer(**self.options) 134 innerlexer = self._innerLexerCls(**self.options)
136 135
137 pos = 0 136 pos = 0
138 curcode = '' 137 curcode = ''
139 insertions = [] 138 insertions = []
140 139
141 for match in line_re.finditer(text): 140 for match in line_re.finditer(text):
142 line = match.group() 141 line = match.group()
143 m = re.match(r'^((?:\(\S+\))?(?:|sh\S*?|\w+\S+[@:]\S+(?:\s+\S+)' 142 m = re.match(self._ps1rgx, line)
144 r'?|\[\S+[@:][^\n]+\].+)[$#%])(.*\n?)' , line)
145 if m: 143 if m:
146 # To support output lexers (say diff output), the output 144 # To support output lexers (say diff output), the output
147 # needs to be broken by prompts whenever the output lexer 145 # needs to be broken by prompts whenever the output lexer
148 # changes. 146 # changes.
149 if not insertions: 147 if not insertions:
150 pos = match.start() 148 pos = match.start()
151 149
152 insertions.append((len(curcode), 150 insertions.append((len(curcode),
153 [(0, Generic.Prompt, m.group(1))])) 151 [(0, Generic.Prompt, m.group(1))]))
154 curcode += m.group(2) 152 curcode += m.group(2)
155 elif line.startswith('>'): 153 elif line.startswith(self._ps2):
156 insertions.append((len(curcode), 154 insertions.append((len(curcode),
157 [(0, Generic.Prompt, line[:1])])) 155 [(0, Generic.Prompt, line[:len(self._ps2)])]))
158 curcode += line[1:] 156 curcode += line[len(self._ps2):]
159 else: 157 else:
160 if insertions: 158 if insertions:
161 toks = bashlexer.get_tokens_unprocessed(curcode) 159 toks = innerlexer.get_tokens_unprocessed(curcode)
162 for i, t, v in do_insertions(insertions, toks): 160 for i, t, v in do_insertions(insertions, toks):
163 yield pos+i, t, v 161 yield pos+i, t, v
164 yield match.start(), Generic.Output, line 162 yield match.start(), Generic.Output, line
165 insertions = [] 163 insertions = []
166 curcode = '' 164 curcode = ''
167 if insertions: 165 if insertions:
168 for i, t, v in do_insertions(insertions, 166 for i, t, v in do_insertions(insertions,
169 bashlexer.get_tokens_unprocessed(curcode)): 167 innerlexer.get_tokens_unprocessed(curcode)):
170 yield pos+i, t, v 168 yield pos+i, t, v
171 169
172 170
173 class ShellSessionLexer(Lexer): 171 class BashSessionLexer(ShellSessionBaseLexer):
174 """ 172 """
175 Lexer for shell sessions that works with different command prompts 173 Lexer for simplistic shell sessions.
176 174
177 .. versionadded:: 1.6 175 .. versionadded:: 1.1
178 """ 176 """
179 177
180 name = 'Shell Session' 178 name = 'Bash Session'
181 aliases = ['shell-session'] 179 aliases = ['console', 'shell-session']
182 filenames = ['*.shell-session'] 180 filenames = ['*.sh-session', '*.shell-session']
183 mimetypes = ['application/x-sh-session'] 181 mimetypes = ['application/x-shell-session', 'application/x-sh-session']
184 182
185 def get_tokens_unprocessed(self, text): 183 _innerLexerCls = BashLexer
186 bashlexer = BashLexer(**self.options) 184 _ps1rgx = \
187 185 r'^((?:(?:\[.*?\])|(?:\(\S+\))?(?:| |sh\S*?|\w+\S+[@:]\S+(?:\s+\S+)' \
188 pos = 0 186 r'?|\[\S+[@:][^\n]+\].+))\s*[$#%])(.*\n?)'
189 curcode = '' 187 _ps2 = '>'
190 insertions = []
191
192 for match in line_re.finditer(text):
193 line = match.group()
194 m = re.match(r'^((?:\[?\S+@[^$#%]+\]?\s*)[$#%])(.*\n?)', line)
195 if m:
196 # To support output lexers (say diff output), the output
197 # needs to be broken by prompts whenever the output lexer
198 # changes.
199 if not insertions:
200 pos = match.start()
201
202 insertions.append((len(curcode),
203 [(0, Generic.Prompt, m.group(1))]))
204 curcode += m.group(2)
205 else:
206 if insertions:
207 toks = bashlexer.get_tokens_unprocessed(curcode)
208 for i, t, v in do_insertions(insertions, toks):
209 yield pos+i, t, v
210 yield match.start(), Generic.Output, line
211 insertions = []
212 curcode = ''
213 if insertions:
214 for i, t, v in do_insertions(insertions,
215 bashlexer.get_tokens_unprocessed(curcode)):
216 yield pos+i, t, v
217 188
218 189
219 class BatchLexer(RegexLexer): 190 class BatchLexer(RegexLexer):
220 """ 191 """
221 Lexer for the DOS/Windows Batch file format. 192 Lexer for the DOS/Windows Batch file format.
227 filenames = ['*.bat', '*.cmd'] 198 filenames = ['*.bat', '*.cmd']
228 mimetypes = ['application/x-dos-batch'] 199 mimetypes = ['application/x-dos-batch']
229 200
230 flags = re.MULTILINE | re.IGNORECASE 201 flags = re.MULTILINE | re.IGNORECASE
231 202
203 _nl = r'\n\x1a'
204 _punct = r'&<>|'
205 _ws = r'\t\v\f\r ,;=\xa0'
206 _space = r'(?:(?:(?:\^[%s])?[%s])+)' % (_nl, _ws)
207 _keyword_terminator = (r'(?=(?:\^[%s]?)?[%s+./:[\\\]]|[%s%s(])' %
208 (_nl, _ws, _nl, _punct))
209 _token_terminator = r'(?=\^?[%s]|[%s%s])' % (_ws, _punct, _nl)
210 _start_label = r'((?:(?<=^[^:])|^[^:]?)[%s]*)(:)' % _ws
211 _label = r'(?:(?:[^%s%s%s+:^]|\^[%s]?[\w\W])*)' % (_nl, _punct, _ws, _nl)
212 _label_compound = (r'(?:(?:[^%s%s%s+:^)]|\^[%s]?[^)])*)' %
213 (_nl, _punct, _ws, _nl))
214 _number = r'(?:-?(?:0[0-7]+|0x[\da-f]+|\d+)%s)' % _token_terminator
215 _opword = r'(?:equ|geq|gtr|leq|lss|neq)'
216 _string = r'(?:"[^%s"]*"?)' % _nl
217 _variable = (r'(?:(?:%%(?:\*|(?:~[a-z]*(?:\$[^:]+:)?)?\d|'
218 r'[^%%:%s]+(?::(?:~(?:-?\d+)?(?:,(?:-?\d+)?)?|(?:[^%%%s^]|'
219 r'\^[^%%%s])[^=%s]*=(?:[^%%%s^]|\^[^%%%s])*)?)?%%))|'
220 r'(?:\^?![^!:%s]+(?::(?:~(?:-?\d+)?(?:,(?:-?\d+)?)?|(?:'
221 r'[^!%s^]|\^[^!%s])[^=%s]*=(?:[^!%s^]|\^[^!%s])*)?)?\^?!))' %
222 (_nl, _nl, _nl, _nl, _nl, _nl, _nl, _nl, _nl, _nl, _nl, _nl))
223 _core_token = r'(?:(?:(?:\^[%s]?)?[^%s%s%s])+)' % (_nl, _nl, _punct, _ws)
224 _core_token_compound = r'(?:(?:(?:\^[%s]?)?[^%s%s%s)])+)' % (_nl, _nl,
225 _punct, _ws)
226 _token = r'(?:[%s]+|%s)' % (_punct, _core_token)
227 _token_compound = r'(?:[%s]+|%s)' % (_punct, _core_token_compound)
228 _stoken = (r'(?:[%s]+|(?:%s|%s|%s)+)' %
229 (_punct, _string, _variable, _core_token))
230
231 def _make_begin_state(compound, _core_token=_core_token,
232 _core_token_compound=_core_token_compound,
233 _keyword_terminator=_keyword_terminator,
234 _nl=_nl, _punct=_punct, _string=_string,
235 _space=_space, _start_label=_start_label,
236 _stoken=_stoken, _token_terminator=_token_terminator,
237 _variable=_variable, _ws=_ws):
238 rest = '(?:%s|%s|[^"%%%s%s%s])*' % (_string, _variable, _nl, _punct,
239 ')' if compound else '')
240 rest_of_line = r'(?:(?:[^%s^]|\^[%s]?[\w\W])*)' % (_nl, _nl)
241 rest_of_line_compound = r'(?:(?:[^%s^)]|\^[%s]?[^)])*)' % (_nl, _nl)
242 set_space = r'((?:(?:\^[%s]?)?[^\S\n])*)' % _nl
243 suffix = ''
244 if compound:
245 _keyword_terminator = r'(?:(?=\))|%s)' % _keyword_terminator
246 _token_terminator = r'(?:(?=\))|%s)' % _token_terminator
247 suffix = '/compound'
248 return [
249 ((r'\)', Punctuation, '#pop') if compound else
250 (r'\)((?=\()|%s)%s' % (_token_terminator, rest_of_line),
251 Comment.Single)),
252 (r'(?=%s)' % _start_label, Text, 'follow%s' % suffix),
253 (_space, using(this, state='text')),
254 include('redirect%s' % suffix),
255 (r'[%s]+' % _nl, Text),
256 (r'\(', Punctuation, 'root/compound'),
257 (r'@+', Punctuation),
258 (r'((?:for|if|rem)(?:(?=(?:\^[%s]?)?/)|(?:(?!\^)|'
259 r'(?<=m))(?:(?=\()|%s)))(%s?%s?(?:\^[%s]?)?/(?:\^[%s]?)?\?)' %
260 (_nl, _token_terminator, _space,
261 _core_token_compound if compound else _core_token, _nl, _nl),
262 bygroups(Keyword, using(this, state='text')),
263 'follow%s' % suffix),
264 (r'(goto%s)(%s(?:\^[%s]?)?/(?:\^[%s]?)?\?%s)' %
265 (_keyword_terminator, rest, _nl, _nl, rest),
266 bygroups(Keyword, using(this, state='text')),
267 'follow%s' % suffix),
268 (words(('assoc', 'break', 'cd', 'chdir', 'cls', 'color', 'copy',
269 'date', 'del', 'dir', 'dpath', 'echo', 'endlocal', 'erase',
270 'exit', 'ftype', 'keys', 'md', 'mkdir', 'mklink', 'move',
271 'path', 'pause', 'popd', 'prompt', 'pushd', 'rd', 'ren',
272 'rename', 'rmdir', 'setlocal', 'shift', 'start', 'time',
273 'title', 'type', 'ver', 'verify', 'vol'),
274 suffix=_keyword_terminator), Keyword, 'follow%s' % suffix),
275 (r'(call)(%s?)(:)' % _space,
276 bygroups(Keyword, using(this, state='text'), Punctuation),
277 'call%s' % suffix),
278 (r'call%s' % _keyword_terminator, Keyword),
279 (r'(for%s(?!\^))(%s)(/f%s)' %
280 (_token_terminator, _space, _token_terminator),
281 bygroups(Keyword, using(this, state='text'), Keyword),
282 ('for/f', 'for')),
283 (r'(for%s(?!\^))(%s)(/l%s)' %
284 (_token_terminator, _space, _token_terminator),
285 bygroups(Keyword, using(this, state='text'), Keyword),
286 ('for/l', 'for')),
287 (r'for%s(?!\^)' % _token_terminator, Keyword, ('for2', 'for')),
288 (r'(goto%s)(%s?)(:?)' % (_keyword_terminator, _space),
289 bygroups(Keyword, using(this, state='text'), Punctuation),
290 'label%s' % suffix),
291 (r'(if(?:(?=\()|%s)(?!\^))(%s?)((?:/i%s)?)(%s?)((?:not%s)?)(%s?)' %
292 (_token_terminator, _space, _token_terminator, _space,
293 _token_terminator, _space),
294 bygroups(Keyword, using(this, state='text'), Keyword,
295 using(this, state='text'), Keyword,
296 using(this, state='text')), ('(?', 'if')),
297 (r'rem(((?=\()|%s)%s?%s?.*|%s%s)' %
298 (_token_terminator, _space, _stoken, _keyword_terminator,
299 rest_of_line_compound if compound else rest_of_line),
300 Comment.Single, 'follow%s' % suffix),
301 (r'(set%s)%s(/a)' % (_keyword_terminator, set_space),
302 bygroups(Keyword, using(this, state='text'), Keyword),
303 'arithmetic%s' % suffix),
304 (r'(set%s)%s((?:/p)?)%s((?:(?:(?:\^[%s]?)?[^"%s%s^=%s]|'
305 r'\^[%s]?[^"=])+)?)((?:(?:\^[%s]?)?=)?)' %
306 (_keyword_terminator, set_space, set_space, _nl, _nl, _punct,
307 ')' if compound else '', _nl, _nl),
308 bygroups(Keyword, using(this, state='text'), Keyword,
309 using(this, state='text'), using(this, state='variable'),
310 Punctuation),
311 'follow%s' % suffix),
312 default('follow%s' % suffix)
313 ]
314
315 def _make_follow_state(compound, _label=_label,
316 _label_compound=_label_compound, _nl=_nl,
317 _space=_space, _start_label=_start_label,
318 _token=_token, _token_compound=_token_compound,
319 _ws=_ws):
320 suffix = '/compound' if compound else ''
321 state = []
322 if compound:
323 state.append((r'(?=\))', Text, '#pop'))
324 state += [
325 (r'%s([%s]*)(%s)(.*)' %
326 (_start_label, _ws, _label_compound if compound else _label),
327 bygroups(Text, Punctuation, Text, Name.Label, Comment.Single)),
328 include('redirect%s' % suffix),
329 (r'(?=[%s])' % _nl, Text, '#pop'),
330 (r'\|\|?|&&?', Punctuation, '#pop'),
331 include('text')
332 ]
333 return state
334
335 def _make_arithmetic_state(compound, _nl=_nl, _punct=_punct,
336 _string=_string, _variable=_variable, _ws=_ws):
337 op = r'=+\-*/!~'
338 state = []
339 if compound:
340 state.append((r'(?=\))', Text, '#pop'))
341 state += [
342 (r'0[0-7]+', Number.Oct),
343 (r'0x[\da-f]+', Number.Hex),
344 (r'\d+', Number.Integer),
345 (r'[(),]+', Punctuation),
346 (r'([%s]|%%|\^\^)+' % op, Operator),
347 (r'(%s|%s|(\^[%s]?)?[^()%s%%^"%s%s%s]|\^[%s%s]?%s)+' %
348 (_string, _variable, _nl, op, _nl, _punct, _ws, _nl, _ws,
349 r'[^)]' if compound else r'[\w\W]'),
350 using(this, state='variable')),
351 (r'(?=[\x00|&])', Text, '#pop'),
352 include('follow')
353 ]
354 return state
355
356 def _make_call_state(compound, _label=_label,
357 _label_compound=_label_compound):
358 state = []
359 if compound:
360 state.append((r'(?=\))', Text, '#pop'))
361 state.append((r'(:?)(%s)' % (_label_compound if compound else _label),
362 bygroups(Punctuation, Name.Label), '#pop'))
363 return state
364
365 def _make_label_state(compound, _label=_label,
366 _label_compound=_label_compound, _nl=_nl,
367 _punct=_punct, _string=_string, _variable=_variable):
368 state = []
369 if compound:
370 state.append((r'(?=\))', Text, '#pop'))
371 state.append((r'(%s?)((?:%s|%s|\^[%s]?%s|[^"%%^%s%s%s])*)' %
372 (_label_compound if compound else _label, _string,
373 _variable, _nl, r'[^)]' if compound else r'[\w\W]', _nl,
374 _punct, r')' if compound else ''),
375 bygroups(Name.Label, Comment.Single), '#pop'))
376 return state
377
378 def _make_redirect_state(compound,
379 _core_token_compound=_core_token_compound,
380 _nl=_nl, _punct=_punct, _stoken=_stoken,
381 _string=_string, _space=_space,
382 _variable=_variable, _ws=_ws):
383 stoken_compound = (r'(?:[%s]+|(?:%s|%s|%s)+)' %
384 (_punct, _string, _variable, _core_token_compound))
385 return [
386 (r'((?:(?<=[%s%s])\d)?)(>>?&|<&)([%s%s]*)(\d)' %
387 (_nl, _ws, _nl, _ws),
388 bygroups(Number.Integer, Punctuation, Text, Number.Integer)),
389 (r'((?:(?<=[%s%s])(?<!\^[%s])\d)?)(>>?|<)(%s?%s)' %
390 (_nl, _ws, _nl, _space, stoken_compound if compound else _stoken),
391 bygroups(Number.Integer, Punctuation, using(this, state='text')))
392 ]
393
232 tokens = { 394 tokens = {
233 'root': [ 395 'root': _make_begin_state(False),
234 # Lines can start with @ to prevent echo 396 'follow': _make_follow_state(False),
235 (r'^\s*@', Punctuation), 397 'arithmetic': _make_arithmetic_state(False),
236 (r'^(\s*)(rem\s.*)$', bygroups(Text, Comment)), 398 'call': _make_call_state(False),
237 (r'".*?"', String.Double), 399 'label': _make_label_state(False),
238 (r"'.*?'", String.Single), 400 'redirect': _make_redirect_state(False),
239 # If made more specific, make sure you still allow expansions 401 'root/compound': _make_begin_state(True),
240 # like %~$VAR:zlt 402 'follow/compound': _make_follow_state(True),
241 (r'%%?[~$:\w]+%?', Name.Variable), 403 'arithmetic/compound': _make_arithmetic_state(True),
242 (r'::.*', Comment), # Technically :: only works at BOL 404 'call/compound': _make_call_state(True),
243 (r'\b(set)(\s+)(\w+)', bygroups(Keyword, Text, Name.Variable)), 405 'label/compound': _make_label_state(True),
244 (r'\b(call)(\s+)(:\w+)', bygroups(Keyword, Text, Name.Label)), 406 'redirect/compound': _make_redirect_state(True),
245 (r'\b(goto)(\s+)(\w+)', bygroups(Keyword, Text, Name.Label)), 407 'variable-or-escape': [
246 (r'\b(set|call|echo|on|off|endlocal|for|do|goto|if|pause|' 408 (_variable, Name.Variable),
247 r'setlocal|shift|errorlevel|exist|defined|cmdextversion|' 409 (r'%%%%|\^[%s]?(\^!|[\w\W])' % _nl, String.Escape)
248 r'errorlevel|else|cd|md|del|deltree|cls|choice)\b', Keyword), 410 ],
249 (r'\b(equ|neq|lss|leq|gtr|geq)\b', Operator), 411 'string': [
250 include('basic'), 412 (r'"', String.Double, '#pop'),
251 (r'.', Text), 413 (_variable, Name.Variable),
252 ], 414 (r'\^!|%%', String.Escape),
253 'echo': [ 415 (r'[^"%%^%s]+|[%%^]' % _nl, String.Double),
254 # Escapes only valid within echo args? 416 default('#pop')
255 (r'\^\^|\^<|\^>|\^\|', String.Escape), 417 ],
256 (r'\n', Text, '#pop'), 418 'sqstring': [
257 include('basic'), 419 include('variable-or-escape'),
258 (r'[^\'"^]+', Text), 420 (r'[^%]+|%', String.Single)
259 ], 421 ],
260 'basic': [ 422 'bqstring': [
261 (r'".*?"', String.Double), 423 include('variable-or-escape'),
262 (r"'.*?'", String.Single), 424 (r'[^%]+|%', String.Backtick)
263 (r'`.*?`', String.Backtick), 425 ],
264 (r'-?\d+', Number), 426 'text': [
265 (r',', Punctuation), 427 (r'"', String.Double, 'string'),
266 (r'=', Operator), 428 include('variable-or-escape'),
267 (r'/\S+', Name), 429 (r'[^"%%^%s%s%s\d)]+|.' % (_nl, _punct, _ws), Text)
268 (r':\w+', Name.Label), 430 ],
269 (r'\w:\w+', Text), 431 'variable': [
270 (r'([<>|])(\s*)(\w+)', bygroups(Punctuation, Text, Name)), 432 (r'"', String.Double, 'string'),
271 ], 433 include('variable-or-escape'),
434 (r'[^"%%^%s]+|.' % _nl, Name.Variable)
435 ],
436 'for': [
437 (r'(%s)(in)(%s)(\()' % (_space, _space),
438 bygroups(using(this, state='text'), Keyword,
439 using(this, state='text'), Punctuation), '#pop'),
440 include('follow')
441 ],
442 'for2': [
443 (r'\)', Punctuation),
444 (r'(%s)(do%s)' % (_space, _token_terminator),
445 bygroups(using(this, state='text'), Keyword), '#pop'),
446 (r'[%s]+' % _nl, Text),
447 include('follow')
448 ],
449 'for/f': [
450 (r'(")((?:%s|[^"])*?")([%s%s]*)(\))' % (_variable, _nl, _ws),
451 bygroups(String.Double, using(this, state='string'), Text,
452 Punctuation)),
453 (r'"', String.Double, ('#pop', 'for2', 'string')),
454 (r"('(?:%s|[\w\W])*?')([%s%s]*)(\))" % (_variable, _nl, _ws),
455 bygroups(using(this, state='sqstring'), Text, Punctuation)),
456 (r'(`(?:%s|[\w\W])*?`)([%s%s]*)(\))' % (_variable, _nl, _ws),
457 bygroups(using(this, state='bqstring'), Text, Punctuation)),
458 include('for2')
459 ],
460 'for/l': [
461 (r'-?\d+', Number.Integer),
462 include('for2')
463 ],
464 'if': [
465 (r'((?:cmdextversion|errorlevel)%s)(%s)(\d+)' %
466 (_token_terminator, _space),
467 bygroups(Keyword, using(this, state='text'),
468 Number.Integer), '#pop'),
469 (r'(defined%s)(%s)(%s)' % (_token_terminator, _space, _stoken),
470 bygroups(Keyword, using(this, state='text'),
471 using(this, state='variable')), '#pop'),
472 (r'(exist%s)(%s%s)' % (_token_terminator, _space, _stoken),
473 bygroups(Keyword, using(this, state='text')), '#pop'),
474 (r'(%s%s?)(==)(%s?%s)' % (_stoken, _space, _space, _stoken),
475 bygroups(using(this, state='text'), Operator,
476 using(this, state='text')), '#pop'),
477 (r'(%s%s)(%s)(%s%s)' % (_number, _space, _opword, _space, _number),
478 bygroups(using(this, state='arithmetic'), Operator.Word,
479 using(this, state='arithmetic')), '#pop'),
480 (r'(%s%s)(%s)(%s%s)' % (_stoken, _space, _opword, _space, _stoken),
481 bygroups(using(this, state='text'), Operator.Word,
482 using(this, state='text')), '#pop')
483 ],
484 '(?': [
485 (_space, using(this, state='text')),
486 (r'\(', Punctuation, ('#pop', 'else?', 'root/compound')),
487 default('#pop')
488 ],
489 'else?': [
490 (_space, using(this, state='text')),
491 (r'else%s' % _token_terminator, Keyword, '#pop'),
492 default('#pop')
493 ]
272 } 494 }
495
496
497 class MSDOSSessionLexer(ShellSessionBaseLexer):
498 """
499 Lexer for simplistic MSDOS sessions.
500
501 .. versionadded:: 2.1
502 """
503
504 name = 'MSDOS Session'
505 aliases = ['doscon']
506 filenames = []
507 mimetypes = []
508
509 _innerLexerCls = BatchLexer
510 _ps1rgx = r'^([^>]+>)(.*\n?)'
511 _ps2 = 'More? '
273 512
274 513
275 class TcshLexer(RegexLexer): 514 class TcshLexer(RegexLexer):
276 """ 515 """
277 Lexer for tcsh scripts. 516 Lexer for tcsh scripts.
338 include('root'), 577 include('root'),
339 ], 578 ],
340 } 579 }
341 580
342 581
582 class TcshSessionLexer(ShellSessionBaseLexer):
583 """
584 Lexer for Tcsh sessions.
585
586 .. versionadded:: 2.1
587 """
588
589 name = 'Tcsh Session'
590 aliases = ['tcshcon']
591 filenames = []
592 mimetypes = []
593
594 _innerLexerCls = TcshLexer
595 _ps1rgx = r'^([^>]+>)(.*\n?)'
596 _ps2 = '? '
597
598
343 class PowerShellLexer(RegexLexer): 599 class PowerShellLexer(RegexLexer):
344 """ 600 """
345 For Windows PowerShell code. 601 For Windows PowerShell code.
346 602
347 .. versionadded:: 1.5 603 .. versionadded:: 1.5
348 """ 604 """
349 name = 'PowerShell' 605 name = 'PowerShell'
350 aliases = ['powershell', 'posh', 'ps1', 'psm1'] 606 aliases = ['powershell', 'posh', 'ps1', 'psm1']
351 filenames = ['*.ps1','*.psm1'] 607 filenames = ['*.ps1', '*.psm1']
352 mimetypes = ['text/x-powershell'] 608 mimetypes = ['text/x-powershell']
353 609
354 flags = re.DOTALL | re.IGNORECASE | re.MULTILINE 610 flags = re.DOTALL | re.IGNORECASE | re.MULTILINE
355 611
356 keywords = ( 612 keywords = (
433 (r'\$\(', Punctuation, 'child'), 689 (r'\$\(', Punctuation, 'child'),
434 (r'[^@\n]+"]', String.Heredoc), 690 (r'[^@\n]+"]', String.Heredoc),
435 (r".", String.Heredoc), 691 (r".", String.Heredoc),
436 ] 692 ]
437 } 693 }
694
695
696 class PowerShellSessionLexer(ShellSessionBaseLexer):
697 """
698 Lexer for simplistic Windows PowerShell sessions.
699
700 .. versionadded:: 2.1
701 """
702
703 name = 'PowerShell Session'
704 aliases = ['ps1con']
705 filenames = []
706 mimetypes = []
707
708 _innerLexerCls = PowerShellLexer
709 _ps1rgx = r'^(PS [^>]+> )(.*\n?)'
710 _ps2 = '>> '
711
712
713 class FishShellLexer(RegexLexer):
714 """
715 Lexer for Fish shell scripts.
716
717 .. versionadded:: 2.1
718 """
719
720 name = 'Fish'
721 aliases = ['fish', 'fishshell']
722 filenames = ['*.fish', '*.load']
723 mimetypes = ['application/x-fish']
724
725 tokens = {
726 'root': [
727 include('basic'),
728 include('data'),
729 include('interp'),
730 ],
731 'interp': [
732 (r'\$\(\(', Keyword, 'math'),
733 (r'\(', Keyword, 'paren'),
734 (r'\$#?(\w+|.)', Name.Variable),
735 ],
736 'basic': [
737 (r'\b(begin|end|if|else|while|break|for|in|return|function|block|'
738 r'case|continue|switch|not|and|or|set|echo|exit|pwd|true|false|'
739 r'cd|count|test)(\s*)\b',
740 bygroups(Keyword, Text)),
741 (r'\b(alias|bg|bind|breakpoint|builtin|command|commandline|'
742 r'complete|contains|dirh|dirs|emit|eval|exec|fg|fish|fish_config|'
743 r'fish_indent|fish_pager|fish_prompt|fish_right_prompt|'
744 r'fish_update_completions|fishd|funced|funcsave|functions|help|'
745 r'history|isatty|jobs|math|mimedb|nextd|open|popd|prevd|psub|'
746 r'pushd|random|read|set_color|source|status|trap|type|ulimit|'
747 r'umask|vared|fc|getopts|hash|kill|printf|time|wait)\s*\b(?!\.)',
748 Name.Builtin),
749 (r'#.*\n', Comment),
750 (r'\\[\w\W]', String.Escape),
751 (r'(\b\w+)(\s*)(=)', bygroups(Name.Variable, Text, Operator)),
752 (r'[\[\]()=]', Operator),
753 (r'<<-?\s*(\'?)\\?(\w+)[\w\W]+?\2', String),
754 ],
755 'data': [
756 (r'(?s)\$?"(\\\\|\\[0-7]+|\\.|[^"\\$])*"', String.Double),
757 (r'"', String.Double, 'string'),
758 (r"(?s)\$'(\\\\|\\[0-7]+|\\.|[^'\\])*'", String.Single),
759 (r"(?s)'.*?'", String.Single),
760 (r';', Punctuation),
761 (r'&|\||\^|<|>', Operator),
762 (r'\s+', Text),
763 (r'\d+(?= |\Z)', Number),
764 (r'[^=\s\[\]{}()$"\'`\\<&|;]+', Text),
765 ],
766 'string': [
767 (r'"', String.Double, '#pop'),
768 (r'(?s)(\\\\|\\[0-7]+|\\.|[^"\\$])+', String.Double),
769 include('interp'),
770 ],
771 'paren': [
772 (r'\)', Keyword, '#pop'),
773 include('root'),
774 ],
775 'math': [
776 (r'\)\)', Keyword, '#pop'),
777 (r'[-+*/%^|&]|\*\*|\|\|', Operator),
778 (r'\d+#\d+', Number),
779 (r'\d+#(?! )', Number),
780 (r'\d+', Number),
781 include('root'),
782 ],
783 }

eric ide

mercurial