diff options
-rw-r--r-- | pygments/lexers/shell.py | 23 | ||||
-rw-r--r-- | tests/test_shell.py | 52 |
2 files changed, 68 insertions, 7 deletions
diff --git a/pygments/lexers/shell.py b/pygments/lexers/shell.py index df9b56f4..097ca624 100644 --- a/pygments/lexers/shell.py +++ b/pygments/lexers/shell.py @@ -39,12 +39,16 @@ class BashLexer(RegexLexer): tokens = { 'root': [ include('basic'), - (r'\$\(\(', Keyword, 'math'), - (r'\$\(', Keyword, 'paren'), - (r'\${#?', Keyword, 'curly'), (r'`', String.Backtick, 'backticks'), + include('interp'), include('data'), ], + 'interp': [ + (r'\$\(\(', Keyword, 'math'), + (r'\$\(', Keyword, 'paren'), + (r'\${#?', String.Interpol, 'curly'), + (r'\$#?(\w+|.)', Name.Variable), + ], 'basic': [ (r'\b(if|fi|else|while|do|done|for|then|return|function|case|' r'select|continue|until|esac|elif)(\s*)\b', @@ -65,7 +69,8 @@ class BashLexer(RegexLexer): (r'&&|\|\|', Operator), ], 'data': [ - (r'(?s)\$?"(\\\\|\\[0-7]+|\\.|[^"\\])*"', String.Double), + (r'(?s)\$?"(\\\\|\\[0-7]+|\\.|[^"\\$])*"', String.Double), + (r'"', String.Double, 'string'), (r"(?s)\$?'(\\\\|\\[0-7]+|\\.|[^'\\])*'", String.Single), (r';', Punctuation), (r'&', Punctuation), @@ -73,14 +78,18 @@ class BashLexer(RegexLexer): (r'\s+', Text), (r'\d+(?= |\Z)', Number), (r'[^=\s\[\]{}()$"\'`\\<&|;]+', Text), - (r'\$#?(\w+|.)', Name.Variable), (r'<', Text), ], + 'string': [ + (r'"', String.Double, '#pop'), + (r'(\\\\|\\[0-7]+|\\[\w\W]|[^"\\$])+', String.Double), + include('interp'), + ], 'curly': [ - (r'}', Keyword, '#pop'), + (r'}', String.Interpol, '#pop'), (r':-', Keyword), (r'\w+', Name.Variable), - (r'[^}:"\'`$]+', Punctuation), + (r'[^}:"\'`$\\]+', Punctuation), (r':', Punctuation), include('root'), ], diff --git a/tests/test_shell.py b/tests/test_shell.py new file mode 100644 index 00000000..ffcf2a69 --- /dev/null +++ b/tests/test_shell.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +""" + Basic Shell Tests + ~~~~~~~~~~~~~~~~~ + + :copyright: Copyright 2006-2014 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import unittest + +from pygments.token import Token +from pygments.lexers import BashLexer + + +class BashTest(unittest.TestCase): + + def setUp(self): + self.lexer = BashLexer() + self.maxDiff = None + + def testCurlyNoEscapeAndQuotes(self): + fragment = u'echo "${a//["b"]/}"\n' + tokens = [ + (Token.Name.Builtin, u'echo'), + (Token.Text, u' '), + (Token.Literal.String.Double, u'"'), + (Token.Keyword, u'${'), + (Token.Name.Variable, u'a'), + (Token.Punctuation, u'//['), + (Token.Literal.String.Double, u'"b"'), + (Token.Punctuation, u']/'), + (Token.Keyword, u'}'), + (Token.Literal.String.Double, u'"'), + (Token.Text, u'\n'), + ] + self.assertEqual(tokens, list(self.lexer.get_tokens(fragment))) + + def testCurlyWithEscape(self): + fragment = u'echo ${a//[\\"]/}\n' + tokens = [ + (Token.Name.Builtin, u'echo'), + (Token.Text, u' '), + (Token.Keyword, u'${'), + (Token.Name.Variable, u'a'), + (Token.Punctuation, u'//['), + (Token.Literal.String.Escape, u'\\"'), + (Token.Punctuation, u']/'), + (Token.Keyword, u'}'), + (Token.Text, u'\n'), + ] + self.assertEqual(tokens, list(self.lexer.get_tokens(fragment))) |