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