summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pygments/lexers/perl.py24
-rw-r--r--tests/test_perllexer.py22
2 files changed, 35 insertions, 11 deletions
diff --git a/pygments/lexers/perl.py b/pygments/lexers/perl.py
index 52522f58..4d5ab3b3 100644
--- a/pygments/lexers/perl.py
+++ b/pygments/lexers/perl.py
@@ -52,7 +52,7 @@ class PerlLexer(RegexLexer):
(words((
'case', 'continue', 'do', 'else', 'elsif', 'for', 'foreach',
'if', 'last', 'my', 'next', 'our', 'redo', 'reset', 'then',
- 'unless', 'until', 'while', 'use', 'print', 'new', 'BEGIN',
+ 'unless', 'until', 'while', 'print', 'new', 'BEGIN',
'CHECK', 'INIT', 'END', 'return'), suffix=r'\b'),
Keyword),
(r'(format)(\s+)(\w+)(\s*)(=)(\s*\n)',
@@ -94,10 +94,10 @@ class PerlLexer(RegexLexer):
'getservbyport', 'getservent', 'getsockname', 'getsockopt', 'glob', 'gmtime',
'goto', 'grep', 'hex', 'import', 'index', 'int', 'ioctl', 'join', 'keys', 'kill', 'last',
'lc', 'lcfirst', 'length', 'link', 'listen', 'local', 'localtime', 'log', 'lstat',
- 'map', 'mkdir', 'msgctl', 'msgget', 'msgrcv', 'msgsnd', 'my', 'next', 'no', 'oct', 'open',
- 'opendir', 'ord', 'our', 'pack', 'package', 'pipe', 'pop', 'pos', 'printf',
+ 'map', 'mkdir', 'msgctl', 'msgget', 'msgrcv', 'msgsnd', 'my', 'next', 'oct', 'open',
+ 'opendir', 'ord', 'our', 'pack', 'pipe', 'pop', 'pos', 'printf',
'prototype', 'push', 'quotemeta', 'rand', 'read', 'readdir',
- 'readline', 'readlink', 'readpipe', 'recv', 'redo', 'ref', 'rename', 'require',
+ 'readline', 'readlink', 'readpipe', 'recv', 'redo', 'ref', 'rename',
'reverse', 'rewinddir', 'rindex', 'rmdir', 'scalar', 'seek', 'seekdir',
'select', 'semctl', 'semget', 'semop', 'send', 'setgrent', 'sethostent', 'setnetent',
'setpgrp', 'setpriority', 'setprotoent', 'setpwent', 'setservent',
@@ -131,8 +131,14 @@ class PerlLexer(RegexLexer):
(r'(q|qq|qw|qr|qx)\[', String.Other, 'sb-string'),
(r'(q|qq|qw|qr|qx)\<', String.Other, 'lt-string'),
(r'(q|qq|qw|qr|qx)([\W_])(.|\n)*?\2', String.Other),
- (r'package\s+', Keyword, 'modulename'),
- (r'sub\s+', Keyword, 'funcname'),
+ (r'(package)(\s+)([a-zA-Z_]\w*(?:::[a-zA-Z_]\w*)*)',
+ bygroups(Keyword, Text, Name.Namespace)),
+ (r'(use|require|no)(\s+)([a-zA-Z_]\w*(?:::[a-zA-Z_]\w*)*)',
+ bygroups(Keyword, Text, Name.Namespace)),
+ (r'(sub)(\s+)', bygroups(Keyword, Text), 'funcname'),
+ (words((
+ 'no', 'package', 'require', 'use'), suffix=r'\b'),
+ Keyword),
(r'(\[\]|\*\*|::|<<|>>|>=|<=>|<=|={3}|!=|=~|'
r'!~|&&?|\|\||\.{1,3})', Operator),
(r'[-+/*%=<>&^|!\\~]=?', Operator),
@@ -152,14 +158,12 @@ class PerlLexer(RegexLexer):
(r'[\w:]+', Name.Variable, '#pop'),
],
'name': [
- (r'\w+::', Name.Namespace),
+ (r'[a-zA-Z_]\w*(::[a-zA-Z_]\w*)*(::)?(?=\s*->)', Name.Namespace, '#pop'),
+ (r'[a-zA-Z_]\w*(::[a-zA-Z_]\w*)*::', Name.Namespace, '#pop'),
(r'[\w:]+', Name, '#pop'),
(r'[A-Z_]+(?=\W)', Name.Constant, '#pop'),
(r'(?=\W)', Text, '#pop'),
],
- 'modulename': [
- (r'[a-zA-Z_]\w*', Name.Namespace, '#pop')
- ],
'funcname': [
(r'[a-zA-Z_]\w*[!?]?', Name.Function),
(r'\s+', Text),
diff --git a/tests/test_perllexer.py b/tests/test_perllexer.py
index 2fcaae7e..102f0a9f 100644
--- a/tests/test_perllexer.py
+++ b/tests/test_perllexer.py
@@ -10,7 +10,7 @@
import time
import unittest
-from pygments.token import String
+from pygments.token import Keyword, Name, String, Text
from pygments.lexers.perl import PerlLexer
@@ -135,3 +135,23 @@ class RunawayRegexTest(unittest.TestCase):
def test_substitution_with_parenthesis(self):
self.assert_single_token(r's(aaa)', String.Regex)
self.assert_fast_tokenization('s(' + '\\'*999)
+
+ ### Namespaces/modules
+
+ def test_package_statement(self):
+ self.assert_tokens(['package', ' ', 'Foo'], [Keyword, Text, Name.Namespace])
+ self.assert_tokens(['package', ' ', 'Foo::Bar'], [Keyword, Text, Name.Namespace])
+
+ def test_use_statement(self):
+ self.assert_tokens(['use', ' ', 'Foo'], [Keyword, Text, Name.Namespace])
+ self.assert_tokens(['use', ' ', 'Foo::Bar'], [Keyword, Text, Name.Namespace])
+
+ def test_no_statement(self):
+ self.assert_tokens(['no', ' ', 'Foo'], [Keyword, Text, Name.Namespace])
+ self.assert_tokens(['no', ' ', 'Foo::Bar'], [Keyword, Text, Name.Namespace])
+
+ def test_require_statement(self):
+ self.assert_tokens(['require', ' ', 'Foo'], [Keyword, Text, Name.Namespace])
+ self.assert_tokens(['require', ' ', 'Foo::Bar'], [Keyword, Text, Name.Namespace])
+ self.assert_tokens(['require', ' ', '"Foo/Bar.pm"'], [Keyword, Text, String])
+