✨ feat(launcher/plugins): add ability to load custom plugins
This commit is contained in:
1 file changed
-187
@@ -1,187 +0,0 @@
|
||||
"""
|
||||
Scripts plugin for the launcher.
|
||||
Provides access to various system scripts and utilities.
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
from typing import List
|
||||
|
||||
from fabric.utils import exec_shell_command_async
|
||||
import utils.icons as icons
|
||||
from modules.launcher.plugin_base import PluginBase
|
||||
from modules.launcher.result import Result
|
||||
|
||||
|
||||
class ScriptsPlugin(PluginBase):
|
||||
"""
|
||||
Plugin for executing system scripts and utilities.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.display_name = "Scripts"
|
||||
self.description = "System scripts and utilities"
|
||||
|
||||
def initialize(self):
|
||||
"""Initialize the scripts plugin."""
|
||||
# Use individual trigger keywords for each specific action
|
||||
self.set_triggers([
|
||||
# Color picker variants
|
||||
"color hex",
|
||||
"color rgb",
|
||||
"color hsv",
|
||||
|
||||
# Night light
|
||||
"night"
|
||||
|
||||
])
|
||||
|
||||
def cleanup(self):
|
||||
"""Cleanup the scripts plugin."""
|
||||
pass
|
||||
|
||||
|
||||
def _run_colorpicker(self, format_type: str):
|
||||
"""Run color picker with specified format."""
|
||||
script_path = self._get_script_path("hyprpicker.sh")
|
||||
exec_shell_command_async(f"bash '{script_path}' -{format_type}")
|
||||
|
||||
|
||||
|
||||
def _get_script_path(self, script_name: str) -> str:
|
||||
"""Get the full path to a script from the scripts directory."""
|
||||
# Get the current working directory (should be Modus root)
|
||||
current_dir = os.getcwd()
|
||||
|
||||
# Try scripts directory relative to current working directory
|
||||
script_path = os.path.join(current_dir, "scripts", script_name)
|
||||
if os.path.exists(script_path):
|
||||
return script_path
|
||||
|
||||
# Try relative to this file's location
|
||||
plugin_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
modus_root = os.path.dirname(os.path.dirname(os.path.dirname(plugin_dir)))
|
||||
script_path = os.path.join(modus_root, "scripts", script_name)
|
||||
if os.path.exists(script_path):
|
||||
return script_path
|
||||
|
||||
# Fallback to relative path
|
||||
return f"scripts/{script_name}"
|
||||
|
||||
def _get_trigger_actions(self) -> dict:
|
||||
"""Get the map of trigger patterns to actions."""
|
||||
|
||||
return {
|
||||
# Color picker triggers
|
||||
"color hex": {
|
||||
"title": "Color Picker (HEX)",
|
||||
"subtitle": "Pick a color and copy HEX value to clipboard",
|
||||
"icon": icons.colorpicker,
|
||||
"action": lambda: self._run_colorpicker("hex"),
|
||||
},
|
||||
"color rgb": {
|
||||
"title": "Color Picker (RGB)",
|
||||
"subtitle": "Pick a color and copy RGB value to clipboard",
|
||||
"icon": icons.colorpicker,
|
||||
"action": lambda: self._run_colorpicker("rgb"),
|
||||
},
|
||||
"color hsv": {
|
||||
"title": "Color Picker (HSV)",
|
||||
"subtitle": "Pick a color and copy HSV value to clipboard",
|
||||
"icon": icons.colorpicker,
|
||||
"action": lambda: self._run_colorpicker("hsv"),
|
||||
},
|
||||
|
||||
# Night light triggers
|
||||
"night": {
|
||||
"title": "Toggle Night Light",
|
||||
"subtitle": "Toggle blue light filter for eye comfort",
|
||||
"icon": icons.night,
|
||||
"action": lambda: self._run_system_command("hyprctl keyword decoration:screen_shader ~/.config/hypr/shaders/blue_light_filter.glsl"),
|
||||
}
|
||||
}
|
||||
|
||||
def query(self, query_string: str) -> List[Result]:
|
||||
"""Search for script actions based on query."""
|
||||
query = query_string.strip().lower()
|
||||
results = []
|
||||
|
||||
# Get trigger actions
|
||||
trigger_actions = self._get_trigger_actions()
|
||||
|
||||
# If no query, return empty results (don't show all actions)
|
||||
if not query:
|
||||
return []
|
||||
|
||||
# Check if query exactly matches one of our triggers
|
||||
# If so, show only that specific result
|
||||
for trigger_key in trigger_actions:
|
||||
if query == trigger_key.lower():
|
||||
action_data = trigger_actions[trigger_key]
|
||||
return [Result(
|
||||
title=action_data["title"],
|
||||
subtitle=action_data["subtitle"],
|
||||
icon_markup=action_data["icon"],
|
||||
action=action_data["action"],
|
||||
relevance=1.0,
|
||||
plugin_name=self.display_name,
|
||||
data={"trigger": trigger_key}
|
||||
)]
|
||||
|
||||
# Search through trigger actions for partial matches
|
||||
for trigger, action_data in trigger_actions.items():
|
||||
# Check if query matches trigger or is contained in title
|
||||
if (query in trigger.lower() or
|
||||
query in action_data["title"].lower() or
|
||||
any(word in trigger.lower() for word in query.split())):
|
||||
|
||||
# Calculate relevance based on match quality
|
||||
if query == trigger.lower():
|
||||
relevance = 1.0
|
||||
elif trigger.lower().startswith(query):
|
||||
relevance = 0.9
|
||||
elif query in trigger.lower():
|
||||
relevance = 0.8
|
||||
else:
|
||||
relevance = 0.7
|
||||
|
||||
results.append(Result(
|
||||
title=action_data["title"],
|
||||
subtitle=action_data["subtitle"],
|
||||
icon_markup=action_data["icon"],
|
||||
action=action_data["action"],
|
||||
relevance=relevance,
|
||||
plugin_name=self.display_name,
|
||||
data={"trigger": trigger}
|
||||
))
|
||||
|
||||
return sorted(results, key=lambda x: x.relevance, reverse=True)
|
||||
|
||||
def query_triggered(self, _query_string: str, trigger: str) -> List[Result]:
|
||||
"""
|
||||
Process a triggered query (when plugin is activated by a specific trigger).
|
||||
Show only the specific result for the triggered keyword.
|
||||
"""
|
||||
# Get trigger actions
|
||||
trigger_actions = self._get_trigger_actions()
|
||||
|
||||
# Find the exact trigger match and return only that result
|
||||
trigger_lower = trigger.lower().strip()
|
||||
|
||||
if trigger_lower in trigger_actions:
|
||||
action_data = trigger_actions[trigger_lower]
|
||||
return [Result(
|
||||
title=action_data["title"],
|
||||
subtitle=action_data["subtitle"],
|
||||
icon_markup=action_data["icon"],
|
||||
action=action_data["action"],
|
||||
relevance=1.0,
|
||||
plugin_name=self.display_name,
|
||||
data={"trigger": trigger_lower}
|
||||
)]
|
||||
|
||||
# If no exact match found, return empty list
|
||||
return []
|
||||
|
||||
|
||||
Reference in new issue
Block a user