188 lines
6.5 KiB
Python
188 lines
6.5 KiB
Python
"""
|
|
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 []
|
|
|
|
|