##// END OF EJS Templates
autoreformat with darker
Matthias Bussonnier -
Show More
@@ -1,653 +1,654 b''
1 1 """IPython terminal interface using prompt_toolkit"""
2 2
3 3 import asyncio
4 4 import os
5 5 import sys
6 6 import warnings
7 7 from warnings import warn
8 8
9 9 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
10 10 from IPython.utils import io
11 11 from IPython.utils.py3compat import input
12 12 from IPython.utils.terminal import toggle_set_term_title, set_term_title, restore_term_title
13 13 from IPython.utils.process import abbrev_cwd
14 14 from traitlets import (
15 15 Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum, Union,
16 16 Any, validate
17 17 )
18 18
19 19 from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
20 20 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
21 21 from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
22 22 from prompt_toolkit.formatted_text import PygmentsTokens
23 23 from prompt_toolkit.history import InMemoryHistory
24 24 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
25 25 from prompt_toolkit.output import ColorDepth
26 26 from prompt_toolkit.patch_stdout import patch_stdout
27 27 from prompt_toolkit.shortcuts import PromptSession, CompleteStyle, print_formatted_text
28 28 from prompt_toolkit.styles import DynamicStyle, merge_styles
29 29 from prompt_toolkit.styles.pygments import style_from_pygments_cls, style_from_pygments_dict
30 30 from prompt_toolkit import __version__ as ptk_version
31 31
32 32 from pygments.styles import get_style_by_name
33 33 from pygments.style import Style
34 34 from pygments.token import Token
35 35
36 36 from .debugger import TerminalPdb, Pdb
37 37 from .magics import TerminalMagics
38 38 from .pt_inputhooks import get_inputhook_name_and_func
39 39 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
40 40 from .ptutils import IPythonPTCompleter, IPythonPTLexer
41 41 from .shortcuts import create_ipython_shortcuts
42 42
43 43 DISPLAY_BANNER_DEPRECATED = object()
44 44 PTK3 = ptk_version.startswith('3.')
45 45
46 46
47 47 class _NoStyle(Style): pass
48 48
49 49
50 50
51 51 _style_overrides_light_bg = {
52 52 Token.Prompt: '#ansibrightblue',
53 53 Token.PromptNum: '#ansiblue bold',
54 54 Token.OutPrompt: '#ansibrightred',
55 55 Token.OutPromptNum: '#ansired bold',
56 56 }
57 57
58 58 _style_overrides_linux = {
59 59 Token.Prompt: '#ansibrightgreen',
60 60 Token.PromptNum: '#ansigreen bold',
61 61 Token.OutPrompt: '#ansibrightred',
62 62 Token.OutPromptNum: '#ansired bold',
63 63 }
64 64
65 65 def get_default_editor():
66 66 try:
67 67 return os.environ['EDITOR']
68 68 except KeyError:
69 69 pass
70 70 except UnicodeError:
71 71 warn("$EDITOR environment variable is not pure ASCII. Using platform "
72 72 "default editor.")
73 73
74 74 if os.name == 'posix':
75 75 return 'vi' # the only one guaranteed to be there!
76 76 else:
77 77 return 'notepad' # same in Windows!
78 78
79 79 # conservatively check for tty
80 80 # overridden streams can result in things like:
81 81 # - sys.stdin = None
82 82 # - no isatty method
83 83 for _name in ('stdin', 'stdout', 'stderr'):
84 84 _stream = getattr(sys, _name)
85 85 if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty():
86 86 _is_tty = False
87 87 break
88 88 else:
89 89 _is_tty = True
90 90
91 91
92 92 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
93 93
94 94 def black_reformat_handler(text_before_cursor):
95 95 import black
96 96 formatted_text = black.format_str(text_before_cursor, mode=black.FileMode())
97 97 if not text_before_cursor.endswith('\n') and formatted_text.endswith('\n'):
98 98 formatted_text = formatted_text[:-1]
99 99 return formatted_text
100 100
101 101
102 102 class TerminalInteractiveShell(InteractiveShell):
103 103 mime_renderers = Dict().tag(config=True)
104 104
105 105 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
106 106 'to reserve for the tab completion menu, '
107 107 'search history, ...etc, the height of '
108 108 'these menus will at most this value. '
109 109 'Increase it is you prefer long and skinny '
110 110 'menus, decrease for short and wide.'
111 111 ).tag(config=True)
112 112
113 113 pt_app = None
114 114 debugger_history = None
115 115
116 116 simple_prompt = Bool(_use_simple_prompt,
117 117 help="""Use `raw_input` for the REPL, without completion and prompt colors.
118 118
119 119 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
120 120 IPython own testing machinery, and emacs inferior-shell integration through elpy.
121 121
122 122 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
123 123 environment variable is set, or the current terminal is not a tty."""
124 124 ).tag(config=True)
125 125
126 126 @property
127 127 def debugger_cls(self):
128 128 return Pdb if self.simple_prompt else TerminalPdb
129 129
130 130 confirm_exit = Bool(True,
131 131 help="""
132 132 Set to confirm when you try to exit IPython with an EOF (Control-D
133 133 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
134 134 you can force a direct exit without any confirmation.""",
135 135 ).tag(config=True)
136 136
137 137 editing_mode = Unicode('emacs',
138 138 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
139 139 ).tag(config=True)
140 140
141 141 emacs_bindings_in_vi_insert_mode = Bool(
142 142 True,
143 143 help="Add shortcuts from 'emacs' insert mode to 'vi' insert mode.",
144 144 ).tag(config=True)
145 145
146 146 autoformatter = Unicode(None,
147 147 help="Autoformatter to reformat Terminal code. Can be `'black'` or `None`",
148 148 allow_none=True
149 149 ).tag(config=True)
150 150
151 151 mouse_support = Bool(False,
152 152 help="Enable mouse support in the prompt\n(Note: prevents selecting text with the mouse)"
153 153 ).tag(config=True)
154 154
155 155 # We don't load the list of styles for the help string, because loading
156 156 # Pygments plugins takes time and can cause unexpected errors.
157 157 highlighting_style = Union([Unicode('legacy'), Type(klass=Style)],
158 158 help="""The name or class of a Pygments style to use for syntax
159 159 highlighting. To see available styles, run `pygmentize -L styles`."""
160 160 ).tag(config=True)
161 161
162 162 @validate('editing_mode')
163 163 def _validate_editing_mode(self, proposal):
164 164 if proposal['value'].lower() == 'vim':
165 165 proposal['value']= 'vi'
166 166 elif proposal['value'].lower() == 'default':
167 167 proposal['value']= 'emacs'
168 168
169 169 if hasattr(EditingMode, proposal['value'].upper()):
170 170 return proposal['value'].lower()
171 171
172 172 return self.editing_mode
173 173
174 174
175 175 @observe('editing_mode')
176 176 def _editing_mode(self, change):
177 177 u_mode = change.new.upper()
178 178 if self.pt_app:
179 179 self.pt_app.editing_mode = u_mode
180 180
181 181 @observe('autoformatter')
182 182 def _autoformatter_changed(self, change):
183 183 formatter = change.new
184 184 if formatter is None:
185 185 self.reformat_handler = lambda x:x
186 186 elif formatter == 'black':
187 187 self.reformat_handler = black_reformat_handler
188 188 else:
189 189 raise ValueError
190 190
191 191 @observe('highlighting_style')
192 192 @observe('colors')
193 193 def _highlighting_style_changed(self, change):
194 194 self.refresh_style()
195 195
196 196 def refresh_style(self):
197 197 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
198 198
199 199
200 200 highlighting_style_overrides = Dict(
201 201 help="Override highlighting format for specific tokens"
202 202 ).tag(config=True)
203 203
204 204 true_color = Bool(False,
205 205 help=("Use 24bit colors instead of 256 colors in prompt highlighting. "
206 206 "If your terminal supports true color, the following command "
207 207 "should print 'TRUECOLOR' in orange: "
208 208 "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"")
209 209 ).tag(config=True)
210 210
211 211 editor = Unicode(get_default_editor(),
212 212 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
213 213 ).tag(config=True)
214 214
215 215 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
216 216
217 217 prompts = Instance(Prompts)
218 218
219 219 @default('prompts')
220 220 def _prompts_default(self):
221 221 return self.prompts_class(self)
222 222
223 223 # @observe('prompts')
224 224 # def _(self, change):
225 225 # self._update_layout()
226 226
227 227 @default('displayhook_class')
228 228 def _displayhook_class_default(self):
229 229 return RichPromptDisplayHook
230 230
231 231 term_title = Bool(True,
232 232 help="Automatically set the terminal title"
233 233 ).tag(config=True)
234 234
235 235 term_title_format = Unicode("IPython: {cwd}",
236 236 help="Customize the terminal title format. This is a python format string. " +
237 237 "Available substitutions are: {cwd}."
238 238 ).tag(config=True)
239 239
240 240 display_completions = Enum(('column', 'multicolumn','readlinelike'),
241 241 help= ( "Options for displaying tab completions, 'column', 'multicolumn', and "
242 242 "'readlinelike'. These options are for `prompt_toolkit`, see "
243 243 "`prompt_toolkit` documentation for more information."
244 244 ),
245 245 default_value='multicolumn').tag(config=True)
246 246
247 247 highlight_matching_brackets = Bool(True,
248 248 help="Highlight matching brackets.",
249 249 ).tag(config=True)
250 250
251 251 extra_open_editor_shortcuts = Bool(False,
252 252 help="Enable vi (v) or Emacs (C-X C-E) shortcuts to open an external editor. "
253 253 "This is in addition to the F2 binding, which is always enabled."
254 254 ).tag(config=True)
255 255
256 256 handle_return = Any(None,
257 257 help="Provide an alternative handler to be called when the user presses "
258 258 "Return. This is an advanced option intended for debugging, which "
259 259 "may be changed or removed in later releases."
260 260 ).tag(config=True)
261 261
262 262 enable_history_search = Bool(True,
263 263 help="Allows to enable/disable the prompt toolkit history search"
264 264 ).tag(config=True)
265 265
266 266 prompt_includes_vi_mode = Bool(True,
267 267 help="Display the current vi mode (when using vi editing mode)."
268 268 ).tag(config=True)
269 269
270 270 @observe('term_title')
271 271 def init_term_title(self, change=None):
272 272 # Enable or disable the terminal title.
273 273 if self.term_title:
274 274 toggle_set_term_title(True)
275 275 set_term_title(self.term_title_format.format(cwd=abbrev_cwd()))
276 276 else:
277 277 toggle_set_term_title(False)
278 278
279 279 def restore_term_title(self):
280 280 if self.term_title:
281 281 restore_term_title()
282 282
283 283 def init_display_formatter(self):
284 284 super(TerminalInteractiveShell, self).init_display_formatter()
285 285 # terminal only supports plain text
286 286 self.display_formatter.active_types = ['text/plain']
287 287 # disable `_ipython_display_`
288 288 self.display_formatter.ipython_display_formatter.enabled = False
289 289
290 290 def init_prompt_toolkit_cli(self):
291 291 if self.simple_prompt:
292 292 # Fall back to plain non-interactive output for tests.
293 293 # This is very limited.
294 294 def prompt():
295 295 prompt_text = "".join(x[1] for x in self.prompts.in_prompt_tokens())
296 296 lines = [input(prompt_text)]
297 297 prompt_continuation = "".join(x[1] for x in self.prompts.continuation_prompt_tokens())
298 298 while self.check_complete('\n'.join(lines))[0] == 'incomplete':
299 299 lines.append( input(prompt_continuation) )
300 300 return '\n'.join(lines)
301 301 self.prompt_for_code = prompt
302 302 return
303 303
304 304 # Set up keyboard shortcuts
305 305 key_bindings = create_ipython_shortcuts(self)
306 306
307 307 # Pre-populate history from IPython's history database
308 308 history = InMemoryHistory()
309 309 last_cell = u""
310 310 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
311 311 include_latest=True):
312 312 # Ignore blank lines and consecutive duplicates
313 313 cell = cell.rstrip()
314 314 if cell and (cell != last_cell):
315 315 history.append_string(cell)
316 316 last_cell = cell
317 317
318 318 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
319 319 self.style = DynamicStyle(lambda: self._style)
320 320
321 321 editing_mode = getattr(EditingMode, self.editing_mode.upper())
322 322
323 323 self.pt_loop = asyncio.new_event_loop()
324 324 self.pt_app = PromptSession(
325 auto_suggest=AutoSuggestFromHistory(),
326 editing_mode=editing_mode,
327 key_bindings=key_bindings,
328 history=history,
329 completer=IPythonPTCompleter(shell=self),
330 enable_history_search = self.enable_history_search,
331 style=self.style,
332 include_default_pygments_style=False,
333 mouse_support=self.mouse_support,
334 enable_open_in_editor=self.extra_open_editor_shortcuts,
335 color_depth=self.color_depth,
336 tempfile_suffix=".py",
337 **self._extra_prompt_options())
325 auto_suggest=AutoSuggestFromHistory(),
326 editing_mode=editing_mode,
327 key_bindings=key_bindings,
328 history=history,
329 completer=IPythonPTCompleter(shell=self),
330 enable_history_search=self.enable_history_search,
331 style=self.style,
332 include_default_pygments_style=False,
333 mouse_support=self.mouse_support,
334 enable_open_in_editor=self.extra_open_editor_shortcuts,
335 color_depth=self.color_depth,
336 tempfile_suffix=".py",
337 **self._extra_prompt_options()
338 )
338 339
339 340 def _make_style_from_name_or_cls(self, name_or_cls):
340 341 """
341 342 Small wrapper that make an IPython compatible style from a style name
342 343
343 344 We need that to add style for prompt ... etc.
344 345 """
345 346 style_overrides = {}
346 347 if name_or_cls == 'legacy':
347 348 legacy = self.colors.lower()
348 349 if legacy == 'linux':
349 350 style_cls = get_style_by_name('monokai')
350 351 style_overrides = _style_overrides_linux
351 352 elif legacy == 'lightbg':
352 353 style_overrides = _style_overrides_light_bg
353 354 style_cls = get_style_by_name('pastie')
354 355 elif legacy == 'neutral':
355 356 # The default theme needs to be visible on both a dark background
356 357 # and a light background, because we can't tell what the terminal
357 358 # looks like. These tweaks to the default theme help with that.
358 359 style_cls = get_style_by_name('default')
359 360 style_overrides.update({
360 361 Token.Number: '#ansigreen',
361 362 Token.Operator: 'noinherit',
362 363 Token.String: '#ansiyellow',
363 364 Token.Name.Function: '#ansiblue',
364 365 Token.Name.Class: 'bold #ansiblue',
365 366 Token.Name.Namespace: 'bold #ansiblue',
366 367 Token.Name.Variable.Magic: '#ansiblue',
367 368 Token.Prompt: '#ansigreen',
368 369 Token.PromptNum: '#ansibrightgreen bold',
369 370 Token.OutPrompt: '#ansired',
370 371 Token.OutPromptNum: '#ansibrightred bold',
371 372 })
372 373
373 374 # Hack: Due to limited color support on the Windows console
374 375 # the prompt colors will be wrong without this
375 376 if os.name == 'nt':
376 377 style_overrides.update({
377 378 Token.Prompt: '#ansidarkgreen',
378 379 Token.PromptNum: '#ansigreen bold',
379 380 Token.OutPrompt: '#ansidarkred',
380 381 Token.OutPromptNum: '#ansired bold',
381 382 })
382 383 elif legacy =='nocolor':
383 384 style_cls=_NoStyle
384 385 style_overrides = {}
385 386 else :
386 387 raise ValueError('Got unknown colors: ', legacy)
387 388 else :
388 389 if isinstance(name_or_cls, str):
389 390 style_cls = get_style_by_name(name_or_cls)
390 391 else:
391 392 style_cls = name_or_cls
392 393 style_overrides = {
393 394 Token.Prompt: '#ansigreen',
394 395 Token.PromptNum: '#ansibrightgreen bold',
395 396 Token.OutPrompt: '#ansired',
396 397 Token.OutPromptNum: '#ansibrightred bold',
397 398 }
398 399 style_overrides.update(self.highlighting_style_overrides)
399 400 style = merge_styles([
400 401 style_from_pygments_cls(style_cls),
401 402 style_from_pygments_dict(style_overrides),
402 403 ])
403 404
404 405 return style
405 406
406 407 @property
407 408 def pt_complete_style(self):
408 409 return {
409 410 'multicolumn': CompleteStyle.MULTI_COLUMN,
410 411 'column': CompleteStyle.COLUMN,
411 412 'readlinelike': CompleteStyle.READLINE_LIKE,
412 413 }[self.display_completions]
413 414
414 415 @property
415 416 def color_depth(self):
416 417 return (ColorDepth.TRUE_COLOR if self.true_color else None)
417 418
418 419 def _extra_prompt_options(self):
419 420 """
420 421 Return the current layout option for the current Terminal InteractiveShell
421 422 """
422 423 def get_message():
423 424 return PygmentsTokens(self.prompts.in_prompt_tokens())
424 425
425 426 if self.editing_mode == 'emacs':
426 427 # with emacs mode the prompt is (usually) static, so we call only
427 428 # the function once. With VI mode it can toggle between [ins] and
428 429 # [nor] so we can't precompute.
429 430 # here I'm going to favor the default keybinding which almost
430 431 # everybody uses to decrease CPU usage.
431 432 # if we have issues with users with custom Prompts we can see how to
432 433 # work around this.
433 434 get_message = get_message()
434 435
435 436 options = {
436 437 'complete_in_thread': False,
437 438 'lexer':IPythonPTLexer(),
438 439 'reserve_space_for_menu':self.space_for_menu,
439 440 'message': get_message,
440 441 'prompt_continuation': (
441 442 lambda width, lineno, is_soft_wrap:
442 443 PygmentsTokens(self.prompts.continuation_prompt_tokens(width))),
443 444 'multiline': True,
444 445 'complete_style': self.pt_complete_style,
445 446
446 447 # Highlight matching brackets, but only when this setting is
447 448 # enabled, and only when the DEFAULT_BUFFER has the focus.
448 449 'input_processors': [ConditionalProcessor(
449 450 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
450 451 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
451 452 Condition(lambda: self.highlight_matching_brackets))],
452 453 }
453 454 if not PTK3:
454 455 options['inputhook'] = self.inputhook
455 456
456 457 return options
457 458
458 459 def prompt_for_code(self):
459 460 if self.rl_next_input:
460 461 default = self.rl_next_input
461 462 self.rl_next_input = None
462 463 else:
463 464 default = ''
464 465
465 466 # In order to make sure that asyncio code written in the
466 467 # interactive shell doesn't interfere with the prompt, we run the
467 468 # prompt in a different event loop.
468 469 # If we don't do this, people could spawn coroutine with a
469 470 # while/true inside which will freeze the prompt.
470 471
471 472 try:
472 473 old_loop = asyncio.get_event_loop()
473 474 except RuntimeError:
474 475 # This happens when the user used `asyncio.run()`.
475 476 old_loop = None
476 477
477 478 asyncio.set_event_loop(self.pt_loop)
478 479 try:
479 480 with patch_stdout(raw=True):
480 481 text = self.pt_app.prompt(
481 482 default=default,
482 483 **self._extra_prompt_options())
483 484 finally:
484 485 # Restore the original event loop.
485 486 asyncio.set_event_loop(old_loop)
486 487
487 488 return text
488 489
489 490 def enable_win_unicode_console(self):
490 491 # Since IPython 7.10 doesn't support python < 3.6 and PEP 528, Python uses the unicode APIs for the Windows
491 492 # console by default, so WUC shouldn't be needed.
492 493 from warnings import warn
493 494 warn("`enable_win_unicode_console` is deprecated since IPython 7.10, does not do anything and will be removed in the future",
494 495 DeprecationWarning,
495 496 stacklevel=2)
496 497
497 498 def init_io(self):
498 499 if sys.platform not in {'win32', 'cli'}:
499 500 return
500 501
501 502 import colorama
502 503 colorama.init()
503 504
504 505 # For some reason we make these wrappers around stdout/stderr.
505 506 # For now, we need to reset them so all output gets coloured.
506 507 # https://github.com/ipython/ipython/issues/8669
507 508 # io.std* are deprecated, but don't show our own deprecation warnings
508 509 # during initialization of the deprecated API.
509 510 with warnings.catch_warnings():
510 511 warnings.simplefilter('ignore', DeprecationWarning)
511 512 io.stdout = io.IOStream(sys.stdout)
512 513 io.stderr = io.IOStream(sys.stderr)
513 514
514 515 def init_magics(self):
515 516 super(TerminalInteractiveShell, self).init_magics()
516 517 self.register_magics(TerminalMagics)
517 518
518 519 def init_alias(self):
519 520 # The parent class defines aliases that can be safely used with any
520 521 # frontend.
521 522 super(TerminalInteractiveShell, self).init_alias()
522 523
523 524 # Now define aliases that only make sense on the terminal, because they
524 525 # need direct access to the console in a way that we can't emulate in
525 526 # GUI or web frontend
526 527 if os.name == 'posix':
527 528 for cmd in ('clear', 'more', 'less', 'man'):
528 529 self.alias_manager.soft_define_alias(cmd, cmd)
529 530
530 531
531 532 def __init__(self, *args, **kwargs):
532 533 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
533 534 self.init_prompt_toolkit_cli()
534 535 self.init_term_title()
535 536 self.keep_running = True
536 537
537 538 self.debugger_history = InMemoryHistory()
538 539
539 540 def ask_exit(self):
540 541 self.keep_running = False
541 542
542 543 rl_next_input = None
543 544
544 545 def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
545 546
546 547 if display_banner is not DISPLAY_BANNER_DEPRECATED:
547 548 warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
548 549
549 550 self.keep_running = True
550 551 while self.keep_running:
551 552 print(self.separate_in, end='')
552 553
553 554 try:
554 555 code = self.prompt_for_code()
555 556 except EOFError:
556 557 if (not self.confirm_exit) \
557 558 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
558 559 self.ask_exit()
559 560
560 561 else:
561 562 if code:
562 563 self.run_cell(code, store_history=True)
563 564
564 565 def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
565 566 # An extra layer of protection in case someone mashing Ctrl-C breaks
566 567 # out of our internal code.
567 568 if display_banner is not DISPLAY_BANNER_DEPRECATED:
568 569 warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
569 570 while True:
570 571 try:
571 572 self.interact()
572 573 break
573 574 except KeyboardInterrupt as e:
574 575 print("\n%s escaped interact()\n" % type(e).__name__)
575 576 finally:
576 577 # An interrupt during the eventloop will mess up the
577 578 # internal state of the prompt_toolkit library.
578 579 # Stopping the eventloop fixes this, see
579 580 # https://github.com/ipython/ipython/pull/9867
580 581 if hasattr(self, '_eventloop'):
581 582 self._eventloop.stop()
582 583
583 584 self.restore_term_title()
584 585
585 586
586 587 _inputhook = None
587 588 def inputhook(self, context):
588 589 if self._inputhook is not None:
589 590 self._inputhook(context)
590 591
591 592 active_eventloop = None
592 593 def enable_gui(self, gui=None):
593 594 if gui and (gui != 'inline') :
594 595 self.active_eventloop, self._inputhook =\
595 596 get_inputhook_name_and_func(gui)
596 597 else:
597 598 self.active_eventloop = self._inputhook = None
598 599
599 600 # For prompt_toolkit 3.0. We have to create an asyncio event loop with
600 601 # this inputhook.
601 602 if PTK3:
602 603 import asyncio
603 604 from prompt_toolkit.eventloop import new_eventloop_with_inputhook
604 605
605 606 if gui == 'asyncio':
606 607 # When we integrate the asyncio event loop, run the UI in the
607 608 # same event loop as the rest of the code. don't use an actual
608 609 # input hook. (Asyncio is not made for nesting event loops.)
609 610 self.pt_loop = asyncio.get_event_loop()
610 611
611 612 elif self._inputhook:
612 613 # If an inputhook was set, create a new asyncio event loop with
613 614 # this inputhook for the prompt.
614 615 self.pt_loop = new_eventloop_with_inputhook(self._inputhook)
615 616 else:
616 617 # When there's no inputhook, run the prompt in a separate
617 618 # asyncio event loop.
618 619 self.pt_loop = asyncio.new_event_loop()
619 620
620 621 # Run !system commands directly, not through pipes, so terminal programs
621 622 # work correctly.
622 623 system = InteractiveShell.system_raw
623 624
624 625 def auto_rewrite_input(self, cmd):
625 626 """Overridden from the parent class to use fancy rewriting prompt"""
626 627 if not self.show_rewritten_input:
627 628 return
628 629
629 630 tokens = self.prompts.rewrite_prompt_tokens()
630 631 if self.pt_app:
631 632 print_formatted_text(PygmentsTokens(tokens), end='',
632 633 style=self.pt_app.app.style)
633 634 print(cmd)
634 635 else:
635 636 prompt = ''.join(s for t, s in tokens)
636 637 print(prompt, cmd, sep='')
637 638
638 639 _prompts_before = None
639 640 def switch_doctest_mode(self, mode):
640 641 """Switch prompts to classic for %doctest_mode"""
641 642 if mode:
642 643 self._prompts_before = self.prompts
643 644 self.prompts = ClassicPrompts(self)
644 645 elif self._prompts_before:
645 646 self.prompts = self._prompts_before
646 647 self._prompts_before = None
647 648 # self._update_layout()
648 649
649 650
650 651 InteractiveShellABC.register(TerminalInteractiveShell)
651 652
652 653 if __name__ == '__main__':
653 654 TerminalInteractiveShell.instance().interact()
General Comments 0
You need to be logged in to leave comments. Login now