1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-04 20:54:50 +00:00
Files
Mole/scripts/setup-quick-launchers.sh

425 lines
13 KiB
Bash
Executable File

#!/bin/bash
# Create Raycast script commands and Alfred keywords for Mole (clean + uninstall).
set -euo pipefail
BLUE='\033[0;34m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
ICON_STEP="➜"
ICON_SUCCESS="✓"
ICON_WARN="!"
ICON_ERR="✗"
log_step() { echo -e "${BLUE}${ICON_STEP}${NC} $1"; }
log_success() { echo -e "${GREEN}${ICON_SUCCESS}${NC} $1"; }
log_warn() { echo -e "${YELLOW}${ICON_WARN}${NC} $1"; }
log_error() { echo -e "${RED}${ICON_ERR}${NC} $1"; }
log_header() { echo -e "\n${BLUE}==== $1 ====${NC}\n"; }
is_interactive() { [[ -t 1 && -r /dev/tty ]]; }
prompt_enter() {
local prompt="$1"
if is_interactive; then
read -r -p "$prompt" < /dev/tty || true
else
echo "$prompt"
fi
}
detect_mo() {
if command -v mo > /dev/null 2>&1; then
command -v mo
elif command -v mole > /dev/null 2>&1; then
command -v mole
else
log_error "Mole not found. Install it first via Homebrew or ./install.sh."
exit 1
fi
}
write_raycast_script() {
local target="$1"
local title="$2"
local mo_bin="$3"
local subcommand="$4"
local raw_cmd="\"${mo_bin}\" ${subcommand}"
local cmd_escaped="${raw_cmd//\\/\\\\}"
cmd_escaped="${cmd_escaped//\"/\\\"}"
cat > "$target" << EOF
#!/bin/bash
# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title ${title}
# @raycast.mode fullOutput
# @raycast.packageName Mole
# Optional parameters:
# @raycast.icon 🐹
set -euo pipefail
echo "🐹 Running ${title}..."
echo ""
CMD="${raw_cmd}"
CMD_ESCAPED="${cmd_escaped}"
has_app() {
local name="\$1"
[[ -d "/Applications/\${name}.app" || -d "\$HOME/Applications/\${name}.app" ]]
}
has_bin() {
command -v "\$1" >/dev/null 2>&1
}
launcher_available() {
local app="\$1"
case "\$app" in
Terminal) return 0 ;;
iTerm|iTerm2) has_app "iTerm" || has_app "iTerm2" ;;
Alacritty) has_app "Alacritty" ;;
Kitty) has_bin "kitty" || has_app "kitty" ;;
WezTerm) has_bin "wezterm" || has_app "WezTerm" ;;
Ghostty) has_bin "ghostty" || has_app "Ghostty" ;;
Hyper) has_app "Hyper" ;;
WindTerm) has_app "WindTerm" ;;
Warp) has_app "Warp" ;;
*)
return 1 ;;
esac
}
detect_launcher_app() {
if [[ -n "\${MO_LAUNCHER_APP:-}" ]]; then
echo "\${MO_LAUNCHER_APP}"
return
fi
local candidates=(Warp Ghostty Alacritty Kitty WezTerm WindTerm Hyper iTerm2 iTerm Terminal)
local app
for app in "\${candidates[@]}"; do
if launcher_available "\$app"; then
echo "\$app"
return
fi
done
echo "Terminal"
}
launch_with_app() {
local app="\$1"
case "\$app" in
Terminal)
if command -v osascript >/dev/null 2>&1; then
osascript <<'APPLESCRIPT'
set targetCommand to "${cmd_escaped}"
tell application "Terminal"
activate
do script targetCommand
end tell
APPLESCRIPT
return 0
fi
;;
iTerm|iTerm2)
if command -v osascript >/dev/null 2>&1; then
osascript <<'APPLESCRIPT'
set targetCommand to "${cmd_escaped}"
tell application "iTerm2"
activate
try
tell current window
tell current session
write text targetCommand
end tell
end tell
on error
create window with default profile
tell current window
tell current session
write text targetCommand
end tell
end tell
end try
end tell
APPLESCRIPT
return 0
fi
;;
Alacritty)
if launcher_available "Alacritty" && command -v open >/dev/null 2>&1; then
open -na "Alacritty" --args -e /bin/zsh -lc "${raw_cmd}"
return \$?
fi
;;
Kitty)
if has_bin "kitty"; then
kitty --hold /bin/zsh -lc "${raw_cmd}"
return \$?
elif [[ -x "/Applications/kitty.app/Contents/MacOS/kitty" ]]; then
"/Applications/kitty.app/Contents/MacOS/kitty" --hold /bin/zsh -lc "${raw_cmd}"
return \$?
fi
;;
WezTerm)
if has_bin "wezterm"; then
wezterm start -- /bin/zsh -lc "${raw_cmd}"
return \$?
elif [[ -x "/Applications/WezTerm.app/Contents/MacOS/wezterm" ]]; then
"/Applications/WezTerm.app/Contents/MacOS/wezterm" start -- /bin/zsh -lc "${raw_cmd}"
return \$?
fi
;;
Ghostty)
if has_bin "ghostty"; then
ghostty --command "/bin/zsh" -- -lc "${raw_cmd}"
return \$?
elif [[ -x "/Applications/Ghostty.app/Contents/MacOS/ghostty" ]]; then
"/Applications/Ghostty.app/Contents/MacOS/ghostty" --command "/bin/zsh" -- -lc "${raw_cmd}"
return \$?
fi
;;
Hyper)
if launcher_available "Hyper" && command -v open >/dev/null 2>&1; then
open -na "Hyper" --args /bin/zsh -lc "${raw_cmd}"
return \$?
fi
;;
WindTerm)
if launcher_available "WindTerm" && command -v open >/dev/null 2>&1; then
open -na "WindTerm" --args /bin/zsh -lc "${raw_cmd}"
return \$?
fi
;;
Warp)
if launcher_available "Warp" && command -v open >/dev/null 2>&1; then
open -na "Warp" --args /bin/zsh -lc "${raw_cmd}"
return \$?
fi
;;
esac
return 1
}
if [[ -n "\${TERM:-}" && "\${TERM}" != "dumb" ]]; then
"${mo_bin}" ${subcommand}
exit \$?
fi
TERM_APP="\$(detect_launcher_app)"
if launch_with_app "\$TERM_APP"; then
exit 0
fi
if [[ "\$TERM_APP" != "Terminal" ]]; then
echo "Could not control \$TERM_APP, falling back to Terminal..."
if launch_with_app "Terminal"; then
exit 0
fi
fi
echo "TERM environment variable not set and no launcher succeeded."
echo "Run this manually:"
echo " ${raw_cmd}"
exit 1
EOF
chmod +x "$target"
}
create_raycast_commands() {
local mo_bin="$1"
local default_dir="$HOME/Library/Application Support/Raycast/script-commands"
local dir="$default_dir"
log_step "Installing Raycast commands..."
mkdir -p "$dir"
write_raycast_script "$dir/mole-clean.sh" "clean" "$mo_bin" "clean"
write_raycast_script "$dir/mole-uninstall.sh" "uninstall" "$mo_bin" "uninstall"
write_raycast_script "$dir/mole-optimize.sh" "optimize" "$mo_bin" "optimize"
write_raycast_script "$dir/mole-analyze.sh" "analyze" "$mo_bin" "analyze"
write_raycast_script "$dir/mole-status.sh" "status" "$mo_bin" "status"
log_success "Scripts ready in: $dir"
log_header "Raycast Configuration"
if command -v open > /dev/null 2>&1; then
if open "raycast://extensions/raycast/raycast-settings/extensions" > /dev/null 2>&1; then
log_step "Raycast settings opened."
else
log_warn "Could not auto-open Raycast."
fi
else
log_warn "open command not available; please open Raycast manually."
fi
echo "If Raycast asks to add a Script Directory, use:"
echo " $dir"
if is_interactive; then
log_header "Finalizing Setup"
prompt_enter "Press [Enter] to reload script directories in Raycast..."
if command -v open > /dev/null 2>&1 && open "raycast://extensions/raycast/raycast/reload-script-directories" > /dev/null 2>&1; then
log_step "Raycast script directories reloaded."
else
log_warn "Could not auto-reload Raycast script directories."
fi
log_success "Raycast setup complete!"
else
log_warn "Non-interactive mode; skip Raycast reload. Please run 'Reload Script Directories' in Raycast."
fi
}
uuid() {
if command -v uuidgen > /dev/null 2>&1; then
uuidgen
else
# Fallback pseudo UUID in format: 8-4-4-4-12
local hex=$(openssl rand -hex 16)
echo "${hex:0:8}-${hex:8:4}-${hex:12:4}-${hex:16:4}-${hex:20:12}"
fi
}
create_alfred_workflow() {
local mo_bin="$1"
local prefs_dir="${ALFRED_PREFS_DIR:-$HOME/Library/Application Support/Alfred/Alfred.alfredpreferences}"
local workflows_dir="$prefs_dir/workflows"
if [[ ! -d "$workflows_dir" ]]; then
return
fi
log_step "Installing Alfred workflows..."
local workflows=(
"fun.tw93.mole.clean|Mole clean|clean|Run Mole clean|\"${mo_bin}\" clean"
"fun.tw93.mole.uninstall|Mole uninstall|uninstall|Uninstall apps via Mole|\"${mo_bin}\" uninstall"
"fun.tw93.mole.optimize|Mole optimize|optimize|System health & optimization|\"${mo_bin}\" optimize"
"fun.tw93.mole.analyze|Mole analyze|analyze|Disk space analysis|\"${mo_bin}\" analyze"
"fun.tw93.mole.status|Mole status|status|Live system dashboard|\"${mo_bin}\" status"
)
for entry in "${workflows[@]}"; do
IFS="|" read -r bundle name keyword subtitle command <<< "$entry"
local workflow_uid="user.workflow.$(uuid | tr '[:upper:]' '[:lower:]')"
local input_uid
local action_uid
input_uid="$(uuid)"
action_uid="$(uuid)"
local dir="$workflows_dir/$workflow_uid"
mkdir -p "$dir"
cat > "$dir/info.plist" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>bundleid</key>
<string>${bundle}</string>
<key>createdby</key>
<string>Mole</string>
<key>name</key>
<string>${name}</string>
<key>objects</key>
<array>
<dict>
<key>config</key>
<dict>
<key>argumenttype</key>
<integer>2</integer>
<key>keyword</key>
<string>${keyword}</string>
<key>subtext</key>
<string>${subtitle}</string>
<key>text</key>
<string>${name}</string>
<key>withspace</key>
<true/>
</dict>
<key>type</key>
<string>alfred.workflow.input.keyword</string>
<key>uid</key>
<string>${input_uid}</string>
<key>version</key>
<integer>1</integer>
</dict>
<dict>
<key>config</key>
<dict>
<key>concurrently</key>
<true/>
<key>escaping</key>
<integer>102</integer>
<key>script</key>
<string>#!/bin/bash
PATH="/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin"
${command}
</string>
<key>scriptargtype</key>
<integer>1</integer>
<key>scriptfile</key>
<string></string>
<key>type</key>
<integer>0</integer>
</dict>
<key>type</key>
<string>alfred.workflow.action.script</string>
<key>uid</key>
<string>${action_uid}</string>
<key>version</key>
<integer>2</integer>
</dict>
</array>
<key>connections</key>
<dict>
<key>${input_uid}</key>
<array>
<dict>
<key>destinationuid</key>
<string>${action_uid}</string>
<key>modifiers</key>
<integer>0</integer>
<key>modifiersubtext</key>
<string></string>
</dict>
</array>
</dict>
<key>uid</key>
<string>${workflow_uid}</string>
<key>version</key>
<integer>1</integer>
</dict>
</plist>
EOF
log_success "Workflow ready: ${name} (keyword: ${keyword})"
done
log_step "Open Alfred preferences → Workflows if you need to adjust keywords."
}
main() {
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " Mole Quick Launchers"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
local mo_bin
mo_bin="$(detect_mo)"
log_step "Detected Mole binary at: ${mo_bin}"
create_raycast_commands "$mo_bin"
create_alfred_workflow "$mo_bin"
echo ""
log_success "Done! Raycast and Alfred are ready with 5 commands:"
echo " • clean - Deep system cleanup"
echo " • uninstall - Remove applications"
echo " • optimize - System health & tuning"
echo " • analyze - Disk space explorer"
echo " • status - Live system monitor"
echo ""
}
main "$@"