diff --git a/IPython/core/hooks.py b/IPython/core/hooks.py
index c6225c0..2616d0b 100644
--- a/IPython/core/hooks.py
+++ b/IPython/core/hooks.py
@@ -43,8 +43,9 @@ somewhere in your configuration files or ipython command line.
 
 from IPython.core import ipapi
 
-import os,bisect
-from IPython.utils.genutils import Term,shell
+import os, bisect
+import sys
+from IPython.utils.genutils import Term, shell
 from pprint import PrettyPrinter
 
 # List here all the default hooks.  For now it's just the editor functions
@@ -53,7 +54,8 @@ from pprint import PrettyPrinter
 __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor', 'result_display',
            'input_prefilter', 'shutdown_hook', 'late_startup_hook',
            'generate_prompt', 'generate_output_prompt','shell_hook',
-           'show_in_pager','pre_prompt_hook', 'pre_runcode_hook']
+           'show_in_pager','pre_prompt_hook', 'pre_runcode_hook',
+           'clipboard_get']
 # vds: <<
 
 pformat = PrettyPrinter().pformat
@@ -243,5 +245,22 @@ def pre_prompt_hook(self):
 def pre_runcode_hook(self):
     """ Executed before running the (prefiltered) code in IPython """
     return None
-    
 
+def clipboard_get(self):
+    """ Get text from the clipboard.
+    """
+    from IPython.lib.clipboard import (
+        osx_clipboard_get, tkinter_clipboard_get, 
+        win32_clipboard_get
+    )
+    if sys.platform == 'win32':
+        chain = [win32_clipboard_get, tkinter_clipboard_get]
+    elif sys.platform == 'darwin':
+        chain = [osx_clipboard_get, tkinter_clipboard_get]
+    else:
+        chain = [tkinter_clipboard_get]
+    dispatcher = CommandChainDispatcher()
+    for func in chain:
+        dispatcher.add(func)
+    text = dispatcher()
+    return text
diff --git a/IPython/core/magic.py b/IPython/core/magic.py
index aa9fff3..41aefd9 100644
--- a/IPython/core/magic.py
+++ b/IPython/core/magic.py
@@ -3262,6 +3262,61 @@ Defaulting color scheme to 'NoColor'"""
         page(self.shell.pycolorize(cont),
              screen_lines=self.shell.rc.screen_length)
 
+    def _rerun_pasted(self):
+        """ Rerun a previously pasted command.
+        """
+        b = self.user_ns.get('pasted_block', None)
+        if b is None:
+            raise UsageError('No previous pasted block available')
+        print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))
+        exec b in self.user_ns
+
+    def _get_pasted_lines(self, sentinel):
+        """ Yield pasted lines until the user enters the given sentinel value.
+        """
+        from IPython.core import iplib
+        print "Pasting code; enter '%s' alone on the line to stop." % sentinel
+        while True:
+            l = iplib.raw_input_original(':')
+            if l == sentinel:
+                return
+            else:
+                yield l
+
+    def _strip_pasted_lines_for_code(self, raw_lines):
+        """ Strip non-code parts of a sequence of lines to return a block of
+        code.
+        """
+        # Regular expressions that declare text we strip from the input:
+        strip_re =  [r'^\s*In \[\d+\]:', # IPython input prompt
+                     r'^\s*(\s?>)+', # Python input prompt
+                     r'^\s*\.{3,}', # Continuation prompts
+                     r'^\++',
+                     ]
+
+        strip_from_start = map(re.compile,strip_re)
+        
+        lines = []
+        for l in raw_lines:
+            for pat in strip_from_start: 
+                l = pat.sub('',l)
+            lines.append(l)
+                         
+        block = "\n".join(lines) + '\n'
+        #print "block:\n",block
+        return block
+
+    def _execute_block(self, block, par):
+        """ Execute a block, or store it in a variable, per the user's request.
+        """
+        if not par:
+            b = textwrap.dedent(block)
+            self.user_ns['pasted_block'] = b
+            exec b in self.user_ns
+        else:
+            self.user_ns[par] = SList(block.splitlines())
+            print "Block assigned to '%s'" % par
+
     def magic_cpaste(self, parameter_s=''):
         """Allows you to paste & execute a pre-formatted code block from clipboard.
         
@@ -3287,50 +3342,60 @@ Defaulting color scheme to 'NoColor'"""
         will be what was just pasted.
         
         IPython statements (magics, shell escapes) are not supported (yet).
+
+        See also
+        --------
+        %paste: automatically pull code from clipboard.
         """
+        
         opts,args = self.parse_options(parameter_s,'rs:',mode='string')
         par = args.strip()
         if opts.has_key('r'):
-            b = self.user_ns.get('pasted_block', None)
-            if b is None:
-                raise UsageError('No previous pasted block available')
-            print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))
-            exec b in self.user_ns
+            self._rerun_pasted()
             return
         
         sentinel = opts.get('s','--')
 
-        # Regular expressions that declare text we strip from the input:
-        strip_re =  [r'^\s*In \[\d+\]:', # IPython input prompt
-                     r'^\s*(\s?>)+', # Python input prompt
-                     r'^\s*\.{3,}', # Continuation prompts
-                     r'^\++',
-                     ]
+        block = self._strip_pasted_lines_for_code(
+            self._get_pasted_lines(sentinel))
 
