completion_lexer.py
57 lines
| 2.0 KiB
| text/x-python
|
PythonLexer
epatters
|
r2602 | # System library imports | ||
from pygments.token import Token, is_token_subtype | ||||
class CompletionLexer(object): | ||||
""" Uses Pygments and some auxillary information to lex code snippets for | ||||
symbol contexts. | ||||
""" | ||||
# Maps Lexer names to a list of possible name separators | ||||
separator_map = { 'C' : [ '.', '->' ], | ||||
'C++' : [ '.', '->', '::' ], | ||||
'Python' : [ '.' ] } | ||||
def __init__(self, lexer): | ||||
self.lexer = lexer | ||||
def get_context(self, string): | ||||
""" Assuming the cursor is at the end of the specified string, get the | ||||
context (a list of names) for the symbol at cursor position. | ||||
""" | ||||
context = [] | ||||
reversed_tokens = list(self._lexer.get_tokens(string)) | ||||
reversed_tokens.reverse() | ||||
# Pygments often tacks on a newline when none is specified in the input | ||||
if reversed_tokens and reversed_tokens[0][1].endswith('\n') and \ | ||||
not string.endswith('\n'): | ||||
reversed_tokens.pop(0) | ||||
current_op = unicode() | ||||
for token, text in reversed_tokens: | ||||
if is_token_subtype(token, Token.Name) and \ | ||||
(not context or current_op in self._name_separators): | ||||
if not context and current_op in self._name_separators: | ||||
context.insert(0, unicode()) | ||||
context.insert(0, text) | ||||
current_op = unicode() | ||||
elif token is Token.Operator or token is Token.Punctuation: | ||||
current_op = text + current_op | ||||
else: | ||||
break | ||||
return context | ||||
def get_lexer(self, lexer): | ||||
return self._lexer | ||||
def set_lexer(self, lexer, name_separators=None): | ||||
self._lexer = lexer | ||||
if name_separators is None: | ||||
self._name_separators = self.separator_map.get(lexer.name, ['.']) | ||||
else: | ||||
self._name_separators = list(name_separators) | ||||
lexer = property(get_lexer, set_lexer) | ||||