##// END OF EJS Templates
Don't try to complete on an empty line
Thomas Kluyver -
Show More
@@ -1,115 +1,118 b''
1 from IPython.core.interactiveshell import InteractiveShell
1 from IPython.core.interactiveshell import InteractiveShell
2
2
3 from prompt_toolkit.completion import Completer, Completion
3 from prompt_toolkit.completion import Completer, Completion
4 from prompt_toolkit.history import InMemoryHistory
4 from prompt_toolkit.history import InMemoryHistory
5 from prompt_toolkit.shortcuts import create_prompt_application
5 from prompt_toolkit.shortcuts import create_prompt_application
6 from prompt_toolkit.interface import CommandLineInterface
6 from prompt_toolkit.interface import CommandLineInterface
7 from prompt_toolkit.key_binding.manager import KeyBindingManager
7 from prompt_toolkit.key_binding.manager import KeyBindingManager
8 from prompt_toolkit.keys import Keys
8 from prompt_toolkit.keys import Keys
9 from prompt_toolkit.layout.lexers import PygmentsLexer
9 from prompt_toolkit.layout.lexers import PygmentsLexer
10 from prompt_toolkit.styles import PygmentsStyle
10 from prompt_toolkit.styles import PygmentsStyle
11
11
12 from pygments.lexers import Python3Lexer
12 from pygments.lexers import Python3Lexer
13 from pygments.token import Token
13 from pygments.token import Token
14
14
15
15
16 class IPythonPTCompleter(Completer):
16 class IPythonPTCompleter(Completer):
17 """Adaptor to provide IPython completions to prompt_toolkit"""
17 """Adaptor to provide IPython completions to prompt_toolkit"""
18 def __init__(self, ipy_completer):
18 def __init__(self, ipy_completer):
19 self.ipy_completer = ipy_completer
19 self.ipy_completer = ipy_completer
20
20
21 def get_completions(self, document, complete_event):
21 def get_completions(self, document, complete_event):
22 if not document.current_line.strip():
23 return
24
22 used, matches = self.ipy_completer.complete(
25 used, matches = self.ipy_completer.complete(
23 line_buffer=document.current_line,
26 line_buffer=document.current_line,
24 cursor_pos=document.cursor_position_col
27 cursor_pos=document.cursor_position_col
25 )
28 )
26 start_pos = -len(used)
29 start_pos = -len(used)
27 for m in matches:
30 for m in matches:
28 yield Completion(m, start_position=start_pos)
31 yield Completion(m, start_position=start_pos)
29
32
30
33
31 class PTInteractiveShell(InteractiveShell):
34 class PTInteractiveShell(InteractiveShell):
32 colors_force = True
35 colors_force = True
33
36
34 pt_cli = None
37 pt_cli = None
35
38
36 def get_prompt_tokens(self, cli):
39 def get_prompt_tokens(self, cli):
37 return [
40 return [
38 (Token.Prompt, 'In ['),
41 (Token.Prompt, 'In ['),
39 (Token.PromptNum, str(self.execution_count)),
42 (Token.PromptNum, str(self.execution_count)),
40 (Token.Prompt, ']: '),
43 (Token.Prompt, ']: '),
41 ]
44 ]
42
45
43
46
44 def init_prompt_toolkit_cli(self):
47 def init_prompt_toolkit_cli(self):
45 kbmanager = KeyBindingManager.for_prompt()
48 kbmanager = KeyBindingManager.for_prompt()
46 @kbmanager.registry.add_binding(Keys.ControlJ) # Ctrl+J == Enter, seemingly
49 @kbmanager.registry.add_binding(Keys.ControlJ) # Ctrl+J == Enter, seemingly
47 def _(event):
50 def _(event):
48 b = event.current_buffer
51 b = event.current_buffer
49 if not b.document.on_last_line:
52 if not b.document.on_last_line:
50 b.newline()
53 b.newline()
51 return
54 return
52
55
53 status, indent = self.input_splitter.check_complete(b.document.text)
56 status, indent = self.input_splitter.check_complete(b.document.text)
54
57
55 if (status != 'incomplete') and b.accept_action.is_returnable:
58 if (status != 'incomplete') and b.accept_action.is_returnable:
56 b.accept_action.validate_and_handle(event.cli, b)
59 b.accept_action.validate_and_handle(event.cli, b)
57 else:
60 else:
58 b.insert_text('\n' + (' ' * (indent or 0)))
61 b.insert_text('\n' + (' ' * (indent or 0)))
59
62
60 @kbmanager.registry.add_binding(Keys.ControlC)
63 @kbmanager.registry.add_binding(Keys.ControlC)
61 def _(event):
64 def _(event):
62 event.current_buffer.reset()
65 event.current_buffer.reset()
63
66
64 # Pre-populate history from IPython's history database
67 # Pre-populate history from IPython's history database
65 history = InMemoryHistory()
68 history = InMemoryHistory()
66 last_cell = u""
69 last_cell = u""
67 for _, _, cell in self.history_manager.get_tail(self.history_load_length,
70 for _, _, cell in self.history_manager.get_tail(self.history_load_length,
68 include_latest=True):
71 include_latest=True):
69 # Ignore blank lines and consecutive duplicates
72 # Ignore blank lines and consecutive duplicates
70 cell = cell.rstrip()
73 cell = cell.rstrip()
71 if cell and (cell != last_cell):
74 if cell and (cell != last_cell):
72 history.append(cell)
75 history.append(cell)
73
76
74 style = PygmentsStyle.from_defaults({
77 style = PygmentsStyle.from_defaults({
75 Token.Prompt: '#009900',
78 Token.Prompt: '#009900',
76 Token.PromptNum: '#00ff00 bold',
79 Token.PromptNum: '#00ff00 bold',
77 Token.Number: '#007700',
80 Token.Number: '#007700',
78 Token.Operator: '#bbbbbb',
81 Token.Operator: '#bbbbbb',
79 })
82 })
80
83
81 app = create_prompt_application(multiline=True,
84 app = create_prompt_application(multiline=True,
82 lexer=PygmentsLexer(Python3Lexer),
85 lexer=PygmentsLexer(Python3Lexer),
83 get_prompt_tokens=self.get_prompt_tokens,
86 get_prompt_tokens=self.get_prompt_tokens,
84 key_bindings_registry=kbmanager.registry,
87 key_bindings_registry=kbmanager.registry,
85 history=history,
88 history=history,
86 completer=IPythonPTCompleter(self.Completer),
89 completer=IPythonPTCompleter(self.Completer),
87 style=style,
90 style=style,
88 )
91 )
89
92
90 self.pt_cli = CommandLineInterface(app)
93 self.pt_cli = CommandLineInterface(app)
91
94
92 def __init__(self, *args, **kwargs):
95 def __init__(self, *args, **kwargs):
93 super(PTInteractiveShell, self).__init__(*args, **kwargs)
96 super(PTInteractiveShell, self).__init__(*args, **kwargs)
94 self.init_prompt_toolkit_cli()
97 self.init_prompt_toolkit_cli()
95 self.keep_running = True
98 self.keep_running = True
96
99
97 def ask_exit(self):
100 def ask_exit(self):
98 self.keep_running = False
101 self.keep_running = False
99
102
100 def interact(self):
103 def interact(self):
101 while self.keep_running:
104 while self.keep_running:
102 print(self.separate_in, end='')
105 print(self.separate_in, end='')
103 try:
106 try:
104 document = self.pt_cli.run()
107 document = self.pt_cli.run()
105 except EOFError:
108 except EOFError:
106 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
109 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
107 self.ask_exit()
110 self.ask_exit()
108
111
109 else:
112 else:
110 if document:
113 if document:
111 self.run_cell(document.text, store_history=True)
114 self.run_cell(document.text, store_history=True)
112
115
113
116
114 if __name__ == '__main__':
117 if __name__ == '__main__':
115 PTInteractiveShell.instance().interact()
118 PTInteractiveShell.instance().interact()
General Comments 0
You need to be logged in to leave comments. Login now