Skip to content
This repository was archived by the owner on Oct 15, 2025. It is now read-only.

Commit 5f4f98b

Browse files
committed
[cliphist] Add cliphist extension
1 parent 53c4bdd commit 5f4f98b

1 file changed

Lines changed: 75 additions & 0 deletions

File tree

cliphist/__init__.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import albert as al
2+
import subprocess as sp
3+
import time
4+
5+
md_iid = "3.0"
6+
md_version = "1.0"
7+
md_name = "ClipHist"
8+
md_description = "Access cliphist clipboard"
9+
md_license = "MIT"
10+
md_url = "https://github.com/albertlauncher/python/tree/main/cliphist"
11+
md_authors = ["@ivomac"]
12+
md_bin_dependencies = ["cliphist"]
13+
14+
15+
def copy(item: str):
16+
"""Copy an entry from cliphist to the clipboard."""
17+
clip_entry = sp.run(["cliphist", "decode"], input=item, stdout=sp.PIPE, text=True)
18+
19+
al.setClipboardText(clip_entry.stdout)
20+
21+
22+
def delete(item: str):
23+
"""Delete an entry from cliphist."""
24+
sp.run(["cliphist", "delete"], input=item, text=True)
25+
26+
27+
def wipe():
28+
"""Delete all entries from cliphist."""
29+
sp.run(["cliphist", "wipe"], text=True)
30+
31+
32+
class Plugin(al.PluginInstance, al.TriggerQueryHandler):
33+
iconUrls = ["xdg:clipboard"]
34+
35+
def __init__(self):
36+
al.PluginInstance.__init__(self)
37+
al.TriggerQueryHandler.__init__(self)
38+
39+
def defaultTrigger(self):
40+
return "ch "
41+
42+
def handleTriggerQuery(self, query):
43+
for _ in range(5):
44+
time.sleep(0.02)
45+
if not query.isValid:
46+
return
47+
48+
plug_id = self.id()
49+
50+
matcher = al.Matcher(query.string)
51+
52+
# Get the list of cliphist entries
53+
clip_history = sp.run(["cliphist", "list"], stdout=sp.PIPE, text=True).stdout
54+
55+
# cliphist items are in the format:
56+
# <id>\t<approximate text>
57+
splits = [(item, *item.split("\t", 1)) for item in clip_history.strip().splitlines()]
58+
59+
query.add(
60+
[
61+
al.StandardItem(
62+
id=plug_id,
63+
iconUrls=self.iconUrls,
64+
text=text,
65+
subtext=idx,
66+
actions=[
67+
al.Action("copy", "Copy", lambda u=item: copy(u)),
68+
al.Action("delete", "Delete", lambda u=item: delete(u)),
69+
al.Action("wipe", "Wipe", lambda: wipe()),
70+
],
71+
)
72+
for item, idx, text in splits
73+
if matcher.match(item)
74+
]
75+
)

0 commit comments

Comments
 (0)