From 70f55876e24f022d3a17bd4cc9c77303ed0c395e Mon Sep 17 00:00:00 2001 From: Ivo Maceira Date: Thu, 24 Apr 2025 16:26:25 +0200 Subject: [PATCH] [cliphist] Add cliphist extension --- cliphist/__init__.py | 95 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 cliphist/__init__.py diff --git a/cliphist/__init__.py b/cliphist/__init__.py new file mode 100644 index 00000000..72844ef6 --- /dev/null +++ b/cliphist/__init__.py @@ -0,0 +1,95 @@ +import albert as al +import subprocess as sp +import time + +md_iid = "3.0" +md_version = "1.0" +md_name = "ClipHist" +md_description = "Access cliphist clipboard" +md_license = "MIT" +md_url = "https://github.com/albertlauncher/python/tree/main/cliphist" +md_authors = ["@ivomac"] +md_bin_dependencies = ["cliphist"] + + +def delete(entry: str): + """Delete an entry from the cliphist history.""" + + sp.run( + ["cliphist", "delete"], + input=entry, + stdout=sp.PIPE, + text=True, + ).stdout + + return + + +def copy(entry: str): + """Copy an entry from the cliphist history to the clipboard.""" + + clip_entry = sp.run( + ["cliphist", "decode"], + input=entry, + stdout=sp.PIPE, + text=True, + ).stdout + + al.setClipboardText(clip_entry) + + return + + +class Plugin(al.PluginInstance, al.TriggerQueryHandler): + iconUrls = ["xdg:clipboard"] + + def __init__(self): + al.PluginInstance.__init__(self) + al.TriggerQueryHandler.__init__(self) + + def defaultTrigger(self): + return "cl " + + def handleTriggerQuery(self, query): + for _ in range(5): + time.sleep(0.02) + if not query.isValid: + return + + plug_id = self.id() + + matcher = al.Matcher(query.string) + + # Get the list of cliphist entries + clip_history = ( + sp.run( + ["cliphist", "list"], + stdout=sp.PIPE, + text=True, + ) + .stdout.strip() + .splitlines() + ) + + # cliphist items are in the format: + # \t + splits = [(item, *item.split("\t", 1)) for item in clip_history] + + query.add( + [ + al.StandardItem( + id=plug_id, + iconUrls=self.iconUrls, + text=text, + subtext=idx, + actions=[ + al.Action("copy", "Copy", lambda u=item: copy(u)), + al.Action("delete", "Delete", lambda u=item: delete(u)), + ], + ) + for item, idx, text in splits + if matcher.match(item) + ] + ) + + return