##// END OF EJS Templates
Pull shortcut definitions out to a separate module
Thomas Kluyver -
Show More
@@ -0,0 +1,165 b''
1 import signal
2 import sys
3
4 from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER
5 from prompt_toolkit.filters import (HasFocus, HasSelection, Condition,
6 ViInsertMode, EmacsInsertMode, HasCompletions)
7 from prompt_toolkit.filters.cli import ViMode
8 from prompt_toolkit.keys import Keys
9 from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline
10
11 @Condition
12 def cursor_in_leading_ws(cli):
13 before = cli.application.buffer.document.current_line_before_cursor
14 return (not before) or before.isspace()
15
16 def register_ipython_shortcuts(registry, shell):
17 """Set up the prompt_toolkit keyboard shortcuts for IPython"""
18 insert_mode = ViInsertMode() | EmacsInsertMode()
19
20 # Ctrl+J == Enter, seemingly
21 registry.add_binding(Keys.ControlJ,
22 filter=(HasFocus(DEFAULT_BUFFER)
23 & ~HasSelection()
24 & insert_mode
25 ))(newline_or_execute_outer(shell))
26
27 registry.add_binding(Keys.ControlP,
28 filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER)
29 ))(previous_history_or_previous_completion)
30
31 registry.add_binding(Keys.ControlN,
32 filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER)
33 ))(next_history_or_next_completion)
34
35 registry.add_binding(Keys.ControlG,
36 filter=(HasFocus(DEFAULT_BUFFER) & HasCompletions()
37 ))(dismiss_completion)
38
39 registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER)
40 )(reset_buffer)
41
42 registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER)
43 )(reset_search_buffer)
44
45 supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP'))
46 registry.add_binding(Keys.ControlZ, filter=supports_suspend
47 )(suspend_to_bg)
48
49 # Ctrl+I == Tab
50 registry.add_binding(Keys.ControlI,
51 filter=(HasFocus(DEFAULT_BUFFER)
52 & ~HasSelection()
53 & insert_mode
54 & cursor_in_leading_ws
55 ))(indent_buffer)
56
57 if shell.display_completions == 'readlinelike':
58 registry.add_binding(Keys.ControlI,
59 filter=(HasFocus(DEFAULT_BUFFER)
60 & ~HasSelection()
61 & insert_mode
62 & ~cursor_in_leading_ws
63 ))(display_completions_like_readline)
64
65 if sys.platform == 'win32':
66 registry.add_binding(Keys.ControlV,
67 filter=(
68 HasFocus(
69 DEFAULT_BUFFER) & ~ViMode()
70 ))(win_paste)
71
72
73 def newline_or_execute_outer(shell):
74 def newline_or_execute(event):
75 """When the user presses return, insert a newline or execute the code."""
76 b = event.current_buffer
77 d = b.document
78
79 if b.complete_state:
80 cc = b.complete_state.current_completion
81 if cc:
82 b.apply_completion(cc)
83 else:
84 b.cancel_completion()
85 return
86
87 if not (d.on_last_line or d.cursor_position_row >= d.line_count
88 - d.empty_line_count_at_the_end()):
89 b.newline()
90 return
91
92 status, indent = shell.input_splitter.check_complete(d.text + '\n')
93
94 if (status != 'incomplete') and b.accept_action.is_returnable:
95 b.accept_action.validate_and_handle(event.cli, b)
96 else:
97 b.insert_text('\n' + (' ' * (indent or 0)))
98 return newline_or_execute
99
100
101 def previous_history_or_previous_completion(event):
102 """
103 Control-P in vi edit mode on readline is history next, unlike default prompt toolkit.
104
105 If completer is open this still select previous completion.
106 """
107 event.current_buffer.auto_up()
108
109
110 def next_history_or_next_completion(event):
111 """
112 Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit.
113
114 If completer is open this still select next completion.
115 """
116 event.current_buffer.auto_down()
117
118
119 def dismiss_completion(event):
120 b = event.current_buffer
121 if b.complete_state:
122 b.cancel_completion()
123
124
125 def reset_buffer(event):
126 b = event.current_buffer
127 if b.complete_state:
128 b.cancel_completion()
129 else:
130 b.reset()
131
132
133 def reset_search_buffer(event):
134 if event.current_buffer.document.text:
135 event.current_buffer.reset()
136 else:
137 event.cli.push_focus(DEFAULT_BUFFER)
138
139 def suspend_to_bg(event):
140 event.cli.suspend_to_background()
141
142 def indent_buffer(event):
143 event.current_buffer.insert_text(' ' * 4)
144
145
146
147
148 if sys.platform == 'win32':
149 from IPython.core.error import TryNext
150 from IPython.lib.clipboard import (ClipboardEmpty,
151 win32_clipboard_get,
152 tkinter_clipboard_get)
153
154
155 def win_paste(event):
156 try:
157 text = win32_clipboard_get()
158 except TryNext:
159 try:
160 text = tkinter_clipboard_get()
161 except (TryNext, ClipboardEmpty):
162 return
163 except ClipboardEmpty:
164 return
165 event.current_buffer.insert_text(text.replace('\t', ' ' * 4))
@@ -1,579 +1,455 b''
1 1 """IPython terminal interface using prompt_toolkit"""
2 2 from __future__ import print_function
3 3
4 4 import os
5 5 import sys
6 import signal
7 6 from warnings import warn
8 7
9 from IPython.core.error import TryNext
10 8 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
11 9 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
12 10 from IPython.utils.terminal import toggle_set_term_title, set_term_title
13 11 from IPython.utils.process import abbrev_cwd
14 12 from traitlets import Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum
15 13
16 from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER, EditingMode
17 from prompt_toolkit.filters import (HasFocus, HasSelection, Condition,
18 ViInsertMode, EmacsInsertMode, IsDone, HasCompletions)
19 from prompt_toolkit.filters.cli import ViMode
14 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
15 from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
20 16 from prompt_toolkit.history import InMemoryHistory
21 17 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout
22 18 from prompt_toolkit.interface import CommandLineInterface
23 19 from prompt_toolkit.key_binding.manager import KeyBindingManager
24 from prompt_toolkit.keys import Keys
25 20 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
26 21 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
27 from prompt_toolkit.key_binding.bindings.completion import display_completions_like_readline
28 22
29 23 from pygments.styles import get_style_by_name, get_all_styles
30 24 from pygments.token import Token
31 25
32 26 from .debugger import TerminalPdb, Pdb
33 27 from .magics import TerminalMagics
34 28 from .pt_inputhooks import get_inputhook_func
35 29 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
36 30 from .ptutils import IPythonPTCompleter, IPythonPTLexer
31 from .shortcuts import register_ipython_shortcuts
37 32
38 33 DISPLAY_BANNER_DEPRECATED = object()
39 34
40 35
41 36 from pygments.style import Style
42 37
43 38 class _NoStyle(Style): pass
44 39
45 40
46 41
47 42 _style_overrides_light_bg = {
48 43 Token.Prompt: '#0000ff',
49 44 Token.PromptNum: '#0000ee bold',
50 45 Token.OutPrompt: '#cc0000',
51 46 Token.OutPromptNum: '#bb0000 bold',
52 47 }
53 48
54 49 _style_overrides_linux = {
55 50 Token.Prompt: '#00cc00',
56 51 Token.PromptNum: '#00bb00 bold',
57 52 Token.OutPrompt: '#cc0000',
58 53 Token.OutPromptNum: '#bb0000 bold',
59 54 }
60 55
61 56
62 57
63 58 def get_default_editor():
64 59 try:
65 60 ed = os.environ['EDITOR']
66 61 if not PY3:
67 62 ed = ed.decode()
68 63 return ed
69 64 except KeyError:
70 65 pass
71 66 except UnicodeError:
72 67 warn("$EDITOR environment variable is not pure ASCII. Using platform "
73 68 "default editor.")
74 69
75 70 if os.name == 'posix':
76 71 return 'vi' # the only one guaranteed to be there!
77 72 else:
78 73 return 'notepad' # same in Windows!
79 74
80 75
81 76 if sys.stdin and sys.stdout and sys.stderr:
82 77 _is_tty = (sys.stdin.isatty()) and (sys.stdout.isatty()) and (sys.stderr.isatty())
83 78 else:
84 79 _is_tty = False
85 80
86 81
87 82 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
88 83
89 84 class TerminalInteractiveShell(InteractiveShell):
90 85 colors_force = True
91 86
92 87 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
93 88 'to reserve for the completion menu'
94 89 ).tag(config=True)
95 90
96 91 def _space_for_menu_changed(self, old, new):
97 92 self._update_layout()
98 93
99 94 pt_cli = None
100 95 debugger_history = None
101 96 _pt_app = None
102 97
103 98 simple_prompt = Bool(_use_simple_prompt,
104 99 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
105 100
106 101 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
107 102 IPython own testing machinery, and emacs inferior-shell integration through elpy.
108 103
109 104 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
110 105 environment variable is set, or the current terminal is not a tty.
111 106
112 107 """
113 108 ).tag(config=True)
114 109
115 110 @property
116 111 def debugger_cls(self):
117 112 return Pdb if self.simple_prompt else TerminalPdb
118 113
119 114 confirm_exit = Bool(True,
120 115 help="""
121 116 Set to confirm when you try to exit IPython with an EOF (Control-D
122 117 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
123 118 you can force a direct exit without any confirmation.""",
124 119 ).tag(config=True)
125 120
126 121 editing_mode = Unicode('emacs',
127 122 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
128 123 ).tag(config=True)
129 124
130 125 mouse_support = Bool(False,
131 126 help="Enable mouse support in the prompt"
132 127 ).tag(config=True)
133 128
134 129 highlighting_style = Unicode('legacy',
135 130 help="The name of a Pygments style to use for syntax highlighting: \n %s" % ', '.join(get_all_styles())
136 131 ).tag(config=True)
137 132
138 133
139 134 @observe('highlighting_style')
140 135 @observe('colors')
141 136 def _highlighting_style_changed(self, change):
142 137 self.refresh_style()
143 138
144 139 def refresh_style(self):
145 140 self._style = self._make_style_from_name(self.highlighting_style)
146 141
147 142
148 143 highlighting_style_overrides = Dict(
149 144 help="Override highlighting format for specific tokens"
150 145 ).tag(config=True)
151 146
152 147 editor = Unicode(get_default_editor(),
153 148 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
154 149 ).tag(config=True)
155 150
156 151 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
157 152
158 153 prompts = Instance(Prompts)
159 154
160 155 @default('prompts')
161 156 def _prompts_default(self):
162 157 return self.prompts_class(self)
163 158
164 159 @observe('prompts')
165 160 def _(self, change):
166 161 self._update_layout()
167 162
168 163 @default('displayhook_class')
169 164 def _displayhook_class_default(self):
170 165 return RichPromptDisplayHook
171 166
172 167 term_title = Bool(True,
173 168 help="Automatically set the terminal title"
174 169 ).tag(config=True)
175 170
176 171 # Leaving that for beta/rc tester, shoudl remove for 5.0.0 final.
177 172 display_completions_in_columns = Bool(None,
178 173 help="DEPRECATED", allow_none=True
179 174 ).tag(config=True)
180 175
181 176 @observe('display_completions_in_columns')
182 177 def _display_completions_in_columns_changed(self, new):
183 178 raise DeprecationWarning("The `display_completions_in_columns` Boolean has been replaced by the enum `display_completions`"
184 179 "with the following acceptable value: 'column', 'multicolumn','readlinelike'. ")
185 180
186 181 display_completions = Enum(('column', 'multicolumn','readlinelike'), default_value='multicolumn').tag(config=True)
187 182
188 183 highlight_matching_brackets = Bool(True,
189 184 help="Highlight matching brackets .",
190 185 ).tag(config=True)
191 186
192 187 @observe('term_title')
193 188 def init_term_title(self, change=None):
194 189 # Enable or disable the terminal title.
195 190 if self.term_title:
196 191 toggle_set_term_title(True)
197 192 set_term_title('IPython: ' + abbrev_cwd())
198 193 else:
199 194 toggle_set_term_title(False)
200 195
201 196 def init_display_formatter(self):
202 197 super(TerminalInteractiveShell, self).init_display_formatter()
203 198 # terminal only supports plain text
204 199 self.display_formatter.active_types = ['text/plain']
205 200
206 201 def init_prompt_toolkit_cli(self):
207 202 if self.simple_prompt:
208 203 # Fall back to plain non-interactive output for tests.
209 204 # This is very limited, and only accepts a single line.
210 205 def prompt():
211 206 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
212 207 self.prompt_for_code = prompt
213 208 return
214 209
210 # Set up keyboard shortcuts
215 211 kbmanager = KeyBindingManager.for_prompt()
216 insert_mode = ViInsertMode() | EmacsInsertMode()
217 # Ctrl+J == Enter, seemingly
218 @kbmanager.registry.add_binding(Keys.ControlJ,
219 filter=(HasFocus(DEFAULT_BUFFER)
220 & ~HasSelection()
221 & insert_mode
222 ))
223 def _(event):
224 b = event.current_buffer
225 d = b.document
226
227 if b.complete_state:
228 cc = b.complete_state.current_completion
229 if cc:
230 b.apply_completion(cc)
231 else:
232 b.cancel_completion()
233 return
234
235 if not (d.on_last_line or d.cursor_position_row >= d.line_count
236 - d.empty_line_count_at_the_end()):
237 b.newline()
238 return
239
240 status, indent = self.input_splitter.check_complete(d.text + '\n')
241
242 if (status != 'incomplete') and b.accept_action.is_returnable:
243 b.accept_action.validate_and_handle(event.cli, b)
244 else:
245 b.insert_text('\n' + (' ' * (indent or 0)))
246
247 @kbmanager.registry.add_binding(Keys.ControlP, filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER)))
248 def _previous_history_or_previous_completion(event):
249 """
250 Control-P in vi edit mode on readline is history next, unlike default prompt toolkit.
251
252 If completer is open this still select previous completion.
253 """
254 event.current_buffer.auto_up()
255
256 @kbmanager.registry.add_binding(Keys.ControlN, filter=(ViInsertMode() & HasFocus(DEFAULT_BUFFER)))
257 def _next_history_or_next_completion(event):
258 """
259 Control-N in vi edit mode on readline is history previous, unlike default prompt toolkit.
260
261 If completer is open this still select next completion.
262 """
263 event.current_buffer.auto_down()
264
265 @kbmanager.registry.add_binding(Keys.ControlG, filter=(
266 HasFocus(DEFAULT_BUFFER) & HasCompletions()
267 ))
268 def _dismiss_completion(event):
269 b = event.current_buffer
270 if b.complete_state:
271 b.cancel_completion()
272
273 @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER))
274 def _reset_buffer(event):
275 b = event.current_buffer
276 if b.complete_state:
277 b.cancel_completion()
278 else:
279 b.reset()
280
281 @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER))
282 def _reset_search_buffer(event):
283 if event.current_buffer.document.text:
284 event.current_buffer.reset()
285 else:
286 event.cli.push_focus(DEFAULT_BUFFER)
287
288 supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP'))
289
290 @kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend)
291 def _suspend_to_bg(event):
292 event.cli.suspend_to_background()
293
294 @Condition
295 def cursor_in_leading_ws(cli):
296 before = cli.application.buffer.document.current_line_before_cursor
297 return (not before) or before.isspace()
298
299 # Ctrl+I == Tab
300 @kbmanager.registry.add_binding(Keys.ControlI,
301 filter=(HasFocus(DEFAULT_BUFFER)
302 & ~HasSelection()
303 & insert_mode
304 & cursor_in_leading_ws
305 ))
306 def _indent_buffer(event):
307 event.current_buffer.insert_text(' ' * 4)
308
309
310 if self.display_completions == 'readlinelike':
311 @kbmanager.registry.add_binding(Keys.ControlI,
312 filter=(HasFocus(DEFAULT_BUFFER)
313 & ~HasSelection()
314 & insert_mode
315 & ~cursor_in_leading_ws
316 ))
317 def _disaply_compl(ev):
318 display_completions_like_readline(ev)
319
320
321 if sys.platform == 'win32':
322 from IPython.lib.clipboard import (ClipboardEmpty,
323 win32_clipboard_get, tkinter_clipboard_get)
324 @kbmanager.registry.add_binding(Keys.ControlV,
325 filter=(HasFocus(DEFAULT_BUFFER) & ~ViMode()))
326 def _paste(event):
327 try:
328 text = win32_clipboard_get()
329 except TryNext:
330 try:
331 text = tkinter_clipboard_get()
332 except (TryNext, ClipboardEmpty):
333 return
334 except ClipboardEmpty:
335 return
336 event.current_buffer.insert_text(text.replace('\t', ' ' * 4))
212 register_ipython_shortcuts(kbmanager.registry, self)
337 213
338 214 # Pre-populate history from IPython's history database
339 215 history = InMemoryHistory()
340 216 last_cell = u""
341 217 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
342 218 include_latest=True):
343 219 # Ignore blank lines and consecutive duplicates
344 220 cell = cell.rstrip()
345 221 if cell and (cell != last_cell):
346 222 history.append(cell)
347 223
348 224 self._style = self._make_style_from_name(self.highlighting_style)
349 225 style = DynamicStyle(lambda: self._style)
350 226
351 227 editing_mode = getattr(EditingMode, self.editing_mode.upper())
352 228
353 229 self._pt_app = create_prompt_application(
354 230 editing_mode=editing_mode,
355 231 key_bindings_registry=kbmanager.registry,
356 232 history=history,
357 233 completer=IPythonPTCompleter(self.Completer),
358 234 enable_history_search=True,
359 235 style=style,
360 236 mouse_support=self.mouse_support,
361 237 **self._layout_options()
362 238 )
363 239 self._eventloop = create_eventloop(self.inputhook)
364 240 self.pt_cli = CommandLineInterface(self._pt_app, eventloop=self._eventloop)
365 241
366 242 def _make_style_from_name(self, name):
367 243 """
368 244 Small wrapper that make an IPython compatible style from a style name
369 245
370 246 We need that to add style for prompt ... etc.
371 247 """
372 248 style_overrides = {}
373 249 if name == 'legacy':
374 250 legacy = self.colors.lower()
375 251 if legacy == 'linux':
376 252 style_cls = get_style_by_name('monokai')
377 253 style_overrides = _style_overrides_linux
378 254 elif legacy == 'lightbg':
379 255 style_overrides = _style_overrides_light_bg
380 256 style_cls = get_style_by_name('pastie')
381 257 elif legacy == 'neutral':
382 258 # The default theme needs to be visible on both a dark background
383 259 # and a light background, because we can't tell what the terminal
384 260 # looks like. These tweaks to the default theme help with that.
385 261 style_cls = get_style_by_name('default')
386 262 style_overrides.update({
387 263 Token.Number: '#007700',
388 264 Token.Operator: 'noinherit',
389 265 Token.String: '#BB6622',
390 266 Token.Name.Function: '#2080D0',
391 267 Token.Name.Class: 'bold #2080D0',
392 268 Token.Name.Namespace: 'bold #2080D0',
393 269 Token.Prompt: '#009900',
394 270 Token.PromptNum: '#00ff00 bold',
395 271 Token.OutPrompt: '#990000',
396 272 Token.OutPromptNum: '#ff0000 bold',
397 273 })
398 274 elif legacy =='nocolor':
399 275 style_cls=_NoStyle
400 276 style_overrides = {}
401 277 else :
402 278 raise ValueError('Got unknown colors: ', legacy)
403 279 else :
404 280 style_cls = get_style_by_name(name)
405 281 style_overrides = {
406 282 Token.Prompt: '#009900',
407 283 Token.PromptNum: '#00ff00 bold',
408 284 Token.OutPrompt: '#990000',
409 285 Token.OutPromptNum: '#ff0000 bold',
410 286 }
411 287 style_overrides.update(self.highlighting_style_overrides)
412 288 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
413 289 style_dict=style_overrides)
414 290
415 291 return style
416 292
417 293 def _layout_options(self):
418 294 """
419 295 Return the current layout option for the current Terminal InteractiveShell
420 296 """
421 297 return {
422 298 'lexer':IPythonPTLexer(),
423 299 'reserve_space_for_menu':self.space_for_menu,
424 300 'get_prompt_tokens':self.prompts.in_prompt_tokens,
425 301 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
426 302 'multiline':True,
427 303 'display_completions_in_columns': (self.display_completions == 'multicolumn'),
428 304
429 305 # Highlight matching brackets, but only when this setting is
430 306 # enabled, and only when the DEFAULT_BUFFER has the focus.
431 307 'extra_input_processors': [ConditionalProcessor(
432 308 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
433 309 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
434 310 Condition(lambda cli: self.highlight_matching_brackets))],
435 311 }
436 312
437 313 def _update_layout(self):
438 314 """
439 315 Ask for a re computation of the application layout, if for example ,
440 316 some configuration options have changed.
441 317 """
442 318 if self._pt_app:
443 319 self._pt_app.layout = create_prompt_layout(**self._layout_options())
444 320
445 321 def prompt_for_code(self):
446 322 document = self.pt_cli.run(
447 323 pre_run=self.pre_prompt, reset_current_buffer=True)
448 324 return document.text
449 325
450 326 def init_io(self):
451 327 if sys.platform not in {'win32', 'cli'}:
452 328 return
453 329
454 330 import win_unicode_console
455 331 import colorama
456 332
457 333 win_unicode_console.enable()
458 334 colorama.init()
459 335
460 336 # For some reason we make these wrappers around stdout/stderr.
461 337 # For now, we need to reset them so all output gets coloured.
462 338 # https://github.com/ipython/ipython/issues/8669
463 339 from IPython.utils import io
464 340 io.stdout = io.IOStream(sys.stdout)
465 341 io.stderr = io.IOStream(sys.stderr)
466 342
467 343 def init_magics(self):
468 344 super(TerminalInteractiveShell, self).init_magics()
469 345 self.register_magics(TerminalMagics)
470 346
471 347 def init_alias(self):
472 348 # The parent class defines aliases that can be safely used with any
473 349 # frontend.
474 350 super(TerminalInteractiveShell, self).init_alias()
475 351
476 352 # Now define aliases that only make sense on the terminal, because they
477 353 # need direct access to the console in a way that we can't emulate in
478 354 # GUI or web frontend
479 355 if os.name == 'posix':
480 356 for cmd in ['clear', 'more', 'less', 'man']:
481 357 self.alias_manager.soft_define_alias(cmd, cmd)
482 358
483 359
484 360 def __init__(self, *args, **kwargs):
485 361 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
486 362 self.init_prompt_toolkit_cli()
487 363 self.init_term_title()
488 364 self.keep_running = True
489 365
490 366 self.debugger_history = InMemoryHistory()
491 367
492 368 def ask_exit(self):
493 369 self.keep_running = False
494 370
495 371 rl_next_input = None
496 372
497 373 def pre_prompt(self):
498 374 if self.rl_next_input:
499 375 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
500 376 self.rl_next_input = None
501 377
502 378 def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
503 379
504 380 if display_banner is not DISPLAY_BANNER_DEPRECATED:
505 381 warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
506 382
507 383 while self.keep_running:
508 384 print(self.separate_in, end='')
509 385
510 386 try:
511 387 code = self.prompt_for_code()
512 388 except EOFError:
513 389 if (not self.confirm_exit) \
514 390 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
515 391 self.ask_exit()
516 392
517 393 else:
518 394 if code:
519 395 self.run_cell(code, store_history=True)
520 396
521 397 def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
522 398 # An extra layer of protection in case someone mashing Ctrl-C breaks
523 399 # out of our internal code.
524 400 if display_banner is not DISPLAY_BANNER_DEPRECATED:
525 401 warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
526 402 while True:
527 403 try:
528 404 self.interact()
529 405 break
530 406 except KeyboardInterrupt:
531 407 print("\nKeyboardInterrupt escaped interact()\n")
532 408
533 409 if hasattr(self, '_eventloop'):
534 410 self._eventloop.close()
535 411
536 412 _inputhook = None
537 413 def inputhook(self, context):
538 414 if self._inputhook is not None:
539 415 self._inputhook(context)
540 416
541 417 def enable_gui(self, gui=None):
542 418 if gui:
543 419 self._inputhook = get_inputhook_func(gui)
544 420 else:
545 421 self._inputhook = None
546 422
547 423 # Run !system commands directly, not through pipes, so terminal programs
548 424 # work correctly.
549 425 system = InteractiveShell.system_raw
550 426
551 427 def auto_rewrite_input(self, cmd):
552 428 """Overridden from the parent class to use fancy rewriting prompt"""
553 429 if not self.show_rewritten_input:
554 430 return
555 431
556 432 tokens = self.prompts.rewrite_prompt_tokens()
557 433 if self.pt_cli:
558 434 self.pt_cli.print_tokens(tokens)
559 435 print(cmd)
560 436 else:
561 437 prompt = ''.join(s for t, s in tokens)
562 438 print(prompt, cmd, sep='')
563 439
564 440 _prompts_before = None
565 441 def switch_doctest_mode(self, mode):
566 442 """Switch prompts to classic for %doctest_mode"""
567 443 if mode:
568 444 self._prompts_before = self.prompts
569 445 self.prompts = ClassicPrompts(self)
570 446 elif self._prompts_before:
571 447 self.prompts = self._prompts_before
572 448 self._prompts_before = None
573 449 self._update_layout()
574 450
575 451
576 452 InteractiveShellABC.register(TerminalInteractiveShell)
577 453
578 454 if __name__ == '__main__':
579 455 TerminalInteractiveShell.instance().interact()
General Comments 0
You need to be logged in to leave comments. Login now