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