feat: clipboard menu
This commit is contained in:
@@ -56,6 +56,7 @@ def _action(name: str) -> Callable[[argparse.Namespace], None]:
|
|||||||
COMMANDS: list[Command] = [
|
COMMANDS: list[Command] = [
|
||||||
Command("finder", "open window finder", _action("open-finder")),
|
Command("finder", "open window finder", _action("open-finder")),
|
||||||
Command("apps", "open application launcher", _action("open-app-launcher")),
|
Command("apps", "open application launcher", _action("open-app-launcher")),
|
||||||
|
Command("clipboard", "open clipboard history picker", _action("open-clipboard-menu")),
|
||||||
Command("power", "open power menu", _action("open-power-menu")),
|
Command("power", "open power menu", _action("open-power-menu")),
|
||||||
Command("screenshot", "open screenshot menu", _action("open-screenshot-menu")),
|
Command("screenshot", "open screenshot menu", _action("open-screenshot-menu")),
|
||||||
Command("notmuch-refresh", "refresh unread mail count", _action("refresh-notmuch")),
|
Command("notmuch-refresh", "refresh unread mail count", _action("refresh-notmuch")),
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ from fabric.utils import (
|
|||||||
from .modules.bar import StatusBar
|
from .modules.bar import StatusBar
|
||||||
from .modules.window_fuzzy import FuzzyWindowFinder
|
from .modules.window_fuzzy import FuzzyWindowFinder
|
||||||
from .modules.launcher.apps import AppLauncher
|
from .modules.launcher.apps import AppLauncher
|
||||||
|
from .modules.launcher.clipboard import ClipboardMenu
|
||||||
from .modules.launcher.power import PowerMenu
|
from .modules.launcher.power import PowerMenu
|
||||||
from .modules.launcher.screenrec import ScreenrecMenu
|
from .modules.launcher.screenrec import ScreenrecMenu
|
||||||
from .modules.launcher.screenshot import ScreenshotMenu
|
from .modules.launcher.screenshot import ScreenshotMenu
|
||||||
@@ -36,6 +37,7 @@ get_i3_connection()
|
|||||||
dummy = Window(visible=False)
|
dummy = Window(visible=False)
|
||||||
finder = FuzzyWindowFinder()
|
finder = FuzzyWindowFinder()
|
||||||
app_launcher = AppLauncher()
|
app_launcher = AppLauncher()
|
||||||
|
clipboard_menu = ClipboardMenu()
|
||||||
power_menu = PowerMenu(lock_command=POWER.get("lock_command", ["waylock"]))
|
power_menu = PowerMenu(lock_command=POWER.get("lock_command", ["waylock"]))
|
||||||
screenshot_menu = ScreenshotMenu()
|
screenshot_menu = ScreenshotMenu()
|
||||||
|
|
||||||
@@ -50,7 +52,7 @@ if SCREENREC.get("enable", False):
|
|||||||
bar_windows = []
|
bar_windows = []
|
||||||
notmuch_widget = None
|
notmuch_widget = None
|
||||||
|
|
||||||
_app_windows = [dummy, finder, app_launcher, power_menu, screenshot_menu]
|
_app_windows = [dummy, finder, app_launcher, clipboard_menu, power_menu, screenshot_menu]
|
||||||
if screenrec_menu is not None:
|
if screenrec_menu is not None:
|
||||||
_app_windows.append(screenrec_menu)
|
_app_windows.append(screenrec_menu)
|
||||||
app = Application("sims", *_app_windows)
|
app = Application("sims", *_app_windows)
|
||||||
@@ -66,6 +68,11 @@ def open_app_launcher():
|
|||||||
app_launcher.show()
|
app_launcher.show()
|
||||||
|
|
||||||
|
|
||||||
|
@Application.action()
|
||||||
|
def open_clipboard_menu():
|
||||||
|
clipboard_menu.show()
|
||||||
|
|
||||||
|
|
||||||
@Application.action()
|
@Application.action()
|
||||||
def open_power_menu():
|
def open_power_menu():
|
||||||
power_menu.show()
|
power_menu.show()
|
||||||
|
|||||||
74
sims/modules/launcher/clipboard.py
Normal file
74
sims/modules/launcher/clipboard.py
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import subprocess
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from fabric.widgets.box import Box
|
||||||
|
from fabric.widgets.label import Label
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
from .base import FuzzyMenu
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ClipEntry:
|
||||||
|
raw: str # full "<id>\t<preview>" line as emitted by cliphist
|
||||||
|
preview: str
|
||||||
|
|
||||||
|
|
||||||
|
class ClipboardProvider:
|
||||||
|
def items(self) -> list[ClipEntry]:
|
||||||
|
proc = subprocess.run(
|
||||||
|
["cliphist", "list"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
if proc.returncode != 0:
|
||||||
|
return []
|
||||||
|
entries: list[ClipEntry] = []
|
||||||
|
for line in proc.stdout.splitlines():
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
_id, sep, preview = line.partition("\t")
|
||||||
|
if not sep:
|
||||||
|
continue
|
||||||
|
entries.append(ClipEntry(raw=line, preview=preview))
|
||||||
|
return entries
|
||||||
|
|
||||||
|
def filter(self, items: list[ClipEntry], query: str) -> list[ClipEntry]:
|
||||||
|
if not query:
|
||||||
|
return items
|
||||||
|
q = query.lower()
|
||||||
|
return [e for e in items if q in e.preview.lower()]
|
||||||
|
|
||||||
|
def render(self, item: ClipEntry) -> Gtk.Widget:
|
||||||
|
return Box(
|
||||||
|
name="slot-box",
|
||||||
|
orientation="h",
|
||||||
|
children=[
|
||||||
|
Label(
|
||||||
|
label=item.preview,
|
||||||
|
h_align="start",
|
||||||
|
ellipsization="end",
|
||||||
|
name="clip-preview",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
def activate(self, item: ClipEntry) -> None:
|
||||||
|
decoded = subprocess.run(
|
||||||
|
["cliphist", "decode"],
|
||||||
|
input=item.raw.encode("utf-8"),
|
||||||
|
capture_output=True,
|
||||||
|
)
|
||||||
|
if decoded.returncode != 0:
|
||||||
|
return
|
||||||
|
subprocess.run(["wl-copy"], input=decoded.stdout)
|
||||||
|
|
||||||
|
|
||||||
|
def ClipboardMenu(monitor: int = 0) -> FuzzyMenu:
|
||||||
|
return FuzzyMenu(
|
||||||
|
provider=ClipboardProvider(),
|
||||||
|
monitor=monitor,
|
||||||
|
placeholder="Clipboard...",
|
||||||
|
window_name="clipboard-menu",
|
||||||
|
max_results=12,
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user