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