asweigart / pyperclip

Python module for cross-platform clipboard functions.
https://pypi.python.org/pypi/pyperclip
BSD 3-Clause "New" or "Revised" License
1.68k stars 198 forks source link

termux support #205

Open pekcheey opened 3 years ago

pekcheey commented 3 years ago

Termux is a linux environment on Android devices.

It support cut and paste operations via termux-clipboard-set and termux-clipboard-get commands.

it should be pretty trivial to add Termux to the list of supported environment.

Caveat it might not be enough to detect if the environment is Termux. the command requires the installation of a Termux plugin : Termux:API

I'm not sure how to integrate this. perhaps something like below

check if the environment is Termux:
    if the "termux-clipboard-set" command is available : 
        # set the clipboard
    else : 
        # prompt the user that Termux:API must be installed for pyperclip to work on Termux. 
pekcheey commented 3 years ago

well, I did a quick hack which goes like. probably not all of it is required. but it works for me.

diff --git a/src/pyperclip/__init__.py b/src/pyperclip/__init__.py
index adf3cb8..e506beb 100644
--- a/src/pyperclip/__init__.py
+++ b/src/pyperclip/__init__.py
@@ -65,6 +65,8 @@ from ctypes import c_size_t, sizeof, c_wchar_p, get_errno, c_wchar
 # and not load PyQt4 if it is absent.
 HAS_DISPLAY = os.getenv("DISPLAY", False)

+IS_TERMUX = 'com.termux' in os.getenv("PREFIX", False) 
+
 EXCEPT_MSG = """
     Pyperclip could not find a copy/paste mechanism for your system.
     For more information, please visit https://pyperclip.readthedocs.io/en/latest/index.html#not-implemented-error """
@@ -227,6 +229,34 @@ def init_xclip_clipboard():
     return copy_xclip, paste_xclip

+def init_termux_clipboard():
+    DEFAULT_SELECTION='c'
+    PRIMARY_SELECTION='p'
+
+    def copy_termux(text, primary=False):
+        text = _stringifyText(text) # Converts non-str values to str.
+        selection=DEFAULT_SELECTION
+        if primary:
+            selection=PRIMARY_SELECTION
+        p = subprocess.Popen(['termux-clipboard-set'],
+                             stdin=subprocess.PIPE, close_fds=True)
+        p.communicate(input=text.encode(ENCODING))
+
+    def paste_termux(primary=False):
+        selection=DEFAULT_SELECTION
+        if primary:
+            selection=PRIMARY_SELECTION
+        p = subprocess.Popen(['termux-clipboard-get'],
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.PIPE,
+                             close_fds=True)
+        stdout, stderr = p.communicate()
+        # Intentionally ignore extraneous output on stderr when clipboard is empty
+        return stdout.decode(ENCODING)
+
+    return copy_termux, paste_termux
+
+
 def init_xsel_clipboard():
     DEFAULT_SELECTION='-b'
     PRIMARY_SELECTION='-p'
@@ -518,7 +548,6 @@ def init_wsl_clipboard():

     return copy_wsl, paste_wsl

-
 # Automatic detection of clipboard mechanisms and importing is done in deteremine_clipboard():
 def determine_clipboard():
     '''
@@ -545,6 +574,10 @@ def determine_clipboard():
             if "microsoft" in f.read().lower():
                 return init_wsl_clipboard()

+    if platform.system() == 'Linux' and os.name == 'posix' and IS_TERMUX :
+        return init_termux_clipboard()
+
+
     # Setup for the MAC OS X platform:
     if os.name == 'mac' or platform.system() == 'Darwin':
         try:
@@ -573,8 +606,12 @@ def determine_clipboard():
             return init_xsel_clipboard()
         if _executable_exists("xclip"):
             return init_xclip_clipboard()
+        if _executable_exists("termux-clipboard-get"):
+            return init_termux_clipboard()
         if _executable_exists("klipper") and _executable_exists("qdbus"):
             return init_klipper_clipboard()
+        if _executable_exists("termux-clipboard-set"):
+            return init_termux_clipboard()

         try:
             # qtpy is a small abstraction layer that lets you write applications using a single api call to either PyQt or PySide.
@@ -600,6 +637,7 @@ def determine_clipboard():
     return init_no_clipboard()

+
 def set_clipboard(clipboard):
     '''
     Explicitly sets the clipboard mechanism. The "clipboard mechanism" is how
@@ -623,6 +661,7 @@ def set_clipboard(clipboard):
         "gtk": init_gtk_clipboard,
         "qt": init_qt_clipboard,  # TODO - split this into 'qtpy', 'pyqt4', and 'pyqt5'
         "xclip": init_xclip_clipboard,
+        "termux": init_termux_clipboard,
         "xsel": init_xsel_clipboard,
         "wl-clipboard": init_wl_clipboard,
         "klipper": init_klipper_clipboard,
BlackCatDevel0per commented 2 years ago

I made a small patch (it was necessary for one script using this library), if someone needs it:

pip install pyperclip-termux
Benjamin-Loison commented 2 years ago

The PR #105 did the trick for me while pyperclip-termux doesn't.

NikitaBeloglazov commented 1 year ago

Also, you can use new module, clipman. I wrote about it in Issue #250 ✨

😇 It has built-in Termux support. I will be glad to receive any feedback.