##// END OF EJS Templates
Add %paste magic for direct pasting from the clipboard.
Robert Kern -
Show More
@@ -0,0 +1,56 b''
1 """ Utilities for accessing the platform's clipboard.
2 """
3
4 import subprocess
5 import sys
6
7 from IPython.ipapi import TryNext
8
9
10 def win32_clipboard_get():
11 """ Get the current clipboard's text on Windows.
12
13 Requires Mark Hammond's pywin32 extensions.
14 """
15 try:
16 import win32clipboard
17 except ImportError:
18 message = ("Getting text from the clipboard requires the pywin32 "
19 "extensions: http://sourceforge.net/projects/pywin32/")
20 raise TryNext(message)
21 win32clipboard.OpenClipboard()
22 text = win32clipboard.GetClipboardData(win32clipboard.CF_TEXT)
23 # FIXME: convert \r\n to \n?
24 win32clipboard.CloseClipboard()
25 return text
26
27 def osx_clipboard_get():
28 """ Get the clipboard's text on OS X.
29 """
30 p = subprocess.Popen(['pbpaste', '-Prefer', 'ascii'],
31 stdout=subprocess.PIPE)
32 text, stderr = p.communicate()
33 # Text comes in with old Mac \r line endings. Change them to \n.
34 text = text.replace('\r', '\n')
35 return text
36
37 def tkinter_clipboard_get():
38 """ Get the clipboard's text using Tkinter.
39
40 This is the default on systems that are not Windows or OS X. It may
41 interfere with other UI toolkits and should be replaced with an
42 implementation that uses that toolkit.
43 """
44 try:
45 import Tkinter
46 except ImportError:
47 message = ("Getting text from the clipboard on this platform "
48 "requires Tkinter.")
49 raise TryNext(message)
50 root = Tkinter.Tk()
51 root.withdraw()
52 text = root.clipboard_get()
53 root.destroy()
54 return text
55
56
@@ -3210,6 +3210,61 b' Defaulting color scheme to \'NoColor\'"""'
3210 3210 page(self.shell.pycolorize(cont),
3211 3211 screen_lines=self.shell.rc.screen_length)
3212 3212
3213 def _rerun_pasted(self):
3214 """ Rerun a previously pasted command.
3215 """
3216 b = self.user_ns.get('pasted_block', None)
3217 if b is None:
3218 raise UsageError('No previous pasted block available')
3219 print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))
3220 exec b in self.user_ns
3221
3222 def _get_pasted_lines(self, sentinel):
3223 """ Yield pasted lines until the user enters the given sentinel value.
3224 """
3225 from IPython import iplib
3226 print "Pasting code; enter '%s' alone on the line to stop." % sentinel
3227 while True:
3228 l = iplib.raw_input_original(':')
3229 if l == sentinel:
3230 return
3231 else:
3232 yield l
3233
3234 def _strip_pasted_lines_for_code(self, raw_lines):
3235 """ Strip non-code parts of a sequence of lines to return a block of
3236 code.
3237 """
3238 # Regular expressions that declare text we strip from the input:
3239 strip_re = [r'^\s*In \[\d+\]:', # IPython input prompt
3240 r'^\s*(\s?>)+', # Python input prompt
3241 r'^\s*\.{3,}', # Continuation prompts
3242 r'^\++',
3243 ]
3244
3245 strip_from_start = map(re.compile,strip_re)
3246
3247 lines = []
3248 for l in raw_lines:
3249 for pat in strip_from_start:
3250 l = pat.sub('',l)
3251 lines.append(l)
3252
3253 block = "\n".join(lines) + '\n'
3254 #print "block:\n",block
3255 return block
3256
3257 def _execute_block(self, block, par):
3258 """ Execute a block, or store it in a variable, per the user's request.
3259 """
3260 if not par:
3261 b = textwrap.dedent(block)
3262 self.user_ns['pasted_block'] = b
3263 exec b in self.user_ns
3264 else:
3265 self.user_ns[par] = SList(block.splitlines())
3266 print "Block assigned to '%s'" % par
3267
3213 3268 def magic_cpaste(self, parameter_s=''):
3214 3269 """Allows you to paste & execute a pre-formatted code block from clipboard.
3215 3270
@@ -3239,46 +3294,47 b' Defaulting color scheme to \'NoColor\'"""'
3239 3294 opts,args = self.parse_options(parameter_s,'rs:',mode='string')
3240 3295 par = args.strip()
3241 3296 if opts.has_key('r'):
3242 b = self.user_ns.get('pasted_block', None)
3243 if b is None:
3244 raise UsageError('No previous pasted block available')
3245 print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))
3246 exec b in self.user_ns
3297 self._rerun_pasted()
3247 3298 return
3248 3299
3249 3300 sentinel = opts.get('s','--')
3250 3301
3251 # Regular expressions that declare text we strip from the input:
3252 strip_re = [r'^\s*In \[\d+\]:', # IPython input prompt
3253 r'^\s*(\s?>)+', # Python input prompt
3254 r'^\s*\.{3,}', # Continuation prompts
3255 r'^\++',
3256 ]
3302 block = self._strip_pasted_lines_for_code(
3303 self._get_pasted_lines(sentinel))
3257 3304
3258 strip_from_start = map(re.compile,strip_re)
3305 self._execute_block(block, par)
3306
3307 def magic_paste(self, parameter_s=''):
3308 """Allows you to paste & execute a pre-formatted code block from clipboard.
3259 3309
3260 from IPython import iplib
3261 lines = []
3262 print "Pasting code; enter '%s' alone on the line to stop." % sentinel
3263 while 1:
3264 l = iplib.raw_input_original(':')
3265 if l ==sentinel:
3266 break
3267
3268 for pat in strip_from_start:
3269 l = pat.sub('',l)
3270 lines.append(l)
3271
3272 block = "\n".join(lines) + '\n'
3273 #print "block:\n",block
3274 if not par:
3275 b = textwrap.dedent(block)
3276 self.user_ns['pasted_block'] = b
3277 exec b in self.user_ns
3278 else:
3279 self.user_ns[par] = SList(block.splitlines())
3280 print "Block assigned to '%s'" % par
3281
3310 The text is pulled directly from the clipboard without user
3311 intervention.
3312
3313 The block is dedented prior to execution to enable execution of method
3314 definitions. '>' and '+' characters at the beginning of a line are
3315 ignored, to allow pasting directly from e-mails, diff files and
3316 doctests (the '...' continuation prompt is also stripped). The
3317 executed block is also assigned to variable named 'pasted_block' for
3318 later editing with '%edit pasted_block'.
3319
3320 You can also pass a variable name as an argument, e.g. '%paste foo'.
3321 This assigns the pasted block to variable 'foo' as string, without
3322 dedenting or executing it (preceding >>> and + is still stripped)
3323
3324 '%paste -r' re-executes the block previously entered by cpaste.
3325
3326 IPython statements (magics, shell escapes) are not supported (yet).
3327 """
3328 opts,args = self.parse_options(parameter_s,'r:',mode='string')
3329 par = args.strip()
3330 if opts.has_key('r'):
3331 self._rerun_pasted()
3332 return
3333
3334 text = self.shell.hooks.clipboard_get()
3335 block = self._strip_pasted_lines_for_code(text.splitlines())
3336 self._execute_block(block, par)
3337
3282 3338 def magic_quickref(self,arg):
3283 3339 """ Show a quick reference sheet """
3284 3340 import IPython.usage
@@ -49,6 +49,7 b' __license__ = Release.license'
49 49 __version__ = Release.version
50 50
51 51 import os,bisect
52 import sys
52 53 from genutils import Term,shell
53 54 from pprint import PrettyPrinter
54 55
@@ -58,7 +59,8 b' from pprint import PrettyPrinter'
58 59 __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor', 'result_display',
59 60 'input_prefilter', 'shutdown_hook', 'late_startup_hook',
60 61 'generate_prompt', 'generate_output_prompt','shell_hook',
61 'show_in_pager','pre_prompt_hook', 'pre_runcode_hook']
62 'show_in_pager','pre_prompt_hook', 'pre_runcode_hook',
63 'clipboard_get']
62 64 # vds: <<
63 65
64 66 pformat = PrettyPrinter().pformat
@@ -248,5 +250,20 b' def pre_prompt_hook(self):'
248 250 def pre_runcode_hook(self):
249 251 """ Executed before running the (prefiltered) code in IPython """
250 252 return None
251
252 253
254 def clipboard_get(self):
255 """ Get text from the clipboard.
256 """
257 from IPython.clipboard import (osx_clipboard_get, tkinter_clipboard_get,
258 win32_clipboard_get)
259 if sys.platform == 'win32':
260 chain = [win32_clipboard_get, tkinter_clipboard_get]
261 elif sys.platform == 'darwin':
262 chain = [osx_clipboard_get, tkinter_clipboard_get]
263 else:
264 chain = [tkinter_clipboard_get]
265 dispatcher = CommandChainDispatcher()
266 for func in chain:
267 dispatcher.add(func)
268 text = dispatcher()
269 return text
General Comments 0
You need to be logged in to leave comments. Login now