Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix paste magic on Wayland #13671

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 5 additions & 3 deletions IPython/core/hooks.py
Expand Up @@ -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)
Expand Down
34 changes: 33 additions & 1 deletion 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.

Expand All @@ -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.
"""
Expand All @@ -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.

Expand All @@ -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