##// END OF EJS Templates
initialize hlen_b4_cell also in the no readline case
Julian Taylor -
Show More
@@ -1,625 +1,627 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Subclass of InteractiveShell for terminal based frontends."""
3 3
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 7 # Copyright (C) 2008-2010 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 import __builtin__
18 18 import bdb
19 19 import os
20 20 import re
21 21 import sys
22 22
23 23 try:
24 24 from contextlib import nested
25 25 except:
26 26 from IPython.utils.nested_context import nested
27 27
28 28 from IPython.core.error import TryNext
29 29 from IPython.core.usage import interactive_usage, default_banner
30 30 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
31 31 from IPython.lib.inputhook import enable_gui
32 32 from IPython.lib.pylabtools import pylab_activate
33 33 from IPython.testing.skipdoctest import skip_doctest
34 34 from IPython.utils import py3compat
35 35 from IPython.utils.terminal import toggle_set_term_title, set_term_title
36 36 from IPython.utils.process import abbrev_cwd
37 37 from IPython.utils.warn import warn
38 38 from IPython.utils.text import num_ini_spaces
39 39 from IPython.utils.traitlets import Int, CBool, Unicode
40 40
41 41 #-----------------------------------------------------------------------------
42 42 # Utilities
43 43 #-----------------------------------------------------------------------------
44 44
45 45 def get_default_editor():
46 46 try:
47 47 ed = os.environ['EDITOR']
48 48 except KeyError:
49 49 if os.name == 'posix':
50 50 ed = 'vi' # the only one guaranteed to be there!
51 51 else:
52 52 ed = 'notepad' # same in Windows!
53 53 return ed
54 54
55 55 #-----------------------------------------------------------------------------
56 56 # Main class
57 57 #-----------------------------------------------------------------------------
58 58
59 59 class TerminalInteractiveShell(InteractiveShell):
60 60
61 61 autoedit_syntax = CBool(False, config=True,
62 62 help="auto editing of files with syntax errors.")
63 63 banner = Unicode('')
64 64 banner1 = Unicode(default_banner, config=True,
65 65 help="""The part of the banner to be printed before the profile"""
66 66 )
67 67 banner2 = Unicode('', config=True,
68 68 help="""The part of the banner to be printed after the profile"""
69 69 )
70 70 confirm_exit = CBool(True, config=True,
71 71 help="""
72 72 Set to confirm when you try to exit IPython with an EOF (Control-D
73 73 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
74 74 you can force a direct exit without any confirmation.""",
75 75 )
76 76 # This display_banner only controls whether or not self.show_banner()
77 77 # is called when mainloop/interact are called. The default is False
78 78 # because for the terminal based application, the banner behavior
79 79 # is controlled by Global.display_banner, which IPythonApp looks at
80 80 # to determine if *it* should call show_banner() by hand or not.
81 81 display_banner = CBool(False) # This isn't configurable!
82 82 embedded = CBool(False)
83 83 embedded_active = CBool(False)
84 84 editor = Unicode(get_default_editor(), config=True,
85 85 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
86 86 )
87 87 pager = Unicode('less', config=True,
88 88 help="The shell program to be used for paging.")
89 89
90 90 screen_length = Int(0, config=True,
91 91 help=
92 92 """Number of lines of your screen, used to control printing of very
93 93 long strings. Strings longer than this number of lines will be sent
94 94 through a pager instead of directly printed. The default value for
95 95 this is 0, which means IPython will auto-detect your screen size every
96 96 time it needs to print certain potentially long strings (this doesn't
97 97 change the behavior of the 'print' keyword, it's only triggered
98 98 internally). If for some reason this isn't working well (it needs
99 99 curses support), specify it yourself. Otherwise don't change the
100 100 default.""",
101 101 )
102 102 term_title = CBool(False, config=True,
103 103 help="Enable auto setting the terminal title."
104 104 )
105 105
106 106 def __init__(self, config=None, ipython_dir=None, profile_dir=None, user_ns=None,
107 107 user_global_ns=None, custom_exceptions=((),None),
108 108 usage=None, banner1=None, banner2=None,
109 109 display_banner=None):
110 110
111 111 super(TerminalInteractiveShell, self).__init__(
112 112 config=config, profile_dir=profile_dir, user_ns=user_ns,
113 113 user_global_ns=user_global_ns, custom_exceptions=custom_exceptions
114 114 )
115 115 # use os.system instead of utils.process.system by default, except on Windows
116 116 if os.name == 'nt':
117 117 self.system = self.system_piped
118 118 else:
119 119 self.system = self.system_raw
120 120
121 121 self.init_term_title()
122 122 self.init_usage(usage)
123 123 self.init_banner(banner1, banner2, display_banner)
124 124
125 125 #-------------------------------------------------------------------------
126 126 # Things related to the terminal
127 127 #-------------------------------------------------------------------------
128 128
129 129 @property
130 130 def usable_screen_length(self):
131 131 if self.screen_length == 0:
132 132 return 0
133 133 else:
134 134 num_lines_bot = self.separate_in.count('\n')+1
135 135 return self.screen_length - num_lines_bot
136 136
137 137 def init_term_title(self):
138 138 # Enable or disable the terminal title.
139 139 if self.term_title:
140 140 toggle_set_term_title(True)
141 141 set_term_title('IPython: ' + abbrev_cwd())
142 142 else:
143 143 toggle_set_term_title(False)
144 144
145 145 #-------------------------------------------------------------------------
146 146 # Things related to aliases
147 147 #-------------------------------------------------------------------------
148 148
149 149 def init_alias(self):
150 150 # The parent class defines aliases that can be safely used with any
151 151 # frontend.
152 152 super(TerminalInteractiveShell, self).init_alias()
153 153
154 154 # Now define aliases that only make sense on the terminal, because they
155 155 # need direct access to the console in a way that we can't emulate in
156 156 # GUI or web frontend
157 157 if os.name == 'posix':
158 158 aliases = [('clear', 'clear'), ('more', 'more'), ('less', 'less'),
159 159 ('man', 'man')]
160 160 elif os.name == 'nt':
161 161 aliases = [('cls', 'cls')]
162 162
163 163
164 164 for name, cmd in aliases:
165 165 self.alias_manager.define_alias(name, cmd)
166 166
167 167 #-------------------------------------------------------------------------
168 168 # Things related to the banner and usage
169 169 #-------------------------------------------------------------------------
170 170
171 171 def _banner1_changed(self):
172 172 self.compute_banner()
173 173
174 174 def _banner2_changed(self):
175 175 self.compute_banner()
176 176
177 177 def _term_title_changed(self, name, new_value):
178 178 self.init_term_title()
179 179
180 180 def init_banner(self, banner1, banner2, display_banner):
181 181 if banner1 is not None:
182 182 self.banner1 = banner1
183 183 if banner2 is not None:
184 184 self.banner2 = banner2
185 185 if display_banner is not None:
186 186 self.display_banner = display_banner
187 187 self.compute_banner()
188 188
189 189 def show_banner(self, banner=None):
190 190 if banner is None:
191 191 banner = self.banner
192 192 self.write(banner)
193 193
194 194 def compute_banner(self):
195 195 self.banner = self.banner1
196 196 if self.profile and self.profile != 'default':
197 197 self.banner += '\nIPython profile: %s\n' % self.profile
198 198 if self.banner2:
199 199 self.banner += '\n' + self.banner2
200 200
201 201 def init_usage(self, usage=None):
202 202 if usage is None:
203 203 self.usage = interactive_usage
204 204 else:
205 205 self.usage = usage
206 206
207 207 #-------------------------------------------------------------------------
208 208 # Mainloop and code execution logic
209 209 #-------------------------------------------------------------------------
210 210
211 211 def mainloop(self, display_banner=None):
212 212 """Start the mainloop.
213 213
214 214 If an optional banner argument is given, it will override the
215 215 internally created default banner.
216 216 """
217 217
218 218 with nested(self.builtin_trap, self.display_trap):
219 219
220 220 while 1:
221 221 try:
222 222 self.interact(display_banner=display_banner)
223 223 #self.interact_with_readline()
224 224 # XXX for testing of a readline-decoupled repl loop, call
225 225 # interact_with_readline above
226 226 break
227 227 except KeyboardInterrupt:
228 228 # this should not be necessary, but KeyboardInterrupt
229 229 # handling seems rather unpredictable...
230 230 self.write("\nKeyboardInterrupt in interact()\n")
231 231
232 232 def _replace_rlhist_multiline(self, source_raw, hlen_before_cell):
233 233 """Store multiple lines as a single entry in history"""
234 234
235 235 # do nothing without readline or disabled multiline
236 236 if not self.has_readline or not self.multiline_history:
237 237 return hlen_before_cell
238 238
239 239 # skip empty cells
240 240 if not source_raw.rstrip():
241 241 return hlen_before_cell
242 242
243 243 # nothing changed do nothing, e.g. when rl removes consecutive dups
244 244 hlen = self.readline.get_current_history_length()
245 245 if hlen == hlen_before_cell:
246 246 return hlen_before_cell
247 247
248 248 for i in range(hlen - hlen_before_cell):
249 249 self.readline.remove_history_item(hlen - i - 1)
250 250 stdin_encoding = sys.stdin.encoding or "utf-8"
251 251 self.readline.add_history(py3compat.unicode_to_str(source_raw.rstrip(),
252 252 stdin_encoding))
253 253 return self.readline.get_current_history_length()
254 254
255 255 def interact(self, display_banner=None):
256 256 """Closely emulate the interactive Python console."""
257 257
258 258 # batch run -> do not interact
259 259 if self.exit_now:
260 260 return
261 261
262 262 if display_banner is None:
263 263 display_banner = self.display_banner
264 264
265 265 if isinstance(display_banner, basestring):
266 266 self.show_banner(display_banner)
267 267 elif display_banner:
268 268 self.show_banner()
269 269
270 270 more = False
271 271
272 272 # Mark activity in the builtins
273 273 __builtin__.__dict__['__IPYTHON__active'] += 1
274 274
275 275 if self.has_readline:
276 276 self.readline_startup_hook(self.pre_readline)
277 277 hlen_b4_cell = self.readline.get_current_history_length()
278 else:
279 hlen_b4_cell = 0
278 280 # exit_now is set by a call to %Exit or %Quit, through the
279 281 # ask_exit callback.
280 282
281 283 while not self.exit_now:
282 284 self.hooks.pre_prompt_hook()
283 285 if more:
284 286 try:
285 287 prompt = self.hooks.generate_prompt(True)
286 288 except:
287 289 self.showtraceback()
288 290 if self.autoindent:
289 291 self.rl_do_indent = True
290 292
291 293 else:
292 294 try:
293 295 prompt = self.hooks.generate_prompt(False)
294 296 except:
295 297 self.showtraceback()
296 298 try:
297 299 line = self.raw_input(prompt)
298 300 if self.exit_now:
299 301 # quick exit on sys.std[in|out] close
300 302 break
301 303 if self.autoindent:
302 304 self.rl_do_indent = False
303 305
304 306 except KeyboardInterrupt:
305 307 #double-guard against keyboardinterrupts during kbdint handling
306 308 try:
307 309 self.write('\nKeyboardInterrupt\n')
308 310 source_raw = self.input_splitter.source_raw_reset()[1]
309 311 hlen_b4_cell = \
310 312 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
311 313 more = False
312 314 except KeyboardInterrupt:
313 315 pass
314 316 except EOFError:
315 317 if self.autoindent:
316 318 self.rl_do_indent = False
317 319 if self.has_readline:
318 320 self.readline_startup_hook(None)
319 321 self.write('\n')
320 322 self.exit()
321 323 except bdb.BdbQuit:
322 324 warn('The Python debugger has exited with a BdbQuit exception.\n'
323 325 'Because of how pdb handles the stack, it is impossible\n'
324 326 'for IPython to properly format this particular exception.\n'
325 327 'IPython will resume normal operation.')
326 328 except:
327 329 # exceptions here are VERY RARE, but they can be triggered
328 330 # asynchronously by signal handlers, for example.
329 331 self.showtraceback()
330 332 else:
331 333 self.input_splitter.push(line)
332 334 more = self.input_splitter.push_accepts_more()
333 335 if (self.SyntaxTB.last_syntax_error and
334 336 self.autoedit_syntax):
335 337 self.edit_syntax_error()
336 338 if not more:
337 339 source_raw = self.input_splitter.source_raw_reset()[1]
338 340 self.run_cell(source_raw, store_history=True)
339 341 hlen_b4_cell = \
340 342 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
341 343
342 344 # We are off again...
343 345 __builtin__.__dict__['__IPYTHON__active'] -= 1
344 346
345 347 # Turn off the exit flag, so the mainloop can be restarted if desired
346 348 self.exit_now = False
347 349
348 350 def raw_input(self, prompt=''):
349 351 """Write a prompt and read a line.
350 352
351 353 The returned line does not include the trailing newline.
352 354 When the user enters the EOF key sequence, EOFError is raised.
353 355
354 356 Optional inputs:
355 357
356 358 - prompt(''): a string to be printed to prompt the user.
357 359
358 360 - continue_prompt(False): whether this line is the first one or a
359 361 continuation in a sequence of inputs.
360 362 """
361 363 # Code run by the user may have modified the readline completer state.
362 364 # We must ensure that our completer is back in place.
363 365
364 366 if self.has_readline:
365 367 self.set_readline_completer()
366 368
367 369 try:
368 370 line = py3compat.str_to_unicode(self.raw_input_original(prompt))
369 371 except ValueError:
370 372 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
371 373 " or sys.stdout.close()!\nExiting IPython!")
372 374 self.ask_exit()
373 375 return ""
374 376
375 377 # Try to be reasonably smart about not re-indenting pasted input more
376 378 # than necessary. We do this by trimming out the auto-indent initial
377 379 # spaces, if the user's actual input started itself with whitespace.
378 380 if self.autoindent:
379 381 if num_ini_spaces(line) > self.indent_current_nsp:
380 382 line = line[self.indent_current_nsp:]
381 383 self.indent_current_nsp = 0
382 384
383 385 return line
384 386
385 387 #-------------------------------------------------------------------------
386 388 # Methods to support auto-editing of SyntaxErrors.
387 389 #-------------------------------------------------------------------------
388 390
389 391 def edit_syntax_error(self):
390 392 """The bottom half of the syntax error handler called in the main loop.
391 393
392 394 Loop until syntax error is fixed or user cancels.
393 395 """
394 396
395 397 while self.SyntaxTB.last_syntax_error:
396 398 # copy and clear last_syntax_error
397 399 err = self.SyntaxTB.clear_err_state()
398 400 if not self._should_recompile(err):
399 401 return
400 402 try:
401 403 # may set last_syntax_error again if a SyntaxError is raised
402 404 self.safe_execfile(err.filename,self.user_ns)
403 405 except:
404 406 self.showtraceback()
405 407 else:
406 408 try:
407 409 f = file(err.filename)
408 410 try:
409 411 # This should be inside a display_trap block and I
410 412 # think it is.
411 413 sys.displayhook(f.read())
412 414 finally:
413 415 f.close()
414 416 except:
415 417 self.showtraceback()
416 418
417 419 def _should_recompile(self,e):
418 420 """Utility routine for edit_syntax_error"""
419 421
420 422 if e.filename in ('<ipython console>','<input>','<string>',
421 423 '<console>','<BackgroundJob compilation>',
422 424 None):
423 425
424 426 return False
425 427 try:
426 428 if (self.autoedit_syntax and
427 429 not self.ask_yes_no('Return to editor to correct syntax error? '
428 430 '[Y/n] ','y')):
429 431 return False
430 432 except EOFError:
431 433 return False
432 434
433 435 def int0(x):
434 436 try:
435 437 return int(x)
436 438 except TypeError:
437 439 return 0
438 440 # always pass integer line and offset values to editor hook
439 441 try:
440 442 self.hooks.fix_error_editor(e.filename,
441 443 int0(e.lineno),int0(e.offset),e.msg)
442 444 except TryNext:
443 445 warn('Could not open editor')
444 446 return False
445 447 return True
446 448
447 449 #-------------------------------------------------------------------------
448 450 # Things related to GUI support and pylab
449 451 #-------------------------------------------------------------------------
450 452
451 453 def enable_pylab(self, gui=None, import_all=True):
452 454 """Activate pylab support at runtime.
453 455
454 456 This turns on support for matplotlib, preloads into the interactive
455 457 namespace all of numpy and pylab, and configures IPython to correcdtly
456 458 interact with the GUI event loop. The GUI backend to be used can be
457 459 optionally selected with the optional :param:`gui` argument.
458 460
459 461 Parameters
460 462 ----------
461 463 gui : optional, string
462 464
463 465 If given, dictates the choice of matplotlib GUI backend to use
464 466 (should be one of IPython's supported backends, 'tk', 'qt', 'wx' or
465 467 'gtk'), otherwise we use the default chosen by matplotlib (as
466 468 dictated by the matplotlib build-time options plus the user's
467 469 matplotlibrc configuration file).
468 470 """
469 471 # We want to prevent the loading of pylab to pollute the user's
470 472 # namespace as shown by the %who* magics, so we execute the activation
471 473 # code in an empty namespace, and we update *both* user_ns and
472 474 # user_ns_hidden with this information.
473 475 ns = {}
474 476 gui = pylab_activate(ns, gui, import_all)
475 477 self.user_ns.update(ns)
476 478 self.user_ns_hidden.update(ns)
477 479 # Now we must activate the gui pylab wants to use, and fix %run to take
478 480 # plot updates into account
479 481 enable_gui(gui)
480 482 self.magic_run = self._pylab_magic_run
481 483
482 484 #-------------------------------------------------------------------------
483 485 # Things related to exiting
484 486 #-------------------------------------------------------------------------
485 487
486 488 def ask_exit(self):
487 489 """ Ask the shell to exit. Can be overiden and used as a callback. """
488 490 self.exit_now = True
489 491
490 492 def exit(self):
491 493 """Handle interactive exit.
492 494
493 495 This method calls the ask_exit callback."""
494 496 if self.confirm_exit:
495 497 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
496 498 self.ask_exit()
497 499 else:
498 500 self.ask_exit()
499 501
500 502 #------------------------------------------------------------------------
501 503 # Magic overrides
502 504 #------------------------------------------------------------------------
503 505 # Once the base class stops inheriting from magic, this code needs to be
504 506 # moved into a separate machinery as well. For now, at least isolate here
505 507 # the magics which this class needs to implement differently from the base
506 508 # class, or that are unique to it.
507 509
508 510 def magic_autoindent(self, parameter_s = ''):
509 511 """Toggle autoindent on/off (if available)."""
510 512
511 513 self.shell.set_autoindent()
512 514 print "Automatic indentation is:",['OFF','ON'][self.shell.autoindent]
513 515
514 516 @skip_doctest
515 517 def magic_cpaste(self, parameter_s=''):
516 518 """Paste & execute a pre-formatted code block from clipboard.
517 519
518 520 You must terminate the block with '--' (two minus-signs) or Ctrl-D alone on the
519 521 line. You can also provide your own sentinel with '%paste -s %%' ('%%'
520 522 is the new sentinel for this operation)
521 523
522 524 The block is dedented prior to execution to enable execution of method
523 525 definitions. '>' and '+' characters at the beginning of a line are
524 526 ignored, to allow pasting directly from e-mails, diff files and
525 527 doctests (the '...' continuation prompt is also stripped). The
526 528 executed block is also assigned to variable named 'pasted_block' for
527 529 later editing with '%edit pasted_block'.
528 530
529 531 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
530 532 This assigns the pasted block to variable 'foo' as string, without
531 533 dedenting or executing it (preceding >>> and + is still stripped)
532 534
533 535 '%cpaste -r' re-executes the block previously entered by cpaste.
534 536
535 537 Do not be alarmed by garbled output on Windows (it's a readline bug).
536 538 Just press enter and type -- (and press enter again) and the block
537 539 will be what was just pasted.
538 540
539 541 IPython statements (magics, shell escapes) are not supported (yet).
540 542
541 543 See also
542 544 --------
543 545 paste: automatically pull code from clipboard.
544 546
545 547 Examples
546 548 --------
547 549 ::
548 550
549 551 In [8]: %cpaste
550 552 Pasting code; enter '--' alone on the line to stop.
551 553 :>>> a = ["world!", "Hello"]
552 554 :>>> print " ".join(sorted(a))
553 555 :--
554 556 Hello world!
555 557 """
556 558
557 559 opts,args = self.parse_options(parameter_s,'rs:',mode='string')
558 560 par = args.strip()
559 561 if opts.has_key('r'):
560 562 self._rerun_pasted()
561 563 return
562 564
563 565 sentinel = opts.get('s','--')
564 566
565 567 block = self._strip_pasted_lines_for_code(
566 568 self._get_pasted_lines(sentinel))
567 569
568 570 self._execute_block(block, par)
569 571
570 572 def magic_paste(self, parameter_s=''):
571 573 """Paste & execute a pre-formatted code block from clipboard.
572 574
573 575 The text is pulled directly from the clipboard without user
574 576 intervention and printed back on the screen before execution (unless
575 577 the -q flag is given to force quiet mode).
576 578
577 579 The block is dedented prior to execution to enable execution of method
578 580 definitions. '>' and '+' characters at the beginning of a line are
579 581 ignored, to allow pasting directly from e-mails, diff files and
580 582 doctests (the '...' continuation prompt is also stripped). The
581 583 executed block is also assigned to variable named 'pasted_block' for
582 584 later editing with '%edit pasted_block'.
583 585
584 586 You can also pass a variable name as an argument, e.g. '%paste foo'.
585 587 This assigns the pasted block to variable 'foo' as string, without
586 588 dedenting or executing it (preceding >>> and + is still stripped)
587 589
588 590 Options
589 591 -------
590 592
591 593 -r: re-executes the block previously entered by cpaste.
592 594
593 595 -q: quiet mode: do not echo the pasted text back to the terminal.
594 596
595 597 IPython statements (magics, shell escapes) are not supported (yet).
596 598
597 599 See also
598 600 --------
599 601 cpaste: manually paste code into terminal until you mark its end.
600 602 """
601 603 opts,args = self.parse_options(parameter_s,'rq',mode='string')
602 604 par = args.strip()
603 605 if opts.has_key('r'):
604 606 self._rerun_pasted()
605 607 return
606 608
607 609 text = self.shell.hooks.clipboard_get()
608 610 block = self._strip_pasted_lines_for_code(text.splitlines())
609 611
610 612 # By default, echo back to terminal unless quiet mode is requested
611 613 if not opts.has_key('q'):
612 614 write = self.shell.write
613 615 write(self.shell.pycolorize(block))
614 616 if not block.endswith('\n'):
615 617 write('\n')
616 618 write("## -- End pasted text --\n")
617 619
618 620 self._execute_block(block, par)
619 621
620 622 def showindentationerror(self):
621 623 super(TerminalInteractiveShell, self).showindentationerror()
622 624 print("If you want to paste code into IPython, try the %paste magic function.")
623 625
624 626
625 627 InteractiveShellABC.register(TerminalInteractiveShell)
General Comments 0
You need to be logged in to leave comments. Login now