-        strip_from_start = map(re.compile,strip_re)
+        self._execute_block(block, par)
+
+    def magic_paste(self, parameter_s=''):
+        """Allows you to paste & execute a pre-formatted code block from clipboard.
         
-        from IPython.core import iplib
-        lines = []
-        print "Pasting code; enter '%s' alone on the line to stop." % sentinel
-        while 1:
-            l = iplib.raw_input_original(':')
-            if l ==sentinel:
-                break
-            
-            for pat in strip_from_start: 
-                l = pat.sub('',l)
-            lines.append(l)
-                         
-        block = "\n".join(lines) + '\n'
-        #print "block:\n",block
-        if not par:
-            b = textwrap.dedent(block)
-            self.user_ns['pasted_block'] = b
-            exec b in self.user_ns
-        else:
-            self.user_ns[par] = SList(block.splitlines())
-            print "Block assigned to '%s'" % par
-            
+        The text is pulled directly from the clipboard without user
+        intervention.
+
+        The block is dedented prior to execution to enable execution of method
+        definitions. '>' and '+' characters at the beginning of a line are
+        ignored, to allow pasting directly from e-mails, diff files and
+        doctests (the '...' continuation prompt is also stripped).  The
+        executed block is also assigned to variable named 'pasted_block' for
+        later editing with '%edit pasted_block'.
+        
+        You can also pass a variable name as an argument, e.g. '%paste foo'.
+        This assigns the pasted block to variable 'foo' as string, without 
+        dedenting or executing it (preceding >>> and + is still stripped)
+        
+        '%paste -r' re-executes the block previously entered by cpaste.
+        
+        IPython statements (magics, shell escapes) are not supported (yet).
+
+        See also
+        --------
+        %cpaste: manually paste code into terminal until you mark its end.
+        """
+        opts,args = self.parse_options(parameter_s,'r:',mode='string')
+        par = args.strip()
+        if opts.has_key('r'):
+            self._rerun_pasted()
+            return
+
+        text = self.shell.hooks.clipboard_get()
+        block = self._strip_pasted_lines_for_code(text.splitlines())
+        self._execute_block(block, par)
+
     def magic_quickref(self,arg):
         """ Show a quick reference sheet """
         import IPython.core.usage
diff --git a/IPython/core/tests/test_magic.py b/IPython/core/tests/test_magic.py
index 6e48d30..588adc4 100644
--- a/IPython/core/tests/test_magic.py
+++ b/IPython/core/tests/test_magic.py
@@ -252,3 +252,39 @@ class TestMagicRun(object):
 
     def teardown(self):
         self.tmpfile.close()
+
+# Multiple tests for clipboard pasting
+def test_paste():
+
+    def paste(txt):
+        hooks.clipboard_get = lambda : txt
+        _ip.magic('paste')
+
+    # Inject fake clipboard hook but save original so we can restore it later
+    hooks = _ip.IP.hooks
+    user_ns = _ip.user_ns
+    original_clip = hooks.clipboard_get
+
+    try:
+        # Run tests with fake clipboard function
+        user_ns.pop('x', None)
+        paste('x=1')
+        yield (nt.assert_equal, user_ns['x'], 1)
+
+        user_ns.pop('x', None)
+        paste('>>> x=2')
+        yield (nt.assert_equal, user_ns['x'], 2)
+
+        paste("""
+        >>> x = [1,2,3]
+        >>> y = []
+        >>> for i in x:
+        ...     y.append(i**2)
+        ...
+        """)
+        yield (nt.assert_equal, user_ns['x'], [1,2,3])
+        yield (nt.assert_equal, user_ns['y'], [1,4,9])
+
+    finally:
+        # Restore original hook
+        hooks.clipboard_get = original_clip
diff --git a/IPython/lib/clipboard.py b/IPython/lib/clipboard.py
new file mode 100644
index 0000000..6607f6e
--- /dev/null
+++ b/IPython/lib/clipboard.py
@@ -0,0 +1,56 @@
+""" Utilities for accessing the platform's clipboard.
+"""
+
+import subprocess
+import sys
+
+from IPython.ipapi import TryNext
+
+
+def win32_clipboard_get():
+    """ Get the current clipboard's text on Windows.
+
+    Requires Mark Hammond's pywin32 extensions.
+    """
+    try:
+        import win32clipboard
+    except ImportError:
+        message = ("Getting text from the clipboard requires the pywin32 "
+            "extensions: http://sourceforge.net/projects/pywin32/")
+        raise TryNext(message)
+    win32clipboard.OpenClipboard() 
+    text = win32clipboard.GetClipboardData(win32clipboard.CF_TEXT) 
+    # FIXME: convert \r\n to \n?
+    win32clipboard.CloseClipboard() 
+    return text
+
+def osx_clipboard_get():
+    """ Get the clipboard's text on OS X.
+    """
+    p = subprocess.Popen(['pbpaste', '-Prefer', 'ascii'],
+        stdout=subprocess.PIPE)
+    text, stderr = p.communicate()
+    # Text comes in with old Mac \r line endings. Change them to \n.
+    text = text.replace('\r', '\n')
+    return text
+
+def tkinter_clipboard_get():
+    """ Get the clipboard's text using Tkinter.
+
+    This is the default on systems that are not Windows or OS X. It may
+    interfere with other UI toolkits and should be replaced with an
+    implementation that uses that toolkit.
+    """
+    try:
+        import Tkinter
+    except ImportError:
+        message = ("Getting text from the clipboard on this platform "
+            "requires Tkinter.")
+        raise TryNext(message)
+    root = Tkinter.Tk()
+    root.withdraw()
+    text = root.clipboard_get()
+    root.destroy()
+    return text
+
+