##// END OF EJS Templates
Simplify code with a context manager
Thomas Kluyver -
Show More
@@ -1,390 +1,387 b''
1 """IPython terminal interface using prompt_toolkit in place of readline"""
1 """IPython terminal interface using prompt_toolkit in place of readline"""
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 import signal
6 import signal
7 from warnings import warn
7 from warnings import warn
8
8
9 from IPython.core.error import TryNext
9 from IPython.core.error import TryNext
10 from IPython.core.interactiveshell import InteractiveShell
10 from IPython.core.interactiveshell import InteractiveShell
11 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
11 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
12 from IPython.utils.terminal import toggle_set_term_title, set_term_title
12 from IPython.utils.terminal import toggle_set_term_title, set_term_title
13 from IPython.utils.process import abbrev_cwd
13 from IPython.utils.process import abbrev_cwd
14 from traitlets import Bool, CBool, Unicode, Dict
14 from traitlets import Bool, CBool, Unicode, Dict
15
15
16 from prompt_toolkit.completion import Completer, Completion
16 from prompt_toolkit.completion import Completer, Completion
17 from prompt_toolkit.enums import DEFAULT_BUFFER
17 from prompt_toolkit.enums import DEFAULT_BUFFER
18 from prompt_toolkit.filters import HasFocus, HasSelection, Condition
18 from prompt_toolkit.filters import HasFocus, HasSelection, Condition
19 from prompt_toolkit.history import InMemoryHistory
19 from prompt_toolkit.history import InMemoryHistory
20 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop
20 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop
21 from prompt_toolkit.interface import CommandLineInterface
21 from prompt_toolkit.interface import CommandLineInterface
22 from prompt_toolkit.key_binding.manager import KeyBindingManager
22 from prompt_toolkit.key_binding.manager import KeyBindingManager
23 from prompt_toolkit.key_binding.vi_state import InputMode
23 from prompt_toolkit.key_binding.vi_state import InputMode
24 from prompt_toolkit.key_binding.bindings.vi import ViStateFilter
24 from prompt_toolkit.key_binding.bindings.vi import ViStateFilter
25 from prompt_toolkit.keys import Keys
25 from prompt_toolkit.keys import Keys
26 from prompt_toolkit.layout.lexers import Lexer
26 from prompt_toolkit.layout.lexers import Lexer
27 from prompt_toolkit.layout.lexers import PygmentsLexer
27 from prompt_toolkit.layout.lexers import PygmentsLexer
28 from prompt_toolkit.styles import PygmentsStyle
28 from prompt_toolkit.styles import PygmentsStyle
29
29
30 from pygments.styles import get_style_by_name
30 from pygments.styles import get_style_by_name
31 from pygments.lexers import Python3Lexer, BashLexer, PythonLexer
31 from pygments.lexers import Python3Lexer, BashLexer, PythonLexer
32 from pygments.token import Token
32 from pygments.token import Token
33
33
34 from .pt_inputhooks import get_inputhook_func
34 from .pt_inputhooks import get_inputhook_func
35 from .interactiveshell import get_default_editor, TerminalMagics
35 from .interactiveshell import get_default_editor, TerminalMagics
36
36
37
37
38
38
39 class IPythonPTCompleter(Completer):
39 class IPythonPTCompleter(Completer):
40 """Adaptor to provide IPython completions to prompt_toolkit"""
40 """Adaptor to provide IPython completions to prompt_toolkit"""
41 def __init__(self, ipy_completer):
41 def __init__(self, ipy_completer):
42 self.ipy_completer = ipy_completer
42 self.ipy_completer = ipy_completer
43
43
44 def get_completions(self, document, complete_event):
44 def get_completions(self, document, complete_event):
45 if not document.current_line.strip():
45 if not document.current_line.strip():
46 return
46 return
47
47
48 used, matches = self.ipy_completer.complete(
48 used, matches = self.ipy_completer.complete(
49 line_buffer=document.current_line,
49 line_buffer=document.current_line,
50 cursor_pos=document.cursor_position_col
50 cursor_pos=document.cursor_position_col
51 )
51 )
52 start_pos = -len(used)
52 start_pos = -len(used)
53 for m in matches:
53 for m in matches:
54 yield Completion(m, start_position=start_pos)
54 yield Completion(m, start_position=start_pos)
55
55
56
56
57 class IPythonPTLexer(Lexer):
57 class IPythonPTLexer(Lexer):
58 """
58 """
59 Wrapper around PythonLexer and BashLexer.
59 Wrapper around PythonLexer and BashLexer.
60 """
60 """
61 def __init__(self):
61 def __init__(self):
62 self.python_lexer = PygmentsLexer(Python3Lexer if PY3 else PythonLexer)
62 self.python_lexer = PygmentsLexer(Python3Lexer if PY3 else PythonLexer)
63 self.shell_lexer = PygmentsLexer(BashLexer)
63 self.shell_lexer = PygmentsLexer(BashLexer)
64
64
65 def lex_document(self, cli, document):
65 def lex_document(self, cli, document):
66 if document.text.startswith('!'):
66 if document.text.startswith('!'):
67 return self.shell_lexer.lex_document(cli, document)
67 return self.shell_lexer.lex_document(cli, document)
68 else:
68 else:
69 return self.python_lexer.lex_document(cli, document)
69 return self.python_lexer.lex_document(cli, document)
70
70
71
71
72 class TerminalInteractiveShell(InteractiveShell):
72 class TerminalInteractiveShell(InteractiveShell):
73 colors_force = True
73 colors_force = True
74
74
75 pt_cli = None
75 pt_cli = None
76
76
77 autoedit_syntax = CBool(False, config=True,
77 autoedit_syntax = CBool(False, config=True,
78 help="auto editing of files with syntax errors.")
78 help="auto editing of files with syntax errors.")
79
79
80 confirm_exit = CBool(True, config=True,
80 confirm_exit = CBool(True, config=True,
81 help="""
81 help="""
82 Set to confirm when you try to exit IPython with an EOF (Control-D
82 Set to confirm when you try to exit IPython with an EOF (Control-D
83 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
83 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
84 you can force a direct exit without any confirmation.""",
84 you can force a direct exit without any confirmation.""",
85 )
85 )
86 vi_mode = Bool(False, config=True,
86 vi_mode = Bool(False, config=True,
87 help="Use vi style keybindings at the prompt",
87 help="Use vi style keybindings at the prompt",
88 )
88 )
89
89
90 mouse_support = Bool(False, config=True,
90 mouse_support = Bool(False, config=True,
91 help="Enable mouse support in the prompt"
91 help="Enable mouse support in the prompt"
92 )
92 )
93
93
94 highlighting_style = Unicode('', config=True,
94 highlighting_style = Unicode('', config=True,
95 help="The name of a Pygments style to use for syntax highlighting"
95 help="The name of a Pygments style to use for syntax highlighting"
96 )
96 )
97
97
98 highlighting_style_overrides = Dict(config=True,
98 highlighting_style_overrides = Dict(config=True,
99 help="Override highlighting format for specific tokens"
99 help="Override highlighting format for specific tokens"
100 )
100 )
101
101
102 editor = Unicode(get_default_editor(), config=True,
102 editor = Unicode(get_default_editor(), config=True,
103 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
103 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
104 )
104 )
105
105
106 term_title = Bool(True, config=True,
106 term_title = Bool(True, config=True,
107 help="Automatically set the terminal title"
107 help="Automatically set the terminal title"
108 )
108 )
109 def _term_title_changed(self, name, new_value):
109 def _term_title_changed(self, name, new_value):
110 self.init_term_title()
110 self.init_term_title()
111
111
112 def init_term_title(self):
112 def init_term_title(self):
113 # Enable or disable the terminal title.
113 # Enable or disable the terminal title.
114 if self.term_title:
114 if self.term_title:
115 toggle_set_term_title(True)
115 toggle_set_term_title(True)
116 set_term_title('IPython: ' + abbrev_cwd())
116 set_term_title('IPython: ' + abbrev_cwd())
117 else:
117 else:
118 toggle_set_term_title(False)
118 toggle_set_term_title(False)
119
119
120 def get_prompt_tokens(self, cli):
120 def get_prompt_tokens(self, cli):
121 return [
121 return [
122 (Token.Prompt, 'In ['),
122 (Token.Prompt, 'In ['),
123 (Token.PromptNum, str(self.execution_count)),
123 (Token.PromptNum, str(self.execution_count)),
124 (Token.Prompt, ']: '),
124 (Token.Prompt, ']: '),
125 ]
125 ]
126
126
127 def get_continuation_tokens(self, cli, width):
127 def get_continuation_tokens(self, cli, width):
128 return [
128 return [
129 (Token.Prompt, (' ' * (width - 5)) + '...: '),
129 (Token.Prompt, (' ' * (width - 5)) + '...: '),
130 ]
130 ]
131
131
132 def init_prompt_toolkit_cli(self):
132 def init_prompt_toolkit_cli(self):
133 if ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or not sys.stdin.isatty():
133 if ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or not sys.stdin.isatty():
134 # Fall back to plain non-interactive output for tests.
134 # Fall back to plain non-interactive output for tests.
135 # This is very limited, and only accepts a single line.
135 # This is very limited, and only accepts a single line.
136 def prompt():
136 def prompt():
137 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
137 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
138 self.prompt_for_code = prompt
138 self.prompt_for_code = prompt
139 return
139 return
140
140
141 kbmanager = KeyBindingManager.for_prompt(enable_vi_mode=self.vi_mode)
141 kbmanager = KeyBindingManager.for_prompt(enable_vi_mode=self.vi_mode)
142 insert_mode = ViStateFilter(kbmanager.get_vi_state, InputMode.INSERT)
142 insert_mode = ViStateFilter(kbmanager.get_vi_state, InputMode.INSERT)
143 # Ctrl+J == Enter, seemingly
143 # Ctrl+J == Enter, seemingly
144 @kbmanager.registry.add_binding(Keys.ControlJ,
144 @kbmanager.registry.add_binding(Keys.ControlJ,
145 filter=(HasFocus(DEFAULT_BUFFER)
145 filter=(HasFocus(DEFAULT_BUFFER)
146 & ~HasSelection()
146 & ~HasSelection()
147 & insert_mode
147 & insert_mode
148 ))
148 ))
149 def _(event):
149 def _(event):
150 b = event.current_buffer
150 b = event.current_buffer
151 d = b.document
151 d = b.document
152 if not (d.on_last_line or d.cursor_position_row >= d.line_count
152 if not (d.on_last_line or d.cursor_position_row >= d.line_count
153 - d.empty_line_count_at_the_end()):
153 - d.empty_line_count_at_the_end()):
154 b.newline()
154 b.newline()
155 return
155 return
156
156
157 status, indent = self.input_splitter.check_complete(d.text)
157 status, indent = self.input_splitter.check_complete(d.text)
158
158
159 if (status != 'incomplete') and b.accept_action.is_returnable:
159 if (status != 'incomplete') and b.accept_action.is_returnable:
160 b.accept_action.validate_and_handle(event.cli, b)
160 b.accept_action.validate_and_handle(event.cli, b)
161 else:
161 else:
162 b.insert_text('\n' + (' ' * (indent or 0)))
162 b.insert_text('\n' + (' ' * (indent or 0)))
163
163
164 @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER))
164 @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER))
165 def _(event):
165 def _(event):
166 event.current_buffer.reset()
166 event.current_buffer.reset()
167
167
168 supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP'))
168 supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP'))
169
169
170 @kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend)
170 @kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend)
171 def _(event):
171 def _(event):
172 event.cli.suspend_to_background()
172 event.cli.suspend_to_background()
173
173
174 @Condition
174 @Condition
175 def cursor_in_leading_ws(cli):
175 def cursor_in_leading_ws(cli):
176 before = cli.application.buffer.document.current_line_before_cursor
176 before = cli.application.buffer.document.current_line_before_cursor
177 return (not before) or before.isspace()
177 return (not before) or before.isspace()
178
178
179 # Ctrl+I == Tab
179 # Ctrl+I == Tab
180 @kbmanager.registry.add_binding(Keys.ControlI,
180 @kbmanager.registry.add_binding(Keys.ControlI,
181 filter=(HasFocus(DEFAULT_BUFFER)
181 filter=(HasFocus(DEFAULT_BUFFER)
182 & ~HasSelection()
182 & ~HasSelection()
183 & insert_mode
183 & insert_mode
184 & cursor_in_leading_ws
184 & cursor_in_leading_ws
185 ))
185 ))
186 def _(event):
186 def _(event):
187 event.current_buffer.insert_text(' ' * 4)
187 event.current_buffer.insert_text(' ' * 4)
188
188
189 # Pre-populate history from IPython's history database
189 # Pre-populate history from IPython's history database
190 history = InMemoryHistory()
190 history = InMemoryHistory()
191 last_cell = u""
191 last_cell = u""
192 for _, _, cell in self.history_manager.get_tail(self.history_load_length,
192 for _, _, cell in self.history_manager.get_tail(self.history_load_length,
193 include_latest=True):
193 include_latest=True):
194 # Ignore blank lines and consecutive duplicates
194 # Ignore blank lines and consecutive duplicates
195 cell = cell.rstrip()
195 cell = cell.rstrip()
196 if cell and (cell != last_cell):
196 if cell and (cell != last_cell):
197 history.append(cell)
197 history.append(cell)
198
198
199 style_overrides = {
199 style_overrides = {
200 Token.Prompt: '#009900',
200 Token.Prompt: '#009900',
201 Token.PromptNum: '#00ff00 bold',
201 Token.PromptNum: '#00ff00 bold',
202 }
202 }
203 if self.highlighting_style:
203 if self.highlighting_style:
204 style_cls = get_style_by_name(self.highlighting_style)
204 style_cls = get_style_by_name(self.highlighting_style)
205 else:
205 else:
206 style_cls = get_style_by_name('default')
206 style_cls = get_style_by_name('default')
207 # The default theme needs to be visible on both a dark background
207 # The default theme needs to be visible on both a dark background
208 # and a light background, because we can't tell what the terminal
208 # and a light background, because we can't tell what the terminal
209 # looks like. These tweaks to the default theme help with that.
209 # looks like. These tweaks to the default theme help with that.
210 style_overrides.update({
210 style_overrides.update({
211 Token.Number: '#007700',
211 Token.Number: '#007700',
212 Token.Operator: 'noinherit',
212 Token.Operator: 'noinherit',
213 Token.String: '#BB6622',
213 Token.String: '#BB6622',
214 Token.Name.Function: '#2080D0',
214 Token.Name.Function: '#2080D0',
215 Token.Name.Class: 'bold #2080D0',
215 Token.Name.Class: 'bold #2080D0',
216 Token.Name.Namespace: 'bold #2080D0',
216 Token.Name.Namespace: 'bold #2080D0',
217 })
217 })
218 style_overrides.update(self.highlighting_style_overrides)
218 style_overrides.update(self.highlighting_style_overrides)
219 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
219 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
220 style_dict=style_overrides)
220 style_dict=style_overrides)
221
221
222 app = create_prompt_application(multiline=True,
222 app = create_prompt_application(multiline=True,
223 lexer=IPythonPTLexer(),
223 lexer=IPythonPTLexer(),
224 get_prompt_tokens=self.get_prompt_tokens,
224 get_prompt_tokens=self.get_prompt_tokens,
225 get_continuation_tokens=self.get_continuation_tokens,
225 get_continuation_tokens=self.get_continuation_tokens,
226 key_bindings_registry=kbmanager.registry,
226 key_bindings_registry=kbmanager.registry,
227 history=history,
227 history=history,
228 completer=IPythonPTCompleter(self.Completer),
228 completer=IPythonPTCompleter(self.Completer),
229 enable_history_search=True,
229 enable_history_search=True,
230 style=style,
230 style=style,
231 mouse_support=self.mouse_support,
231 mouse_support=self.mouse_support,
232 reserve_space_for_menu=6,
232 reserve_space_for_menu=6,
233 )
233 )
234
234
235 self.pt_cli = CommandLineInterface(app,
235 self.pt_cli = CommandLineInterface(app,
236 eventloop=create_eventloop(self.inputhook))
236 eventloop=create_eventloop(self.inputhook))
237
237
238 def prompt_for_code(self):
238 def prompt_for_code(self):
239 document = self.pt_cli.run(pre_run=self.pre_prompt)
239 document = self.pt_cli.run(pre_run=self.pre_prompt)
240 return document.text
240 return document.text
241
241
242 def init_io(self):
242 def init_io(self):
243 if sys.platform not in {'win32', 'cli'}:
243 if sys.platform not in {'win32', 'cli'}:
244 return
244 return
245
245
246 import colorama
246 import colorama
247 colorama.init()
247 colorama.init()
248
248
249 # For some reason we make these wrappers around stdout/stderr.
249 # For some reason we make these wrappers around stdout/stderr.
250 # For now, we need to reset them so all output gets coloured.
250 # For now, we need to reset them so all output gets coloured.
251 # https://github.com/ipython/ipython/issues/8669
251 # https://github.com/ipython/ipython/issues/8669
252 from IPython.utils import io
252 from IPython.utils import io
253 io.stdout = io.IOStream(sys.stdout)
253 io.stdout = io.IOStream(sys.stdout)
254 io.stderr = io.IOStream(sys.stderr)
254 io.stderr = io.IOStream(sys.stderr)
255
255
256 def init_magics(self):
256 def init_magics(self):
257 super(TerminalInteractiveShell, self).init_magics()
257 super(TerminalInteractiveShell, self).init_magics()
258 self.register_magics(TerminalMagics)
258 self.register_magics(TerminalMagics)
259
259
260 def init_alias(self):
260 def init_alias(self):
261 # The parent class defines aliases that can be safely used with any
261 # The parent class defines aliases that can be safely used with any
262 # frontend.
262 # frontend.
263 super(TerminalInteractiveShell, self).init_alias()
263 super(TerminalInteractiveShell, self).init_alias()
264
264
265 # Now define aliases that only make sense on the terminal, because they
265 # Now define aliases that only make sense on the terminal, because they
266 # need direct access to the console in a way that we can't emulate in
266 # need direct access to the console in a way that we can't emulate in
267 # GUI or web frontend
267 # GUI or web frontend
268 if os.name == 'posix':
268 if os.name == 'posix':
269 for cmd in ['clear', 'more', 'less', 'man']:
269 for cmd in ['clear', 'more', 'less', 'man']:
270 self.alias_manager.soft_define_alias(cmd, cmd)
270 self.alias_manager.soft_define_alias(cmd, cmd)
271
271
272
272
273 def __init__(self, *args, **kwargs):
273 def __init__(self, *args, **kwargs):
274 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
274 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
275 self.init_prompt_toolkit_cli()
275 self.init_prompt_toolkit_cli()
276 self.init_term_title()
276 self.init_term_title()
277 self.keep_running = True
277 self.keep_running = True
278
278
279 def ask_exit(self):
279 def ask_exit(self):
280 self.keep_running = False
280 self.keep_running = False
281
281
282 rl_next_input = None
282 rl_next_input = None
283
283
284 def pre_prompt(self):
284 def pre_prompt(self):
285 if self.rl_next_input:
285 if self.rl_next_input:
286 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
286 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
287 self.rl_next_input = None
287 self.rl_next_input = None
288
288
289 def interact(self):
289 def interact(self):
290 while self.keep_running:
290 while self.keep_running:
291 print(self.separate_in, end='')
291 print(self.separate_in, end='')
292
292
293 try:
293 try:
294 code = self.prompt_for_code()
294 code = self.prompt_for_code()
295 except EOFError:
295 except EOFError:
296 if (not self.confirm_exit) \
296 if (not self.confirm_exit) \
297 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
297 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
298 self.ask_exit()
298 self.ask_exit()
299
299
300 else:
300 else:
301 if code:
301 if code:
302 self.run_cell(code, store_history=True)
302 self.run_cell(code, store_history=True)
303 if self.autoedit_syntax and self.SyntaxTB.last_syntax_error:
303 if self.autoedit_syntax and self.SyntaxTB.last_syntax_error:
304 self.edit_syntax_error()
304 self.edit_syntax_error()
305
305
306 def mainloop(self):
306 def mainloop(self):
307 # An extra layer of protection in case someone mashing Ctrl-C breaks
307 # An extra layer of protection in case someone mashing Ctrl-C breaks
308 # out of our internal code.
308 # out of our internal code.
309 while True:
309 while True:
310 try:
310 try:
311 self.interact()
311 self.interact()
312 break
312 break
313 except KeyboardInterrupt:
313 except KeyboardInterrupt:
314 print("\nKeyboardInterrupt escaped interact()\n")
314 print("\nKeyboardInterrupt escaped interact()\n")
315
315
316 _inputhook = None
316 _inputhook = None
317 def inputhook(self, context):
317 def inputhook(self, context):
318 if self._inputhook is not None:
318 if self._inputhook is not None:
319 self._inputhook(context)
319 self._inputhook(context)
320
320
321 def enable_gui(self, gui=None):
321 def enable_gui(self, gui=None):
322 if gui:
322 if gui:
323 self._inputhook = get_inputhook_func(gui)
323 self._inputhook = get_inputhook_func(gui)
324 else:
324 else:
325 self._inputhook = None
325 self._inputhook = None
326
326
327 # Methods to support auto-editing of SyntaxErrors:
327 # Methods to support auto-editing of SyntaxErrors:
328
328
329 def edit_syntax_error(self):
329 def edit_syntax_error(self):
330 """The bottom half of the syntax error handler called in the main loop.
330 """The bottom half of the syntax error handler called in the main loop.
331
331
332 Loop until syntax error is fixed or user cancels.
332 Loop until syntax error is fixed or user cancels.
333 """
333 """
334
334
335 while self.SyntaxTB.last_syntax_error:
335 while self.SyntaxTB.last_syntax_error:
336 # copy and clear last_syntax_error
336 # copy and clear last_syntax_error
337 err = self.SyntaxTB.clear_err_state()
337 err = self.SyntaxTB.clear_err_state()
338 if not self._should_recompile(err):
338 if not self._should_recompile(err):
339 return
339 return
340 try:
340 try:
341 # may set last_syntax_error again if a SyntaxError is raised
341 # may set last_syntax_error again if a SyntaxError is raised
342 self.safe_execfile(err.filename, self.user_ns)
342 self.safe_execfile(err.filename, self.user_ns)
343 except:
343 except:
344 self.showtraceback()
344 self.showtraceback()
345 else:
345 else:
346 try:
346 try:
347 f = open(err.filename)
347 with open(err.filename) as f:
348 try:
349 # This should be inside a display_trap block and I
348 # This should be inside a display_trap block and I
350 # think it is.
349 # think it is.
351 sys.displayhook(f.read())
350 sys.displayhook(f.read())
352 finally:
353 f.close()
354 except:
351 except:
355 self.showtraceback()
352 self.showtraceback()
356
353
357 def _should_recompile(self, e):
354 def _should_recompile(self, e):
358 """Utility routine for edit_syntax_error"""
355 """Utility routine for edit_syntax_error"""
359
356
360 if e.filename in ('<ipython console>', '<input>', '<string>',
357 if e.filename in ('<ipython console>', '<input>', '<string>',
361 '<console>', '<BackgroundJob compilation>',
358 '<console>', '<BackgroundJob compilation>',
362 None):
359 None):
363 return False
360 return False
364 try:
361 try:
365 if (self.autoedit_syntax and
362 if (self.autoedit_syntax and
366 not self.ask_yes_no(
363 not self.ask_yes_no(
367 'Return to editor to correct syntax error? '
364 'Return to editor to correct syntax error? '
368 '[Y/n] ', 'y')):
365 '[Y/n] ', 'y')):
369 return False
366 return False
370 except EOFError:
367 except EOFError:
371 return False
368 return False
372
369
373 def int0(x):
370 def int0(x):
374 try:
371 try:
375 return int(x)
372 return int(x)
376 except TypeError:
373 except TypeError:
377 return 0
374 return 0
378
375
379 # always pass integer line and offset values to editor hook
376 # always pass integer line and offset values to editor hook
380 try:
377 try:
381 self.hooks.fix_error_editor(e.filename,
378 self.hooks.fix_error_editor(e.filename,
382 int0(e.lineno), int0(e.offset),
379 int0(e.lineno), int0(e.offset),
383 e.msg)
380 e.msg)
384 except TryNext:
381 except TryNext:
385 warn('Could not open editor')
382 warn('Could not open editor')
386 return False
383 return False
387 return True
384 return True
388
385
389 if __name__ == '__main__':
386 if __name__ == '__main__':
390 TerminalInteractiveShell.instance().interact()
387 TerminalInteractiveShell.instance().interact()
General Comments 0
You need to be logged in to leave comments. Login now