How many times have you needed to paste the same copied text multiple times?
How many times have you needed to copy multiple pieces of texts and paste it without switching windows?
For me personally, the second count was much bigger than the first. Hence, this.
clipstack stores your clipboard contents in a stack. Copying text pushes to the stack. Pasting pops it. As simple as that!
Did you actually want to paste that thing at two places? No worries, just copy it twice!
High quality original speed video here
- Pushes whatever you copy to a stack. Pasting pops it from the stack.
clipstackis written in a very modular way. Classes likeClipboardSpycan be used independently for other tasks.- Don't like the stack based
ContentManager? Implement your own! See content_manager.py for example implementations. - Want to make your clipboard data persistent? Make your
ContentManagerstore and retrieve data from a database. You can even share your clipboard across multiple machines! (use a common source for both content managers, for example,redis). The only limit is your imagination.
- Don't like the stack based
- Event-based. No constantly running loops. (i.e., CPU usage when idle is very low / 0).
- The only dependency is
python-xlib.
python3- You should be using the X window system
pip install git+https://github.com/yoogottamk/clipstack.gitpython3 -m clipstackBy default, this ignores all images and stores the clipboard contents on a stack.
There is no configuration file. If you want clipstack to behave differently, you can write a simple python file similar to __main__.py and run that instead of clipstack.
In X, clipboards (selections) work in a special way. We are interested in the CLIPBOARD selection only, and I'll be referring it to as clipboard from now on. When you copy something from an application, say A, that application becomes the "owner" of that selection. When you paste something to an application, say B, B "contacts" A for the contents. Nothing is actually copied until B "contacts" A. Check the references for a better explanation.
There are 2 components that make this work:
ClipboardSpyClipboard
Whenever the owner of clipboard changes, this is notified. This then passes on the contents to Clipboard.
When this gets the contents from ClipboardSpy, it claims ownership for clipboard, basically "stealing" it from the actual application. This "knows" (in a very hacky way, see Issues) when the content has been pasted.
If some other application takes the ownership from Clipboard during this, we wait for ClipboardSpy to pass it on here again.
INCRand maybe more protocols that I don't even know about are not supported by bothClipboardSpyandClipboard. WithoutINCR, it might not be possible to copy/paste very large chunks.- Images don't work for now and
clipstackactively ignores it. When you copy an image,clipstackwill stop running until you copy a supported content again. For now, only images are being ignored. If you find another type that is not supported, kindly open an issue (or a PR 😛). - Applications are weird. None of them follow a consistent selection request pattern. A very weird hack [check function
_check_update_contents] had to be used in order to get around this problem. A consequence of this hack is that pasting multiple times "very fast" is not supported. Currently, the timeout is 200ms but I might change it if I find that this is too short or too long. - The interface for
clipboard.pyis bad, it should be as easy to use asClipboardSpy. - Not memory efficient. Maybe someone only copies and never pastes? They would fill the stack without emptying it and it might take a lot of memory. I don't see this happening in a normal scenario though.
If you face an issue or want to work on this, you can change the logging level in __main__.py to get more logs. If you plan on opening an issue, please provide the logs and the actions that you followed.
I don't know a lot about X and this was mostly created (in less than a day) by searching stackoverflow, open source code and sometimes translating it to python. Due to this, some of the identifier names might not make sense, some doc strings might be wrong or much better ways might exist of doing what this is doing. If you find any such issues, please educate me 🙏.
- https://www.jwz.org/doc/x-cut-and-paste.html
- https://www.uninformativ.de/blog/postings/2017-04-02/0/POSTING-en.html
- https://stackoverflow.com/questions/8755471/
- https://stackoverflow.com/a/44992938/10627913
- https://stackoverflow.com/a/44992320
- https://github.com/python-xlib/python-xlib/tree/master/examples
