##// END OF EJS Templates
Fix paste/cpaste bug and refactor/cleanup that code a lot....
Fernando Perez -
Show More
@@ -25,7 +25,6 b' import sys'
25 25 import shutil
26 26 import re
27 27 import time
28 import textwrap
29 28 from StringIO import StringIO
30 29 from getopt import getopt,GetoptError
31 30 from pprint import pformat
@@ -3203,65 +3202,6 b' Defaulting color scheme to \'NoColor\'"""'
3203 3202
3204 3203 page.page(self.shell.pycolorize(cont))
3205 3204
3206 def _rerun_pasted(self):
3207 """ Rerun a previously pasted command.
3208 """
3209 b = self.user_ns.get('pasted_block', None)
3210 if b is None:
3211 raise UsageError('No previous pasted block available')
3212 print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))
3213 exec b in self.user_ns
3214
3215 def _get_pasted_lines(self, sentinel):
3216 """ Yield pasted lines until the user enters the given sentinel value.
3217 """
3218 from IPython.core import interactiveshell
3219 print "Pasting code; enter '%s' alone on the line to stop." % sentinel
3220 while True:
3221 try:
3222 l = self.shell.raw_input_original(':')
3223 if l == sentinel:
3224 return
3225 else:
3226 yield l
3227 except EOFError:
3228 print '<EOF>'
3229 return
3230
3231 def _strip_pasted_lines_for_code(self, raw_lines):
3232 """ Strip non-code parts of a sequence of lines to return a block of
3233 code.
3234 """
3235 # Regular expressions that declare text we strip from the input:
3236 strip_re = [r'^\s*In \[\d+\]:', # IPython input prompt
3237 r'^\s*(\s?>)+', # Python input prompt
3238 r'^\s*\.{3,}', # Continuation prompts
3239 r'^\++',
3240 ]
3241
3242 strip_from_start = map(re.compile,strip_re)
3243
3244 lines = []
3245 for l in raw_lines:
3246 for pat in strip_from_start:
3247 l = pat.sub('',l)
3248 lines.append(l)
3249
3250 block = "\n".join(lines) + '\n'
3251 #print "block:\n",block
3252 return block
3253
3254 def _execute_block(self, block, par):
3255 """ Execute a block, or store it in a variable, per the user's request.
3256 """
3257 if not par:
3258 b = textwrap.dedent(block)
3259 self.user_ns['pasted_block'] = b
3260 self.run_cell(b)
3261 else:
3262 self.user_ns[par] = SList(block.splitlines())
3263 print "Block assigned to '%s'" % par
3264
3265 3205 def magic_quickref(self,arg):
3266 3206 """ Show a quick reference sheet """
3267 3207 import IPython.core.usage
@@ -355,14 +355,15 b' def test_cpaste():'
355 355 _ip.user_ns['code_ran'] = True
356 356 return 'run' # return string so '+ run()' doesn't result in success
357 357
358 tests = {'pass': ["> > > run()",
359 ">>> > run()",
360 "+++ run()",
361 "++ run()",
362 " >>> run()"],
363
364 'fail': ["+ + run()",
365 " ++ run()"]}
358 tests = {'pass': ["run()",
359 "In [1]: run()",
360 "In [1]: if 1:\n ...: run()",
361 ">>> run()",
362 " >>> run()",
363 ],
364
365 'fail': ["1 + run()",
366 "++ run()"]}
366 367
367 368 _ip.user_ns['run'] = run
368 369
@@ -19,6 +19,7 b' import bdb'
19 19 import os
20 20 import re
21 21 import sys
22 import textwrap
22 23
23 24 try:
24 25 from contextlib import nested
@@ -35,7 +36,7 b' from IPython.utils import py3compat'
35 36 from IPython.utils.terminal import toggle_set_term_title, set_term_title
36 37 from IPython.utils.process import abbrev_cwd
37 38 from IPython.utils.warn import warn, error
38 from IPython.utils.text import num_ini_spaces
39 from IPython.utils.text import num_ini_spaces, SList
39 40 from IPython.utils.traitlets import Integer, CBool, Unicode
40 41
41 42 #-----------------------------------------------------------------------------
@@ -52,6 +53,48 b' def get_default_editor():'
52 53 ed = 'notepad' # same in Windows!
53 54 return ed
54 55
56
57 def get_pasted_lines(sentinel, input=raw_input):
58 """ Yield pasted lines until the user enters the given sentinel value.
59 """
60 print "Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
61 % sentinel
62 while True:
63 try:
64 l = input(':')
65 if l == sentinel:
66 return
67 else:
68 yield l
69 except EOFError:
70 print '<EOF>'
71 return
72
73
74 def store_or_execute(shell, block, name):
75 """ Execute a block, or store it in a variable, per the user's request.
76 """
77 if name:
78 # If storing it for further editing, run the prefilter on it
79 shell.user_ns[name] = SList(shell.prefilter(block).splitlines())
80 print "Block assigned to '%s'" % name
81 else:
82 # For execution we just dedent it, as all other filtering is
83 # automatically applied by run_cell
84 b = textwrap.dedent(block)
85 shell.user_ns['pasted_block'] = b
86 shell.run_cell(b)
87
88
89 def rerun_pasted(shell):
90 """ Rerun a previously pasted command.
91 """
92 b = shell.user_ns.get('pasted_block')
93 if b is None:
94 raise UsageError('No previous pasted block available')
95 print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))
96 shell.run_cell(b)
97
55 98 #-----------------------------------------------------------------------------
56 99 # Main class
57 100 #-----------------------------------------------------------------------------
@@ -523,9 +566,9 b' class TerminalInteractiveShell(InteractiveShell):'
523 566 def magic_cpaste(self, parameter_s=''):
524 567 """Paste & execute a pre-formatted code block from clipboard.
525 568
526 You must terminate the block with '--' (two minus-signs) or Ctrl-D alone on the
527 line. You can also provide your own sentinel with '%paste -s %%' ('%%'
528 is the new sentinel for this operation)
569 You must terminate the block with '--' (two minus-signs) or Ctrl-D
570 alone on the line. You can also provide your own sentinel with '%paste
571 -s %%' ('%%' is the new sentinel for this operation)
529 572
530 573 The block is dedented prior to execution to enable execution of method
531 574 definitions. '>' and '+' characters at the beginning of a line are
@@ -562,18 +605,15 b' class TerminalInteractiveShell(InteractiveShell):'
562 605 Hello world!
563 606 """
564 607
565 opts,args = self.parse_options(parameter_s,'rs:',mode='string')
566 par = args.strip()
567 if opts.has_key('r'):
568 self._rerun_pasted()
608 opts, args = self.parse_options(parameter_s, 'rs:', mode='string')
609 name = args.strip()
610 if 'r' in opts:
611 rerun_pasted(self.shell)
569 612 return
570 613
571 sentinel = opts.get('s','--')
572
573 block = self._strip_pasted_lines_for_code(
574 self._get_pasted_lines(sentinel))
575
576 self._execute_block(block, par)
614 sentinel = opts.get('s', '--')
615 block = '\n'.join(get_pasted_lines(sentinel))
616 store_or_execute(self.shell, block, name)
577 617
578 618 def magic_paste(self, parameter_s=''):
579 619 """Paste & execute a pre-formatted code block from clipboard.
@@ -606,10 +646,10 b' class TerminalInteractiveShell(InteractiveShell):'
606 646 --------
607 647 cpaste: manually paste code into terminal until you mark its end.
608 648 """
609 opts,args = self.parse_options(parameter_s,'rq',mode='string')
610 par = args.strip()
611 if opts.has_key('r'):
612 self._rerun_pasted()
649 opts, args = self.parse_options(parameter_s, 'rq', mode='string')
650 name = args.strip()
651 if 'r' in opts:
652 rerun_pasted(self.shell)
613 653 return
614 654 try:
615 655 text = self.shell.hooks.clipboard_get()
@@ -623,14 +663,14 b' class TerminalInteractiveShell(InteractiveShell):'
623 663 return
624 664
625 665 # By default, echo back to terminal unless quiet mode is requested
626 if not opts.has_key('q'):
666 if 'q' not in opts:
627 667 write = self.shell.write
628 668 write(self.shell.pycolorize(block))
629 669 if not block.endswith('\n'):
630 670 write('\n')
631 671 write("## -- End pasted text --\n")
632 672
633 self._execute_block(block, par)
673 store_or_execute(self.shell, block, name)
634 674
635 675 if sys.platform == 'win32':
636 676 def magic_cls(self, s):
General Comments 0
You need to be logged in to leave comments. Login now