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