##// END OF EJS Templates
explicit TypeError when IPCompleter passed to PTCompleter
Min RK -
Show More
@@ -1,92 +1,96 b''
1 1 import unicodedata
2 2 from wcwidth import wcwidth
3 3
4 4 from IPython.utils.py3compat import PY3
5 5
6 from IPython.core.completer import IPCompleter
6 7 from prompt_toolkit.completion import Completer, Completion
7 8 from prompt_toolkit.layout.lexers import Lexer
8 9 from prompt_toolkit.layout.lexers import PygmentsLexer
9 10
10 11 import pygments.lexers as pygments_lexers
11 12
12 13
13 14 class IPythonPTCompleter(Completer):
14 15 """Adaptor to provide IPython completions to prompt_toolkit"""
15 16 def __init__(self, shell):
17 if isinstance(shell, IPCompleter):
18 raise TypeError("IPythonPTCompleter expects an InteractiveShell"
19 " instance in IPython 5.1, not a Completer")
16 20 self.shell = shell
17
21
18 22 @property
19 23 def ipy_completer(self):
20 24 return self.shell.Completer
21 25
22 26 def get_completions(self, document, complete_event):
23 27 if not document.current_line.strip():
24 28 return
25 29
26 30 used, matches = self.ipy_completer.complete(
27 31 line_buffer=document.current_line,
28 32 cursor_pos=document.cursor_position_col
29 33 )
30 34 start_pos = -len(used)
31 35 for m in matches:
32 36 if not m:
33 37 # Guard against completion machinery giving us an empty string.
34 38 continue
35 39
36 40 m = unicodedata.normalize('NFC', m)
37 41
38 42 # When the first character of the completion has a zero length,
39 43 # then it's probably a decomposed unicode character. E.g. caused by
40 44 # the "\dot" completion. Try to compose again with the previous
41 45 # character.
42 46 if wcwidth(m[0]) == 0:
43 47 if document.cursor_position + start_pos > 0:
44 48 char_before = document.text[document.cursor_position + start_pos - 1]
45 49 m = unicodedata.normalize('NFC', char_before + m)
46 50
47 51 # Yield the modified completion instead, if this worked.
48 52 if wcwidth(m[0:1]) == 1:
49 53 yield Completion(m, start_position=start_pos - 1)
50 54 continue
51 55
52 56 # TODO: Use Jedi to determine meta_text
53 57 # (Jedi currently has a bug that results in incorrect information.)
54 58 # meta_text = ''
55 59 # yield Completion(m, start_position=start_pos,
56 60 # display_meta=meta_text)
57 61 yield Completion(m, start_position=start_pos)
58 62
59 63 class IPythonPTLexer(Lexer):
60 64 """
61 65 Wrapper around PythonLexer and BashLexer.
62 66 """
63 67 def __init__(self):
64 68 l = pygments_lexers
65 69 self.python_lexer = PygmentsLexer(l.Python3Lexer if PY3 else l.PythonLexer)
66 70 self.shell_lexer = PygmentsLexer(l.BashLexer)
67 71
68 72 self.magic_lexers = {
69 73 'HTML': PygmentsLexer(l.HtmlLexer),
70 74 'html': PygmentsLexer(l.HtmlLexer),
71 75 'javascript': PygmentsLexer(l.JavascriptLexer),
72 76 'js': PygmentsLexer(l.JavascriptLexer),
73 77 'perl': PygmentsLexer(l.PerlLexer),
74 78 'ruby': PygmentsLexer(l.RubyLexer),
75 79 'latex': PygmentsLexer(l.TexLexer),
76 80 }
77 81
78 82 def lex_document(self, cli, document):
79 83 text = document.text.lstrip()
80 84
81 85 lexer = self.python_lexer
82 86
83 87 if text.startswith('!') or text.startswith('%%bash'):
84 88 lexer = self.shell_lexer
85 89
86 90 elif text.startswith('%%'):
87 91 for magic, l in self.magic_lexers.items():
88 92 if text.startswith('%%' + magic):
89 93 lexer = l
90 94 break
91 95
92 96 return lexer.lex_document(cli, document)
General Comments 0
You need to be logged in to leave comments. Login now