简体   繁体   中英

Store clipboard history in file using Python on mac

I need copy some words from a text and I would like to store the copied words in a file. Basically a file with the clipboard history.

Since the copying of words is a continuous process I need to use a loop that stores the copied words during the performance. I figured it would be handy to use a action/event listener to 1) store the clipboard data to file when cmd + x is pressed and 2) end loop when, for instance cmd + q is pressed.

I am not very familiar with action/event listeners, and not sure how I should go about using them. Are there any easy implementations I could use?

I have what is mostly a pseudo code, that describes what I would like to accomplish. Any suggestions are appreciated!

import pyperclip
import os
import os.path
import time

save_path = "/Users/username/file"
FileName = os.path.join(save_path, "clipboard.txt")         
f= open(FileName, "w")    

text = pyperclip.paste()  # text will have the content of clipboard

x = 0
while True:
    time.sleep(2) #Replace with-->: wait for "cmd + x" to be pressed
    text = pyperclip.paste()  # text will have the content of clipboard
    f.write(text+"\n")
    x += 1
    if x > 10: #Replace with --> break if "cmd + q" is pressed 
        break

f.close()
print("End of session")

The code above waits 2 seconds before copying the text from the clipboard to the file. Loop reaches its end after 10 iterations.

I would the code to react to actions performed so that I could store all copied words into a single file.

EDIT: Using the suggestions in the replies to the question I tried solving the problem in two ways, one with keyboard and pynput module. Keyboard did not work for me, might be due to me using Mac? It did not react as intended when pressing a key.

Keyboard code # (Does not work)

while True:
    try:
        if keyboard.is_pressed('c'):
            print('Copying the selected')
            text = pyperclip.paste()  # text will have the content of clipboard
            f.write(text+"\n")
            sleep(0.1)  # Avoiding long press, remove to see effect
            # Your Code
        elif keyboard.is_pressed('esc'):
            print('Exiting Code')
            break
    except Exception as error:
        print(error)
f.close()

Problem: When pressing the key 'c', nothing happens. The print statement does not activate.

pynput code # (Works)

def on_release(key):
    if str(key) == "'c'":
        print('Copying the slected')
        text = pyperclip.paste()  # text will have the content of clipboard
        f.write(text+"\n")

    print('{0} release'.format(
        key))
    if key == Key.esc:
        # Stop listener
        f.close()
        print("End")
        return False


# Collect events until released
with Listener(
        on_release=on_release) as listener:
    listener.join()

pynput worked as intended, in the way that everytime 'c' key is pressed, as is done when using cmd + c to copy, it copies the currently stored text in clipboard to the text file.

(minor) Problem: I did not get pynput to react on the combination of pressing cmd + c simultaneosly. However that did not matter in this case, as reacting to the key press 'c' is enough. For future references though, please comment if you know how to listen for a combination of keys.

I tried the following, which neither one worked:

if key == Key.cmd and str(key) == "'c'":
        print('Copying the selected')

and

if key == Key.cmd:
    if str(key) == "'c'":
        print('Copying the selected')

You should use the keyboard library for python in this case https://pypi.org/project/keyboard/

The basic structure for your code would look something like this

import keyboard
from time import sleep

while True:
    try:
        if keyboard.is_pressed('ctrl+c'):
            print('Copying the slected')
            sleep(0.1)  # Avoiding long press, remove to see effect
            # Your Code

        elif keyboard.is_pressed('esc'):
            print('Exiting Code')
            break

    except Exception as error:
        print(error)

You can try this one use pynput, a function support multi combination keys mapping arbitrary custom functions, just put them into a dict:

def multi_hotkey_listen(hotkey_dict):
    """Multi-hotkey listen"""

    # Create a mapping of hot keys to function, use hashable frozenset as keys
    # Original set type is not hashable - so they can't be used as keys of dict
    frozen_hotkey_dict = {frozenset(k.split('+')): v for k, v in hotkey_dict.items()}
    # Currently pressed keys
    current_keys = set()

    def on_press(key):
        """When a key is pressed, add it to the set we are keeping track of
        and check if this set is in the dictionary"""
        try:
            key_str = key.char
        except AttributeError:
            key_str = key.name

        current_keys.add(key_str)
        # print(current_keys)

        if frozenset(current_keys) in frozen_hotkey_dict:
            # If the current set of keys are in the mapping, execute the function
            trigger_func = frozen_hotkey_dict[frozenset(current_keys)]
            print(f'Success:function {trigger_func.__name__} be triggered', )
            trigger_func()

    def on_release(key):
        """When a key is released, remove it from the set of keys we are keeping track of"""
        try:
            key_str = key.char
        except AttributeError:
            key_str = key.name
        current_keys.remove(key_str)

    with KeyboardListener(on_press=on_press, on_release=on_release, suppress=False) as listener:
        listener.join()


hotkey_dict = {
    'cmd+x': save_data  # support combination key like ctrl+shift+1
    'cmd+q': end_loop,
}

multi_hotkey_listen(hotkey_dict)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM