leo
5/25/2014 - 9:00 PM

clip_magic.py

"""
Add copy to clipboard from IPython!
To install, just copy it to your profile/startup directory, typically:

    ~/.ipython/profile_default/startup/

Example usage:

    %clip hello world
    # will store "hello world"
    a = [1, 2, 3]
    %clip a
    # will store "[1, 2, 3]"

You can also use it with cell magic

    In [1]: %%clip
       ...: Even multi
       ...: lines
       ...: work!
       ...:

If you don't have a variable named 'clip' you can rely on automagic:

    clip hey man
    a = [1, 2, 3]
    clip a

This is a fork of https://gist.github.com/nova77/clip_magic.py
which enables support for windows (using Tkinter) and adds linux
support for xclip (in additional to xsel) if available.

"""

import sys

if sys.platform == 'darwin':
    from AppKit import NSPasteboard, NSArray
else:
    from subprocess import Popen, PIPE

try:
    from Tkinter import Tk  # optional crossplatform fallback
except ImportError:
    Tk = None

from IPython.core.magic import register_line_cell_magic


def _tkinter_clip(arg):
    if not Tk:
        return False
    r = Tk()
    r.withdraw()
    r.clipboard_clear()
    r.clipboard_append(arg)
    r.destroy()
    return True


def _xsel_clip(arg):
    try:
        p = Popen(['xsel', '-pi'], stdin=PIPE)
        p.communicate(input=arg)
    except OSError:
        return False
    return True


def _xclip_clip(arg):
    try:
        p = Popen(['xclip'], stdin=PIPE)
        p.communicate(input=arg)
    except OSError:
        return False
    return True


def _osx_clip(arg):
    pb = NSPasteboard.generalPasteboard()
    pb.clearContents()
    a = NSArray.arrayWithObject_(arg)
    pb.writeObjects_(a)


def _copy_to_clipboard(arg):
    arg = str(globals().get(arg) or arg)

    if sys.platform == 'darwin':
        _osx_clip(arg)
    elif sys.platform.startswith('linux'):
        if not (_xsel_clip(arg) or _tkinter_clip(arg) or _xclip_clip(arg)):
            raise Exception('clip_magic: Linux requires either python '
                            'Tkinter or xsel/xclip to be installed')
    elif sys.platform.startswith('win32'):
        if not _tkinter_clip(arg):
            raise Exception('clip_magic: Windows requires python Tkinter')
    else:
        raise Exception("clip magic does not support platform %s", sys.platform)

    print 'Copied to clipboard!'


@register_line_cell_magic
def clip(line, cell=None):
    if line and cell:
        cell = '\n'.join((line, cell))

    _copy_to_clipboard(cell or line)

# We delete it to avoid name conflicts for automagic to work
del clip