Type to find and toolbar options for scripts/actions

Discussion of Photoshop Scripting, Photoshop Actions and Photoshop Automation in General

Moderators: Tom, Kukurykus

MrEd
Posts: 1
Joined: Wed Aug 28, 2024 9:38 am

Type to find and toolbar options for scripts/actions

Post by MrEd »

Hey there,
[1] Type to find + execute
I have been looking around and can't find a complete tool/plugin/extension. I am trying to find a tool that can launch with a hotkey and search actions and custom scripts and execute on 'return'. I can see various tools that almost do it like this
https://exchange.adobe.com/apps/cc/1587 ... shon-trees
(Doesn't focus search box, doesn't allow keyboard execution, no actions)
Surely something exists for Ps ?

[2]
Also is there a defacto custom toolbar available that you can create icons, launch scripts, actions ?
This looked good but seems to be unmaintained.
https://exchange.adobe.com/apps/cc/19405/lascripts

Totally willing to pay for good software!
Thanks for any tips!

A

Professional AI Audio Generation within Adobe Premiere Pro - Download Free Plugin here

codila
Posts: 1
Joined: Thu Jun 12, 2025 9:00 am

Re: Type to find and toolbar options for scripts/actions

Post by codila »

MrEd wrote: Wed Aug 28, 2024 10:00 am Hey there,
[1] Type to find + execute
I have been looking around and can't find a complete tool/plugin/extension. I am trying to find a tool that can launch with a hotkey and search actions and custom scripts and execute on 'return'. I can see various tools that almost do it like this
https://exchange.adobe.com/apps/cc/1587 ... shon-trees
(Doesn't focus search box, doesn't allow keyboard execution, no actions)
Surely something exists for Ps ? wordle unlimited

[2]
Also is there a defacto custom toolbar available that you can create icons, launch scripts, actions ?
This looked good but seems to be unmaintained.
https://exchange.adobe.com/apps/cc/19405/lascripts

Totally willing to pay for good software!
Thanks for any tips!

A
How to change it?
User avatar
Scriptor
Posts: 32
Joined: Tue Oct 01, 2019 12:07 pm

Re: Type to find and toolbar options for scripts/actions

Post by Scriptor »

Sure. Put this all into a .jsx-file, record an action where you play said jsx through "File" > "Scripts" > "Browse...", and set a shortcut (eg. F2 or whatever). Each time you press F2 you'll get this script, and you can play whatever set/action (or script if you use the above method for your other scripts as well).

If you want it to start with focus on "Seach Action..." do this:

actionSetInput.active = true; < disable this line with "//"
//actionNameInput.active = true; < enable this line by removing "//"

Code: Select all

function getAllActions() {
    var actionSets = [];

    var actionSetCounter = 1;
    var actionSetContinue = true;

    while (actionSetContinue) {
        try {
            var actionSetRef = new ActionReference();
            actionSetRef.putIndex(charIDToTypeID("ASet"), actionSetCounter);
            var setDesc = executeActionGet(actionSetRef);
            var actionSetName = setDesc.getString(charIDToTypeID("Nm  "));  // Action Set Name

            var actions = [];
            var actionCounter = 1;
            var actionContinue = true;

            while (actionContinue) {
                try {
                    var actionRef = new ActionReference();
                    actionRef.putIndex(charIDToTypeID("Actn"), actionCounter);
                    actionRef.putIndex(charIDToTypeID("ASet"), actionSetCounter);
                    var actionDesc = executeActionGet(actionRef);
                    var actionName = actionDesc.getString(charIDToTypeID("Nm  "));  // Action Name
                    actions.push(actionName);
                    actionCounter++;
                } catch (e) {
                    actionContinue = false;  // No more actions in this set
                }
            }

            // Add the action set name and its actions as an array
            actionSets.push([actionSetName].concat(actions));

            actionSetCounter++;
        } catch (e) {
            actionSetContinue = false;  // No more action sets
        }
    }

    return actionSets;
}

// Function to find the closest match manually
function findClosestMatch(input, array) {
    input = input.toLowerCase();
    var bestMatchIndex = -1;
    var bestMatchLength = Infinity;

    for (var i = 0; i < array.length; i++) {
        var item = array[i].toLowerCase();
        // Manual search for a substring match (avoiding indexOf)
        var matchFound = false;
        for (var j = 0; j <= item.length - input.length; j++) {
            if (item.substring(j, j + input.length) === input) {
                matchFound = true;
                break;
            }
        }
        if (matchFound && input.length < bestMatchLength) {
            bestMatchLength = input.length;
            bestMatchIndex = i;
        }
    }

    return bestMatchIndex;  // Returns the best match index or -1 if no match is found
}

// DIALOG
// ======
var dialog = new Window("dialog"); 
    dialog.text = "Action Set Go by Scriptor"; 
    dialog.orientation = "column"; 
    dialog.alignChildren = ["center","top"]; 
    dialog.spacing = 10; 
    dialog.margins = 16; 

// GROUP1
// ======
var group1 = dialog.add("group", undefined, {name: "group1"}); 
    group1.orientation = "column"; 
    group1.alignChildren = ["left","center"]; 
    group1.spacing = 10; 
    group1.margins = 0; 

// GROUP2
// ======
var group2 = group1.add("group", undefined, {name: "group2"}); 
    group2.orientation = "row"; 
    group2.alignChildren = ["left","center"]; 
    group2.spacing = 10; 
    group2.margins = 0; 

// GROUP4
// ======
var group4 = group2.add("group", undefined, {name: "group4"}); 
    group4.orientation = "column"; 
    group4.alignChildren = ["center","center"]; 
    group4.spacing = 10; 
    group4.margins = 0; 

