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