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