##// END OF EJS Templates
Fix greedy completion for qtconsole
Martin Bergtholdt -
Show More
@@ -1,74 +1,79 b''
1 1 # System library imports
2 2 from pygments.token import Token, is_token_subtype
3 3
4 4
5 5 class CompletionLexer(object):
6 6 """ Uses Pygments and some auxillary information to lex code snippets for
7 7 symbol contexts.
8 8 """
9 9
10 10 # Maps Lexer names to a list of possible name separators
11 11 separator_map = { 'C' : [ '.', '->' ],
12 12 'C++' : [ '.', '->', '::' ],
13 13 'Python' : [ '.' ] }
14 14
15 15 def __init__(self, lexer):
16 16 """ Create a CompletionLexer using the specified Pygments lexer.
17 17 """
18 18 self.lexer = lexer
19 19
20 20 def get_context(self, string):
21 21 """ Assuming the cursor is at the end of the specified string, get the
22 22 context (a list of names) for the symbol at cursor position.
23 23 """
24 24 context = []
25 25 reversed_tokens = list(self._lexer.get_tokens(string))
26 26 reversed_tokens.reverse()
27 27
28 28 # Pygments often tacks on a newline when none is specified in the input.
29 29 # Remove this newline.
30 30 if reversed_tokens and reversed_tokens[0][1].endswith('\n') and \
31 31 not string.endswith('\n'):
32 32 reversed_tokens.pop(0)
33 33
34 34 current_op = ''
35 35 for token, text in reversed_tokens:
36 36
37 37 if is_token_subtype(token, Token.Name):
38 38
39 39 # Handle a trailing separator, e.g 'foo.bar.'
40 40 if current_op in self._name_separators:
41 41 if not context:
42 42 context.insert(0, '')
43 43
44 44 # Handle non-separator operators and punction.
45 45 elif current_op:
46 46 break
47 47
48 48 context.insert(0, text)
49 49 current_op = ''
50 50
51 51 # Pygments doesn't understand that, e.g., '->' is a single operator
52 52 # in C++. This is why we have to build up an operator from
53 53 # potentially several tokens.
54 54 elif token is Token.Operator or token is Token.Punctuation:
55 # Handle a trailing separator, e.g 'foo.bar.'
56 if current_op in self._name_separators:
57 if not context:
58 context.insert(0, '')
59 else:
55 60 current_op = text + current_op
56 61
57 62 # Break on anything that is not a Operator, Punctuation, or Name.
58 63 else:
59 64 break
60 65
61 66 return context
62 67
63 68 def get_lexer(self, lexer):
64 69 return self._lexer
65 70
66 71 def set_lexer(self, lexer, name_separators=None):
67 72 self._lexer = lexer
68 73 if name_separators is None:
69 74 self._name_separators = self.separator_map.get(lexer.name, ['.'])
70 75 else:
71 76 self._name_separators = list(name_separators)
72 77
73 78 lexer = property(get_lexer, set_lexer)
74 79
General Comments 0
You need to be logged in to leave comments. Login now