From b966e2d53930b17712d23152548257a347f35d3e Mon Sep 17 00:00:00 2001 From: stewart86 Date: Wed, 10 Dec 2025 18:10:15 +0800 Subject: [PATCH 1/2] feat: add support for custom user action scripts Add ability to define custom actions by placing executable scripts in ~/.config/illogical-impulse/actions/ - Script filename becomes the action name (extension stripped) - Use /script-name in search bar to execute - Arguments are passed to the script - Uses FolderListModel for auto-reload when scripts are added/removed - Follows existing pattern of user-customizable directories (ai/prompts) --- .../ii/modules/common/Directories.qml | 2 ++ .../quickshell/ii/services/LauncherSearch.qml | 34 ++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/common/Directories.qml b/dots/.config/quickshell/ii/modules/common/Directories.qml index 9afbed44b..78b0a9edb 100644 --- a/dots/.config/quickshell/ii/modules/common/Directories.qml +++ b/dots/.config/quickshell/ii/modules/common/Directories.qml @@ -44,6 +44,7 @@ Singleton { property string wallpaperSwitchScriptPath: FileUtils.trimFileProtocol(`${Directories.scriptPath}/colors/switchwall.sh`) property string defaultAiPrompts: Quickshell.shellPath("defaults/ai/prompts") property string userAiPrompts: FileUtils.trimFileProtocol(`${Directories.shellConfig}/ai/prompts`) + property string userActions: FileUtils.trimFileProtocol(`${Directories.shellConfig}/actions`) property string aiChats: FileUtils.trimFileProtocol(`${Directories.state}/user/ai/chats`) property string aiTranslationScriptPath: FileUtils.trimFileProtocol(`${Directories.scriptPath}/ai/gemini-translate.sh`) property string recordScriptPath: FileUtils.trimFileProtocol(`${Directories.scriptPath}/videos/record.sh`) @@ -59,6 +60,7 @@ Singleton { Quickshell.execDetached(["bash", "-c", `rm -rf '${latexOutput}'; mkdir -p '${latexOutput}'`]) Quickshell.execDetached(["bash", "-c", `rm -rf '${cliphistDecode}'; mkdir -p '${cliphistDecode}'`]) Quickshell.execDetached(["mkdir", "-p", `${aiChats}`]) + Quickshell.execDetached(["mkdir", "-p", `${userActions}`]) Quickshell.execDetached(["rm", "-rf", `${tempImages}`]) } } diff --git a/dots/.config/quickshell/ii/services/LauncherSearch.qml b/dots/.config/quickshell/ii/services/LauncherSearch.qml index f5a18bec9..d8f7af59a 100644 --- a/dots/.config/quickshell/ii/services/LauncherSearch.qml +++ b/dots/.config/quickshell/ii/services/LauncherSearch.qml @@ -4,6 +4,7 @@ import qs.modules.common import qs.modules.common.models import qs.modules.common.functions import QtQuick +import Qt.labs.folderlistmodel import Quickshell import Quickshell.Io @@ -31,6 +32,34 @@ Singleton { return acc; }, []).sort() + // Load user action scripts from ~/.config/illogical-impulse/actions/ + // Uses FolderListModel to auto-reload when scripts are added/removed + property var userActionScripts: { + const actions = []; + for (let i = 0; i < userActionsFolder.count; i++) { + const fileName = userActionsFolder.get(i, "fileName"); + const filePath = userActionsFolder.get(i, "filePath"); + if (fileName && filePath) { + const actionName = fileName.replace(/\.[^/.]+$/, ""); // strip extension + actions.push({ + action: actionName, + execute: ((path) => (args) => { + Quickshell.execDetached([path, ...(args ? args.split(" ") : [])]); + })(filePath.toString().replace("file://", "")) + }); + } + } + return actions; + } + + FolderListModel { + id: userActionsFolder + folder: `file://${Directories.userActions}` + showDirs: false + showHidden: false + sortField: FolderListModel.Name + } + property var searchActions: [ { action: "accentcolor", @@ -90,6 +119,9 @@ Singleton { }, ] + // Combined built-in and user actions + property var allActions: searchActions.concat(userActionScripts) + property string mathResult: "" property bool clipboardWorkSafetyActive: { const enabled = Config.options.workSafety.enable.clipboard; @@ -273,7 +305,7 @@ Singleton { Qt.openUrlExternally(url); } }); - const launcherActionObjects = root.searchActions.map(action => { + const launcherActionObjects = root.allActions.map(action => { const actionString = `${Config.options.search.prefix.action}${action.action}`; if (actionString.startsWith(root.query) || root.query.startsWith(actionString)) { return resultComp.createObject(null, { From 5f51b97b6d343d5fbed35dd4e3de43df08715211 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 14 Dec 2025 10:38:12 +0100 Subject: [PATCH 2/2] replace manual `file://` replacement with util functions --- dots/.config/quickshell/ii/services/LauncherSearch.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dots/.config/quickshell/ii/services/LauncherSearch.qml b/dots/.config/quickshell/ii/services/LauncherSearch.qml index d8f7af59a..52e783e28 100644 --- a/dots/.config/quickshell/ii/services/LauncherSearch.qml +++ b/dots/.config/quickshell/ii/services/LauncherSearch.qml @@ -45,7 +45,7 @@ Singleton { action: actionName, execute: ((path) => (args) => { Quickshell.execDetached([path, ...(args ? args.split(" ") : [])]); - })(filePath.toString().replace("file://", "")) + })(FileUtils.trimFileProtocol(filePath.toString())) }); } } @@ -54,7 +54,7 @@ Singleton { FolderListModel { id: userActionsFolder - folder: `file://${Directories.userActions}` + folder: Qt.resolvedUrl(Directories.userActions) showDirs: false showHidden: false sortField: FolderListModel.Name