macOS Automation – Create Clickable List to Run Programs

automationlaunch-servicesmacossoftware-recommendation

I'm looking for something which runs under macOS that will let me do the following:

Suppose I have a file called "program.list" with contents something like this:

"Program 1" "/usr/local/bin/program 1"
"Program 2" "/usr/local/bin/program 2"
"Program 3" "/usr/local/bin/other-program xyz"
"Program 4" "/usr/local/bin/something-else"
... etc. ...

I'd like to feed this file to a program which, for example, could be called "run-from-list", and which I could invoke as follows:

run-from-list program.list

… and when that command is invoked, the following would show up on the screen in a scrollable list:

Program 1
Program 2
Program 3
Program 4
... etc. ...

And whatever line I click on, the associated program will run. For example, if I click on "Program 1", it will run the "/usr/local/bin/program 1" program.

Is there any way to write "run-from-list" in MacOS without compiling source code into an executable? A scripting language would be suitable. Or is there some sort of existing utility that I could download which I could use similarly for this purpose?

Best Answer

I combined zsh and AppleScript to accomplish this. Doesn't need compilation.


My version of program.list looks like this:

➜  ~ cat program.list

"Music" "open -a Music"
"Safari" "open -a Safari"
"New Safari" "open -na Safari"
"A Good Question" "open -a Safari https://apple.stackexchange.com/q/471930/71941"

I created a run_from_list.sh in my home dir and execute chmod +x run_from_list.sh.


The contents of run_from_list.sh are as follows. Code is adequately commented for every relevant step:

#!/bin/zsh

# Check if the input file exists.
if [[ ! -f "$1" ]]; then
    echo "File not found!"
    exit 1
fi

# Initialize arrays to read the program names and commands into.
program_names=()
program_commands=()

# Read and process the input file line by line.
while IFS= read -r line; do
    program_name=$(echo "$line" | cut -d '"' -f 2)
    program_command=$(echo "$line" | cut -d '"' -f 4)
    program_names+=("$program_name")  # Append the program name.
    program_commands+=("$program_command") # Append the prescribed command for the program.
done < "$1"

# Generate AppleScript command to display list.
cmd="choose from list {"
for name in $program_names; do
    cmd+='"'"$name"'", '
done
cmd="${cmd%,*} } with title \"Select a Program\""

# Run AppleScript command and capture the selection.
selected_program=$(osascript -e "$cmd")

# User made the selection. Now, find and execute the corresponding command.
for i in {1..$#program_names}; do
    if [[ "${program_names[i]}" == "$selected_program" ]]; then
        echo "Running ${program_commands[i]}" # Display a message on the terminal.
        eval "${program_commands[i]}" # Execute the prescribed command.
        break
    fi
done

Test it:

  • Go to your home dir by doing cd ~;
  • ./run_from_list.sh program.list.