var actionSetInput = group4.add('edittext {properties: {name: "actionSetInput"}}'); 
    actionSetInput.text = "Search Set..."; 
	actionSetInput.active = true;
    actionSetInput.preferredSize.width = 200; 

// GROUP5
// ======
var group5 = group2.add("group", undefined, {name: "group5"}); 
    group5.orientation = "column"; 
    group5.alignChildren = ["center","center"]; 
    group5.spacing = 10; 
    group5.margins = 0; 


var dropdown1 = group5.add("dropdownlist", undefined, undefined, {name: "dropdown1"}); 
    dropdown1.selection = 0; 
    dropdown1.preferredSize.width = 200; 

// GROUP6
// ======
var group6 = group1.add("group", undefined, {name: "group6"}); 
    group6.orientation = "row"; 
    group6.alignChildren = ["left","center"]; 
    group6.spacing = 10; 
    group6.margins = 0; 

var actionNameInput = group6.add('edittext {properties: {name: "actionNameInput"}}'); 
    actionNameInput.text = "Search Action..."; 
    //actionNameInput.active = true;
    actionNameInput.preferredSize.width = 200; 

var dropdown2 = group6.add("dropdownlist", undefined, undefined, {name: "dropdown2"}); 
    dropdown2.selection = 0; 
    dropdown2.preferredSize.width = 200; 

// GROUP7
// ======
var group7 = group1.add("group", undefined, {name: "group7"}); 
    group7.orientation = "row"; 
    group7.alignChildren = ["left","center"]; 
    group7.spacing = 10; 
    group7.margins = 0; 

var button1 = group7.add("button", undefined, undefined, {name: "button1"}); 
    button1.text = "OK"; 

var button2 = group7.add("button", undefined, undefined, {name: "button2"}); 
    button2.text = "Cancel"; 


// Populate the dropdowns with action sets and actions
var actionSetsArray = getAllActions();
var selectedSetIndex = 0; // Keep track of the selected index manually

// Fill the first dropdown (Action Set dropdown)
for (var i = 0; i < actionSetsArray.length; i++) {
    dropdown1.add("item", actionSetsArray[i][0]);  // Add action set names
}

// Set default selection for Action Set
dropdown1.selection = 0;

// Function to update the Action dropdown when an Action Set is selected
function updateActionDropdown() {
    var actions = actionSetsArray[selectedSetIndex].slice(1);  // Get actions for the selected set
    dropdown2.removeAll();  // Clear the second dropdown
    for (var i = 0; i < actions.length; i++) {
        dropdown2.add("item", actions[i]);  // Add action names
    }
    dropdown2.selection = 0;  // Set the first action as the default
}

// Initialize the second dropdown with the actions of the first Action Set
updateActionDropdown();

// When the Action Set dropdown changes, update the Action dropdown
dropdown1.onChange = function () {
    // Manually determine the selected set index for dropdown1
    for (var i = 0; i < dropdown1.items.length; i++) {
        if (dropdown1.items[i] === dropdown1.selection) {
            selectedSetIndex = i;
            break;
        }
    }
    updateActionDropdown();  // Refresh dropdown2 with the new actions
};

// Function to update dropdown2 manually when searching by action name
function updateDropdownsFromActionNameInput() {
    var actionNameInputText = actionNameInput.text.toLowerCase();
    
    for (var i = 0; i < actionSetsArray.length; i++) {
        var actions = actionSetsArray[i].slice(1);  // Get actions (ignoring the set name)
        
        for (var j = 0; j < actions.length; j++) {
            var actionLower = actions[j].toLowerCase();
            var matchFound = false;
            
            // Manual comparison to check for a match (avoiding indexOf)
            for (var k = 0; k <= actionLower.length - actionNameInputText.length; k++) {
                if (actionLower.substring(k, k + actionNameInputText.length) === actionNameInputText) {
                    matchFound = true;
                    break;
                }
            }

            if (matchFound) {
                // Set the matching action set and action
                selectedSetIndex = i;
                dropdown1.selection = dropdown1.items[i];
                updateActionDropdown();  // Update dropdown2 with corresponding actions
                
                // Manually set the selection for dropdown2
                for (var x = 0; x < dropdown2.items.length; x++) {
                    if (dropdown2.items[x].text.toLowerCase() === actions[j].toLowerCase()) {
                        dropdown2.selection = dropdown2.items[x];  // Set the matched action
                        break;
                    }
                }
                return;  // Stop after the first match
            }
        }
    }
}

// Function to update dropdowns based on user input in actionSetInput
function updateDropdownsFromActionSetInput() {
    // Find the closest match for Action Set
    var actionSetInputText = actionSetInput.text;
    var actionSetNames = [];
    for (var i = 0; i < actionSetsArray.length; i++) {
        actionSetNames.push(actionSetsArray[i][0]);  // Add the name of the action set
    }
    var actionSetMatchIndex = findClosestMatch(actionSetInputText, actionSetNames);
    
    if (actionSetMatchIndex !== -1) {
        selectedSetIndex = actionSetMatchIndex;
        dropdown1.selection = actionSetMatchIndex;
        updateActionDropdown();
    }
}

// Attach event listeners to input fields
actionSetInput.onChanging = updateDropdownsFromActionSetInput;
actionNameInput.onChanging = updateDropdownsFromActionNameInput;

// When the "OK" button is clicked, execute the selected action
button1.onClick = function () {
    var selectedActionSet = dropdown1.selection.text;
    var selectedAction = dropdown2.selection.text;
    dialog.close();
    app.doAction(selectedAction, selectedActionSet);
};

// Show the dialog
dialog.show();