##// END OF EJS Templates
* Fixed bug in CompletionLexer where a context would be generated for, e.g, 'foo('....
epatters -
Show More
@@ -13,6 +13,8 b' class CompletionLexer(object):'
13 'Python' : [ '.' ] }
13 'Python' : [ '.' ] }
14
14
15 def __init__(self, lexer):
15 def __init__(self, lexer):
16 """ Create a CompletionLexer using the specified Pygments lexer.
17 """
16 self.lexer = lexer
18 self.lexer = lexer
17
19
18 def get_context(self, string):
20 def get_context(self, string):
@@ -23,21 +25,36 b' class CompletionLexer(object):'
23 reversed_tokens = list(self._lexer.get_tokens(string))
25 reversed_tokens = list(self._lexer.get_tokens(string))
24 reversed_tokens.reverse()
26 reversed_tokens.reverse()
25
27
26 # Pygments often tacks on a newline when none is specified in the input
28 # Pygments often tacks on a newline when none is specified in the input.
29 # Remove this newline.
27 if reversed_tokens and reversed_tokens[0][1].endswith('\n') and \
30 if reversed_tokens and reversed_tokens[0][1].endswith('\n') and \
28 not string.endswith('\n'):
31 not string.endswith('\n'):
29 reversed_tokens.pop(0)
32 reversed_tokens.pop(0)
30
33
31 current_op = unicode()
34 current_op = unicode()
32 for token, text in reversed_tokens:
35 for token, text in reversed_tokens:
33 if is_token_subtype(token, Token.Name) and \
36
34 (not context or current_op in self._name_separators):
37 if is_token_subtype(token, Token.Name):
35 if not context and current_op in self._name_separators:
38
36 context.insert(0, unicode())
39 # Handle a trailing separator, e.g 'foo.bar.'
40 if current_op in self._name_separators:
41 if not context:
42 context.insert(0, unicode())
43
44 # Handle non-separator operators and punction.
45 elif current_op:
46 break
47
37 context.insert(0, text)
48 context.insert(0, text)
38 current_op = unicode()
49 current_op = unicode()
50
51 # Pygments doesn't understand that, e.g., '->' is a single operator
52 # in C++. This is why we have to build up an operator from
53 # potentially several tokens.
39 elif token is Token.Operator or token is Token.Punctuation:
54 elif token is Token.Operator or token is Token.Punctuation:
40 current_op = text + current_op
55 current_op = text + current_op
56
57 # Break on anything that is not a Operator, Punctuation, or Name.
41 else:
58 else:
42 break
59 break
43
60
@@ -15,14 +15,23 b' class TestCompletionLexer(unittest.TestCase):'
15 """
15 """
16 lexer = CompletionLexer(PythonLexer())
16 lexer = CompletionLexer(PythonLexer())
17
17
18 # Test simplest case.
18 self.assertEquals(lexer.get_context("foo.bar.baz"),
19 self.assertEquals(lexer.get_context("foo.bar.baz"),
19 [ "foo", "bar", "baz" ])
20 [ "foo", "bar", "baz" ])
21
22 # Test trailing period.
20 self.assertEquals(lexer.get_context("foo.bar."), [ "foo", "bar", "" ])
23 self.assertEquals(lexer.get_context("foo.bar."), [ "foo", "bar", "" ])
21
24
25 # Test with prompt present.
22 self.assertEquals(lexer.get_context(">>> foo.bar.baz"),
26 self.assertEquals(lexer.get_context(">>> foo.bar.baz"),
23 [ "foo", "bar", "baz" ])
27 [ "foo", "bar", "baz" ])
28
29 # Test spacing in name.
24 self.assertEquals(lexer.get_context("foo.bar. baz"), [ "baz" ])
30 self.assertEquals(lexer.get_context("foo.bar. baz"), [ "baz" ])
25
31
32 # Test parenthesis.
33 self.assertEquals(lexer.get_context("foo("), [])
34
26 def testC(self):
35 def testC(self):
27 """ Does the CompletionLexer work for C/C++?
36 """ Does the CompletionLexer work for C/C++?
28 """
37 """
General Comments 0
You need to be logged in to leave comments. Login now