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