|
""" Utilities for accessing the platform's clipboard. |
|
""" |
|
import os |
|
import subprocess |
|
|
|
from IPython.core.error import TryNext |
|
import IPython.utils.py3compat as py3compat |
|
|
|
|
|
class ClipboardEmpty(ValueError): |
|
pass |
|
|
|
|
|
def win32_clipboard_get(): |
|
""" Get the current clipboard's text on Windows. |
|
|
|
Requires Mark Hammond's pywin32 extensions. |
|
""" |
|
try: |
|
import win32clipboard |
|
except ImportError as e: |
|
raise TryNext("Getting text from the clipboard requires the pywin32 " |
|
"extensions: http://sourceforge.net/projects/pywin32/") from e |
|
win32clipboard.OpenClipboard() |
|
try: |
|
text = win32clipboard.GetClipboardData(win32clipboard.CF_UNICODETEXT) |
|
except (TypeError, win32clipboard.error): |
|
try: |
|
text = win32clipboard.GetClipboardData(win32clipboard.CF_TEXT) |
|
text = py3compat.cast_unicode(text, py3compat.DEFAULT_ENCODING) |
|
except (TypeError, win32clipboard.error) as e: |
|
raise ClipboardEmpty from e |
|
finally: |
|
win32clipboard.CloseClipboard() |
|
return text |
|
|
|
|
|
def osx_clipboard_get() -> str: |
|
""" Get the clipboard's text on OS X. |
|
""" |
|
p = subprocess.Popen(['pbpaste', '-Prefer', 'ascii'], |
|
stdout=subprocess.PIPE) |
|
bytes_, stderr = p.communicate() |
|
|
|
bytes_ = bytes_.replace(b'\r', b'\n') |
|
text = py3compat.decode(bytes_) |
|
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: |
|
from tkinter import Tk, TclError |
|
except ImportError as e: |
|
raise TryNext("Getting text from the clipboard on this platform requires tkinter.") from e |
|
|
|
root = Tk() |
|
root.withdraw() |
|
try: |
|
text = root.clipboard_get() |
|
except TclError as e: |
|
raise ClipboardEmpty from e |
|
finally: |
|
root.destroy() |
|
text = py3compat.cast_unicode(text, py3compat.DEFAULT_ENCODING) |
|
return text |
|
|
|
|
|
def wayland_clipboard_get(): |
|
"""Get the clipboard's text under Wayland using wl-paste command. |
|
|
|
This requires Wayland and wl-clipboard installed and running. |
|
""" |
|
if os.environ.get("XDG_SESSION_TYPE") != "wayland": |
|
raise TryNext("wayland is not detected") |
|
|
|
try: |
|
with subprocess.Popen(["wl-paste"], stdout=subprocess.PIPE) as p: |
|
raw, err = p.communicate() |
|
if p.wait(): |
|
raise TryNext(err) |
|
except FileNotFoundError as e: |
|
raise TryNext( |
|
"Getting text from the clipboard under Wayland requires the wl-clipboard " |
|
"extension: https://github.com/bugaevc/wl-clipboard" |
|
) from e |
|
|
|
if not raw: |
|
raise ClipboardEmpty |
|
|
|
try: |
|
text = py3compat.decode(raw) |
|
except UnicodeDecodeError as e: |
|
raise ClipboardEmpty from e |
|
|
|
return text |
|
|