diff --git a/IPython/core/hooks.py b/IPython/core/hooks.py index 09b08d942e0..f73c5657638 100644 --- a/IPython/core/hooks.py +++ b/IPython/core/hooks.py @@ -155,15 +155,17 @@ def clipboard_get(self): """ Get text from the clipboard. """ from ..lib.clipboard import ( - osx_clipboard_get, tkinter_clipboard_get, - win32_clipboard_get + osx_clipboard_get, + tkinter_clipboard_get, + win32_clipboard_get, + wayland_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] + chain = [wayland_clipboard_get, tkinter_clipboard_get] dispatcher = CommandChainDispatcher() for func in chain: dispatcher.add(func) diff --git a/IPython/lib/clipboard.py b/IPython/lib/clipboard.py index 95a6b0a0a34..1d691a7ea63 100644 --- a/IPython/lib/clipboard.py +++ b/IPython/lib/clipboard.py @@ -1,14 +1,16 @@ """ 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. @@ -32,6 +34,7 @@ def win32_clipboard_get(): win32clipboard.CloseClipboard() return text + def osx_clipboard_get() -> str: """ Get the clipboard's text on OS X. """ @@ -43,6 +46,7 @@ def osx_clipboard_get() -> str: text = py3compat.decode(bytes_) return text + def tkinter_clipboard_get(): """ Get the clipboard's text using Tkinter. @@ -67,3 +71,31 @@ def tkinter_clipboard_get(): 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