##// END OF EJS Templates
added help line tointeractiveshell.py
michaelpacer -
Show More
@@ -1,452 +1,457 b''
1 """IPython terminal interface using prompt_toolkit"""
1 """IPython terminal interface using prompt_toolkit"""
2 from __future__ import print_function
2 from __future__ import print_function
3
3
4 import os
4 import os
5 import sys
5 import sys
6 from warnings import warn
6 from warnings import warn
7
7
8 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
8 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
9 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
9 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
10 from IPython.utils.terminal import toggle_set_term_title, set_term_title
10 from IPython.utils.terminal import toggle_set_term_title, set_term_title
11 from IPython.utils.process import abbrev_cwd
11 from IPython.utils.process import abbrev_cwd
12 from traitlets import Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum
12 from traitlets import Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum
13
13
14 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
14 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
15 from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
15 from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
16 from prompt_toolkit.history import InMemoryHistory
16 from prompt_toolkit.history import InMemoryHistory
17 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output
17 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output
18 from prompt_toolkit.interface import CommandLineInterface
18 from prompt_toolkit.interface import CommandLineInterface
19 from prompt_toolkit.key_binding.manager import KeyBindingManager
19 from prompt_toolkit.key_binding.manager import KeyBindingManager
20 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
20 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
21 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
21 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
22
22
23 from pygments.styles import get_style_by_name, get_all_styles
23 from pygments.styles import get_style_by_name, get_all_styles
24 from pygments.token import Token
24 from pygments.token import Token
25
25
26 from .debugger import TerminalPdb, Pdb
26 from .debugger import TerminalPdb, Pdb
27 from .magics import TerminalMagics
27 from .magics import TerminalMagics
28 from .pt_inputhooks import get_inputhook_func
28 from .pt_inputhooks import get_inputhook_func
29 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
29 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
30 from .ptutils import IPythonPTCompleter, IPythonPTLexer
30 from .ptutils import IPythonPTCompleter, IPythonPTLexer
31 from .shortcuts import register_ipython_shortcuts
31 from .shortcuts import register_ipython_shortcuts
32
32
33 DISPLAY_BANNER_DEPRECATED = object()
33 DISPLAY_BANNER_DEPRECATED = object()
34
34
35
35
36 from pygments.style import Style
36 from pygments.style import Style
37
37
38 class _NoStyle(Style): pass
38 class _NoStyle(Style): pass
39
39
40
40
41
41
42 _style_overrides_light_bg = {
42 _style_overrides_light_bg = {
43 Token.Prompt: '#0000ff',
43 Token.Prompt: '#0000ff',
44 Token.PromptNum: '#0000ee bold',
44 Token.PromptNum: '#0000ee bold',
45 Token.OutPrompt: '#cc0000',
45 Token.OutPrompt: '#cc0000',
46 Token.OutPromptNum: '#bb0000 bold',
46 Token.OutPromptNum: '#bb0000 bold',
47 }
47 }
48
48
49 _style_overrides_linux = {
49 _style_overrides_linux = {
50 Token.Prompt: '#00cc00',
50 Token.Prompt: '#00cc00',
51 Token.PromptNum: '#00bb00 bold',
51 Token.PromptNum: '#00bb00 bold',
52 Token.OutPrompt: '#cc0000',
52 Token.OutPrompt: '#cc0000',
53 Token.OutPromptNum: '#bb0000 bold',
53 Token.OutPromptNum: '#bb0000 bold',
54 }
54 }
55
55
56
56
57
57
58 def get_default_editor():
58 def get_default_editor():
59 try:
59 try:
60 ed = os.environ['EDITOR']
60 ed = os.environ['EDITOR']
61 if not PY3:
61 if not PY3:
62 ed = ed.decode()
62 ed = ed.decode()
63 return ed
63 return ed
64 except KeyError:
64 except KeyError:
65 pass
65 pass
66 except UnicodeError:
66 except UnicodeError:
67 warn("$EDITOR environment variable is not pure ASCII. Using platform "
67 warn("$EDITOR environment variable is not pure ASCII. Using platform "
68 "default editor.")
68 "default editor.")
69
69
70 if os.name == 'posix':
70 if os.name == 'posix':
71 return 'vi' # the only one guaranteed to be there!
71 return 'vi' # the only one guaranteed to be there!
72 else:
72 else:
73 return 'notepad' # same in Windows!
73 return 'notepad' # same in Windows!
74
74
75
75
76 if sys.stdin and sys.stdout and sys.stderr:
76 if sys.stdin and sys.stdout and sys.stderr:
77 _is_tty = (sys.stdin.isatty()) and (sys.stdout.isatty()) and (sys.stderr.isatty())
77 _is_tty = (sys.stdin.isatty()) and (sys.stdout.isatty()) and (sys.stderr.isatty())
78 else:
78 else:
79 _is_tty = False
79 _is_tty = False
80
80
81
81
82 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
82 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
83
83
84 class TerminalInteractiveShell(InteractiveShell):
84 class TerminalInteractiveShell(InteractiveShell):
85 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
85 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
86 'to reserve for the completion menu'
86 'to reserve for the completion menu'
87 ).tag(config=True)
87 ).tag(config=True)
88
88
89 def _space_for_menu_changed(self, old, new):
89 def _space_for_menu_changed(self, old, new):
90 self._update_layout()
90 self._update_layout()
91
91
92 pt_cli = None
92 pt_cli = None
93 debugger_history = None
93 debugger_history = None
94 _pt_app = None
94 _pt_app = None
95
95
96 simple_prompt = Bool(_use_simple_prompt,
96 simple_prompt = Bool(_use_simple_prompt,
97 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
97 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
98
98
99 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
99 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
100 IPython own testing machinery, and emacs inferior-shell integration through elpy.
100 IPython own testing machinery, and emacs inferior-shell integration through elpy.
101
101
102 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
102 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
103 environment variable is set, or the current terminal is not a tty.
103 environment variable is set, or the current terminal is not a tty.
104
104
105 """
105 """
106 ).tag(config=True)
106 ).tag(config=True)
107
107
108 @property
108 @property
109 def debugger_cls(self):
109 def debugger_cls(self):
110 return Pdb if self.simple_prompt else TerminalPdb
110 return Pdb if self.simple_prompt else TerminalPdb
111
111
112 confirm_exit = Bool(True,
112 confirm_exit = Bool(True,
113 help="""
113 help="""
114 Set to confirm when you try to exit IPython with an EOF (Control-D
114 Set to confirm when you try to exit IPython with an EOF (Control-D
115 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
115 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
116 you can force a direct exit without any confirmation.""",
116 you can force a direct exit without any confirmation.""",
117 ).tag(config=True)
117 ).tag(config=True)
118
118
119 editing_mode = Unicode('emacs',
119 editing_mode = Unicode('emacs',
120 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
120 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
121 ).tag(config=True)
121 ).tag(config=True)
122
122
123 mouse_support = Bool(False,
123 mouse_support = Bool(False,
124 help="Enable mouse support in the prompt"
124 help="Enable mouse support in the prompt"
125 ).tag(config=True)
125 ).tag(config=True)
126
126
127 highlighting_style = Unicode('legacy',
127 highlighting_style = Unicode('legacy',
128 help="The name of a Pygments style to use for syntax highlighting: \n %s" % ', '.join(get_all_styles())
128 help="The name of a Pygments style to use for syntax highlighting: \n %s" % ', '.join(get_all_styles())
129 ).tag(config=True)
129 ).tag(config=True)
130
130
131
131
132 @observe('highlighting_style')
132 @observe('highlighting_style')
133 @observe('colors')
133 @observe('colors')
134 def _highlighting_style_changed(self, change):
134 def _highlighting_style_changed(self, change):
135 self.refresh_style()
135 self.refresh_style()
136
136
137 def refresh_style(self):
137 def refresh_style(self):
138 self._style = self._make_style_from_name(self.highlighting_style)
138 self._style = self._make_style_from_name(self.highlighting_style)
139
139
140
140
141 highlighting_style_overrides = Dict(
141 highlighting_style_overrides = Dict(
142 help="Override highlighting format for specific tokens"
142 help="Override highlighting format for specific tokens"
143 ).tag(config=True)
143 ).tag(config=True)
144
144
145 true_color = Bool(False,
145 true_color = Bool(False,
146 help=("Use 24bit colors instead of 256 colors in prompt highlighting. "
146 help=("Use 24bit colors instead of 256 colors in prompt highlighting. "
147 "If your terminal supports true color, the following command "
147 "If your terminal supports true color, the following command "
148 "should print 'TRUECOLOR' in orange: "
148 "should print 'TRUECOLOR' in orange: "
149 "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"")
149 "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"")
150 ).tag(config=True)
150 ).tag(config=True)
151
151
152 editor = Unicode(get_default_editor(),
152 editor = Unicode(get_default_editor(),
153 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
153 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
154 ).tag(config=True)
154 ).tag(config=True)
155
155
156 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
156 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
157
157
158 prompts = Instance(Prompts)
158 prompts = Instance(Prompts)
159
159
160 @default('prompts')
160 @default('prompts')
161 def _prompts_default(self):
161 def _prompts_default(self):
162 return self.prompts_class(self)
162 return self.prompts_class(self)
163
163
164 @observe('prompts')
164 @observe('prompts')
165 def _(self, change):
165 def _(self, change):
166 self._update_layout()
166 self._update_layout()
167
167
168 @default('displayhook_class')
168 @default('displayhook_class')
169 def _displayhook_class_default(self):
169 def _displayhook_class_default(self):
170 return RichPromptDisplayHook
170 return RichPromptDisplayHook
171
171
172 term_title = Bool(True,
172 term_title = Bool(True,
173 help="Automatically set the terminal title"
173 help="Automatically set the terminal title"
174 ).tag(config=True)
174 ).tag(config=True)
175
175
176 display_completions = Enum(('column', 'multicolumn','readlinelike'), default_value='multicolumn').tag(config=True)
176 display_completions = Enum(('column', 'multicolumn','readlinelike'),
177 help= ( "Options for displaying tab completions, 'column', 'multicolumn', and"
178 "'readlinelike'. These options are for `prompt_toolkit`, see `prompt_toolkit`"
179 "documentation for more information."
180 ),
181 default_value='multicolumn').tag(config=True)
177
182
178 highlight_matching_brackets = Bool(True,
183 highlight_matching_brackets = Bool(True,
179 help="Highlight matching brackets .",
184 help="Highlight matching brackets .",
180 ).tag(config=True)
185 ).tag(config=True)
181
186
182 @observe('term_title')
187 @observe('term_title')
183 def init_term_title(self, change=None):
188 def init_term_title(self, change=None):
184 # Enable or disable the terminal title.
189 # Enable or disable the terminal title.
185 if self.term_title:
190 if self.term_title:
186 toggle_set_term_title(True)
191 toggle_set_term_title(True)
187 set_term_title('IPython: ' + abbrev_cwd())
192 set_term_title('IPython: ' + abbrev_cwd())
188 else:
193 else:
189 toggle_set_term_title(False)
194 toggle_set_term_title(False)
190
195
191 def init_display_formatter(self):
196 def init_display_formatter(self):
192 super(TerminalInteractiveShell, self).init_display_formatter()
197 super(TerminalInteractiveShell, self).init_display_formatter()
193 # terminal only supports plain text
198 # terminal only supports plain text
194 self.display_formatter.active_types = ['text/plain']
199 self.display_formatter.active_types = ['text/plain']
195
200
196 def init_prompt_toolkit_cli(self):
201 def init_prompt_toolkit_cli(self):
197 if self.simple_prompt:
202 if self.simple_prompt:
198 # Fall back to plain non-interactive output for tests.
203 # Fall back to plain non-interactive output for tests.
199 # This is very limited, and only accepts a single line.
204 # This is very limited, and only accepts a single line.
200 def prompt():
205 def prompt():
201 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
206 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
202 self.prompt_for_code = prompt
207 self.prompt_for_code = prompt
203 return
208 return
204
209
205 # Set up keyboard shortcuts
210 # Set up keyboard shortcuts
206 kbmanager = KeyBindingManager.for_prompt()
211 kbmanager = KeyBindingManager.for_prompt()
207 register_ipython_shortcuts(kbmanager.registry, self)
212 register_ipython_shortcuts(kbmanager.registry, self)
208
213
209 # Pre-populate history from IPython's history database
214 # Pre-populate history from IPython's history database
210 history = InMemoryHistory()
215 history = InMemoryHistory()
211 last_cell = u""
216 last_cell = u""
212 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
217 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
213 include_latest=True):
218 include_latest=True):
214 # Ignore blank lines and consecutive duplicates
219 # Ignore blank lines and consecutive duplicates
215 cell = cell.rstrip()
220 cell = cell.rstrip()
216 if cell and (cell != last_cell):
221 if cell and (cell != last_cell):
217 history.append(cell)
222 history.append(cell)
218
223
219 self._style = self._make_style_from_name(self.highlighting_style)
224 self._style = self._make_style_from_name(self.highlighting_style)
220 style = DynamicStyle(lambda: self._style)
225 style = DynamicStyle(lambda: self._style)
221
226
222 editing_mode = getattr(EditingMode, self.editing_mode.upper())
227 editing_mode = getattr(EditingMode, self.editing_mode.upper())
223
228
224 self._pt_app = create_prompt_application(
229 self._pt_app = create_prompt_application(
225 editing_mode=editing_mode,
230 editing_mode=editing_mode,
226 key_bindings_registry=kbmanager.registry,
231 key_bindings_registry=kbmanager.registry,
227 history=history,
232 history=history,
228 completer=IPythonPTCompleter(self.Completer),
233 completer=IPythonPTCompleter(self.Completer),
229 enable_history_search=True,
234 enable_history_search=True,
230 style=style,
235 style=style,
231 mouse_support=self.mouse_support,
236 mouse_support=self.mouse_support,
232 **self._layout_options()
237 **self._layout_options()
233 )
238 )
234 self._eventloop = create_eventloop(self.inputhook)
239 self._eventloop = create_eventloop(self.inputhook)
235 self.pt_cli = CommandLineInterface(
240 self.pt_cli = CommandLineInterface(
236 self._pt_app, eventloop=self._eventloop,
241 self._pt_app, eventloop=self._eventloop,
237 output=create_output(true_color=self.true_color))
242 output=create_output(true_color=self.true_color))
238
243
239 def _make_style_from_name(self, name):
244 def _make_style_from_name(self, name):
240 """
245 """
241 Small wrapper that make an IPython compatible style from a style name
246 Small wrapper that make an IPython compatible style from a style name
242
247
243 We need that to add style for prompt ... etc.
248 We need that to add style for prompt ... etc.
244 """
249 """
245 style_overrides = {}
250 style_overrides = {}
246 if name == 'legacy':
251 if name == 'legacy':
247 legacy = self.colors.lower()
252 legacy = self.colors.lower()
248 if legacy == 'linux':
253 if legacy == 'linux':
249 style_cls = get_style_by_name('monokai')
254 style_cls = get_style_by_name('monokai')
250 style_overrides = _style_overrides_linux
255 style_overrides = _style_overrides_linux
251 elif legacy == 'lightbg':
256 elif legacy == 'lightbg':
252 style_overrides = _style_overrides_light_bg
257 style_overrides = _style_overrides_light_bg
253 style_cls = get_style_by_name('pastie')
258 style_cls = get_style_by_name('pastie')
254 elif legacy == 'neutral':
259 elif legacy == 'neutral':
255 # The default theme needs to be visible on both a dark background
260 # The default theme needs to be visible on both a dark background
256 # and a light background, because we can't tell what the terminal
261 # and a light background, because we can't tell what the terminal
257 # looks like. These tweaks to the default theme help with that.
262 # looks like. These tweaks to the default theme help with that.
258 style_cls = get_style_by_name('default')
263 style_cls = get_style_by_name('default')
259 style_overrides.update({
264 style_overrides.update({
260 Token.Number: '#007700',
265 Token.Number: '#007700',
261 Token.Operator: 'noinherit',
266 Token.Operator: 'noinherit',
262 Token.String: '#BB6622',
267 Token.String: '#BB6622',
263 Token.Name.Function: '#2080D0',
268 Token.Name.Function: '#2080D0',
264 Token.Name.Class: 'bold #2080D0',
269 Token.Name.Class: 'bold #2080D0',
265 Token.Name.Namespace: 'bold #2080D0',
270 Token.Name.Namespace: 'bold #2080D0',
266 Token.Prompt: '#009900',
271 Token.Prompt: '#009900',
267 Token.PromptNum: '#00ff00 bold',
272 Token.PromptNum: '#00ff00 bold',
268 Token.OutPrompt: '#990000',
273 Token.OutPrompt: '#990000',
269 Token.OutPromptNum: '#ff0000 bold',
274 Token.OutPromptNum: '#ff0000 bold',
270 })
275 })
271 elif legacy =='nocolor':
276 elif legacy =='nocolor':
272 style_cls=_NoStyle
277 style_cls=_NoStyle
273 style_overrides = {}
278 style_overrides = {}
274 else :
279 else :
275 raise ValueError('Got unknown colors: ', legacy)
280 raise ValueError('Got unknown colors: ', legacy)
276 else :
281 else :
277 style_cls = get_style_by_name(name)
282 style_cls = get_style_by_name(name)
278 style_overrides = {
283 style_overrides = {
279 Token.Prompt: '#009900',
284 Token.Prompt: '#009900',
280 Token.PromptNum: '#00ff00 bold',
285 Token.PromptNum: '#00ff00 bold',
281 Token.OutPrompt: '#990000',
286 Token.OutPrompt: '#990000',
282 Token.OutPromptNum: '#ff0000 bold',
287 Token.OutPromptNum: '#ff0000 bold',
283 }
288 }
284 style_overrides.update(self.highlighting_style_overrides)
289 style_overrides.update(self.highlighting_style_overrides)
285 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
290 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
286 style_dict=style_overrides)
291 style_dict=style_overrides)
287
292
288 return style
293 return style
289
294
290 def _layout_options(self):
295 def _layout_options(self):
291 """
296 """
292 Return the current layout option for the current Terminal InteractiveShell
297 Return the current layout option for the current Terminal InteractiveShell
293 """
298 """
294 return {
299 return {
295 'lexer':IPythonPTLexer(),
300 'lexer':IPythonPTLexer(),
296 'reserve_space_for_menu':self.space_for_menu,
301 'reserve_space_for_menu':self.space_for_menu,
297 'get_prompt_tokens':self.prompts.in_prompt_tokens,
302 'get_prompt_tokens':self.prompts.in_prompt_tokens,
298 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
303 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
299 'multiline':True,
304 'multiline':True,
300 'display_completions_in_columns': (self.display_completions == 'multicolumn'),
305 'display_completions_in_columns': (self.display_completions == 'multicolumn'),
301
306
302 # Highlight matching brackets, but only when this setting is
307 # Highlight matching brackets, but only when this setting is
303 # enabled, and only when the DEFAULT_BUFFER has the focus.
308 # enabled, and only when the DEFAULT_BUFFER has the focus.
304 'extra_input_processors': [ConditionalProcessor(
309 'extra_input_processors': [ConditionalProcessor(
305 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
310 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
306 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
311 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
307 Condition(lambda cli: self.highlight_matching_brackets))],
312 Condition(lambda cli: self.highlight_matching_brackets))],
308 }
313 }
309
314
310 def _update_layout(self):
315 def _update_layout(self):
311 """
316 """
312 Ask for a re computation of the application layout, if for example ,
317 Ask for a re computation of the application layout, if for example ,
313 some configuration options have changed.
318 some configuration options have changed.
314 """
319 """
315 if self._pt_app:
320 if self._pt_app:
316 self._pt_app.layout = create_prompt_layout(**self._layout_options())
321 self._pt_app.layout = create_prompt_layout(**self._layout_options())
317
322
318 def prompt_for_code(self):
323 def prompt_for_code(self):
319 document = self.pt_cli.run(
324 document = self.pt_cli.run(
320 pre_run=self.pre_prompt, reset_current_buffer=True)
325 pre_run=self.pre_prompt, reset_current_buffer=True)
321 return document.text
326 return document.text
322
327
323 def init_io(self):
328 def init_io(self):
324 if sys.platform not in {'win32', 'cli'}:
329 if sys.platform not in {'win32', 'cli'}:
325 return
330 return
326
331
327 import win_unicode_console
332 import win_unicode_console
328 import colorama
333 import colorama
329
334
330 win_unicode_console.enable()
335 win_unicode_console.enable()
331 colorama.init()
336 colorama.init()
332
337
333 # For some reason we make these wrappers around stdout/stderr.
338 # For some reason we make these wrappers around stdout/stderr.
334 # For now, we need to reset them so all output gets coloured.
339 # For now, we need to reset them so all output gets coloured.
335 # https://github.com/ipython/ipython/issues/8669
340 # https://github.com/ipython/ipython/issues/8669
336 from IPython.utils import io
341 from IPython.utils import io
337 io.stdout = io.IOStream(sys.stdout)
342 io.stdout = io.IOStream(sys.stdout)
338 io.stderr = io.IOStream(sys.stderr)
343 io.stderr = io.IOStream(sys.stderr)
339
344
340 def init_magics(self):
345 def init_magics(self):
341 super(TerminalInteractiveShell, self).init_magics()
346 super(TerminalInteractiveShell, self).init_magics()
342 self.register_magics(TerminalMagics)
347 self.register_magics(TerminalMagics)
343
348
344 def init_alias(self):
349 def init_alias(self):
345 # The parent class defines aliases that can be safely used with any
350 # The parent class defines aliases that can be safely used with any
346 # frontend.
351 # frontend.
347 super(TerminalInteractiveShell, self).init_alias()
352 super(TerminalInteractiveShell, self).init_alias()
348
353
349 # Now define aliases that only make sense on the terminal, because they
354 # Now define aliases that only make sense on the terminal, because they
350 # need direct access to the console in a way that we can't emulate in
355 # need direct access to the console in a way that we can't emulate in
351 # GUI or web frontend
356 # GUI or web frontend
352 if os.name == 'posix':
357 if os.name == 'posix':
353 for cmd in ['clear', 'more', 'less', 'man']:
358 for cmd in ['clear', 'more', 'less', 'man']:
354 self.alias_manager.soft_define_alias(cmd, cmd)
359 self.alias_manager.soft_define_alias(cmd, cmd)
355
360
356
361
357 def __init__(self, *args, **kwargs):
362 def __init__(self, *args, **kwargs):
358 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
363 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
359 self.init_prompt_toolkit_cli()
364 self.init_prompt_toolkit_cli()
360 self.init_term_title()
365 self.init_term_title()
361 self.keep_running = True
366 self.keep_running = True
362
367
363 self.debugger_history = InMemoryHistory()
368 self.debugger_history = InMemoryHistory()
364
369
365 def ask_exit(self):
370 def ask_exit(self):
366 self.keep_running = False
371 self.keep_running = False
367
372
368 rl_next_input = None
373 rl_next_input = None
369
374
370 def pre_prompt(self):
375 def pre_prompt(self):
371 if self.rl_next_input:
376 if self.rl_next_input:
372 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
377 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
373 self.rl_next_input = None
378 self.rl_next_input = None
374
379
375 def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
380 def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
376
381
377 if display_banner is not DISPLAY_BANNER_DEPRECATED:
382 if display_banner is not DISPLAY_BANNER_DEPRECATED:
378 warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
383 warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
379
384
380 while self.keep_running:
385 while self.keep_running:
381 print(self.separate_in, end='')
386 print(self.separate_in, end='')
382
387
383 try:
388 try:
384 code = self.prompt_for_code()
389 code = self.prompt_for_code()
385 except EOFError:
390 except EOFError:
386 if (not self.confirm_exit) \
391 if (not self.confirm_exit) \
387 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
392 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
388 self.ask_exit()
393 self.ask_exit()
389
394
390 else:
395 else:
391 if code:
396 if code:
392 self.run_cell(code, store_history=True)
397 self.run_cell(code, store_history=True)
393
398
394 def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
399 def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
395 # An extra layer of protection in case someone mashing Ctrl-C breaks
400 # An extra layer of protection in case someone mashing Ctrl-C breaks
396 # out of our internal code.
401 # out of our internal code.
397 if display_banner is not DISPLAY_BANNER_DEPRECATED:
402 if display_banner is not DISPLAY_BANNER_DEPRECATED:
398 warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
403 warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
399 while True:
404 while True:
400 try:
405 try:
401 self.interact()
406 self.interact()
402 break
407 break
403 except KeyboardInterrupt:
408 except KeyboardInterrupt:
404 print("\nKeyboardInterrupt escaped interact()\n")
409 print("\nKeyboardInterrupt escaped interact()\n")
405
410
406 if hasattr(self, '_eventloop'):
411 if hasattr(self, '_eventloop'):
407 self._eventloop.close()
412 self._eventloop.close()
408
413
409 _inputhook = None
414 _inputhook = None
410 def inputhook(self, context):
415 def inputhook(self, context):
411 if self._inputhook is not None:
416 if self._inputhook is not None:
412 self._inputhook(context)
417 self._inputhook(context)
413
418
414 def enable_gui(self, gui=None):
419 def enable_gui(self, gui=None):
415 if gui:
420 if gui:
416 self._inputhook = get_inputhook_func(gui)
421 self._inputhook = get_inputhook_func(gui)
417 else:
422 else:
418 self._inputhook = None
423 self._inputhook = None
419
424
420 # Run !system commands directly, not through pipes, so terminal programs
425 # Run !system commands directly, not through pipes, so terminal programs
421 # work correctly.
426 # work correctly.
422 system = InteractiveShell.system_raw
427 system = InteractiveShell.system_raw
423
428
424 def auto_rewrite_input(self, cmd):
429 def auto_rewrite_input(self, cmd):
425 """Overridden from the parent class to use fancy rewriting prompt"""
430 """Overridden from the parent class to use fancy rewriting prompt"""
426 if not self.show_rewritten_input:
431 if not self.show_rewritten_input:
427 return
432 return
428
433
429 tokens = self.prompts.rewrite_prompt_tokens()
434 tokens = self.prompts.rewrite_prompt_tokens()
430 if self.pt_cli:
435 if self.pt_cli:
431 self.pt_cli.print_tokens(tokens)
436 self.pt_cli.print_tokens(tokens)
432 print(cmd)
437 print(cmd)
433 else:
438 else:
434 prompt = ''.join(s for t, s in tokens)
439 prompt = ''.join(s for t, s in tokens)
435 print(prompt, cmd, sep='')
440 print(prompt, cmd, sep='')
436
441
437 _prompts_before = None
442 _prompts_before = None
438 def switch_doctest_mode(self, mode):
443 def switch_doctest_mode(self, mode):
439 """Switch prompts to classic for %doctest_mode"""
444 """Switch prompts to classic for %doctest_mode"""
440 if mode:
445 if mode:
441 self._prompts_before = self.prompts
446 self._prompts_before = self.prompts
442 self.prompts = ClassicPrompts(self)
447 self.prompts = ClassicPrompts(self)
443 elif self._prompts_before:
448 elif self._prompts_before:
444 self.prompts = self._prompts_before
449 self.prompts = self._prompts_before
445 self._prompts_before = None
450 self._prompts_before = None
446 self._update_layout()
451 self._update_layout()
447
452
448
453
449 InteractiveShellABC.register(TerminalInteractiveShell)
454 InteractiveShellABC.register(TerminalInteractiveShell)
450
455
451 if __name__ == '__main__':
456 if __name__ == '__main__':
452 TerminalInteractiveShell.instance().interact()
457 TerminalInteractiveShell.instance().interact()
General Comments 0
You need to be logged in to leave comments. Login now