Skip to content

Instantly share code, notes, and snippets.

@mayoff
Last active April 5, 2018 23:46
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mayoff/5498775 to your computer and use it in GitHub Desktop.
Save mayoff/5498775 to your computer and use it in GitHub Desktop.
bash completion for the `-a` and `-b` flags of the Mac OS X `open` command
#
# This is a set of bash function definitions, and a bash command, that
# set up bash completion for the Mac OS X "open" command.
#
# HOW TO USE
#
# Add this command to your .bashrc:
#
# . open.sh
#
# (Adjust the filename to wherever you put this file.)
#
# WHAT THIS ACTUALLY DOES
#
# When you try to complete a word after "open -a", bash will match the
# word against the names of the apps on your Mac. Example:
#
# $ open -a Ado<TAB>
# AdobePatchInstaller Adobe\ Bridge\ CS6 Adobe\ Media\ Player
# Adobe\ AIR\ Application\ Installer Adobe\ Encore\ CS6 Adobe\ Photoshop\ CS6
# Adobe\ AIR\ Uninstaller Adobe\ Extension\ Manager\ CS6 Adobe\ Prelude\ CS6
# Adobe\ AIR\ Updater Adobe\ Fireworks\ CS6 Adobe\ Premiere\ Pro\ CS6
# Adobe\ After\ Effects\ CS6 Adobe\ Flash\ CS6 Adobe\ SpeedGrade\ CS6
# Adobe\ After\ Effects\ Render\ Engine Adobe\ Help Adobe\ Story
# Adobe\ Application\ Manager Adobe\ Illustrator
# Adobe\ Audition\ CS6 Adobe\ Media\ Encoder\ CS6
# $ open -a Adobe
#
# When you try to complete a word after "open -b", bash will match the
# word against the bundle identifiers of the apps on your Mac. Example:
#
# :; open -b com.ado
# com.adobe.AdobePremierePro com.adobe.air.Installer
# com.adobe.AdobeStory.4875E02D9FB21EE389F73B8D1702B320485DF8CE.1 com.adobe.air.NativeTemplate
# com.adobe.AfterEffects com.adobe.air.Template
# com.adobe.Audition.5.0 com.adobe.ame.application
# com.adobe.Encore com.adobe.amp.4875E02D9FB21EE389F73B8D1702B320485DF8CE.1
# com.adobe.ExtensionManager com.adobe.bridge5
# com.adobe.Installers.Redirector com.adobe.csi.CS6ServiceManager
# com.adobe.Installers.Setup com.adobe.director.projector
# com.adobe.PDApp com.adobe.dynamiclinkmanager
# com.adobe.PDApp.AAMRegistrationNotifier com.adobe.dynamiclinkmediaserver
# com.adobe.PDApp.AAMUpdatesNotifier com.adobe.estoolkit-3.8
# com.adobe.Photoshop com.adobe.flash
# com.adobe.Prelude com.adobe.headlights.LogTransport2App
# com.adobe.adobe_licutil com.adobe.illustrator
# com.adobe.air.ApplicationInstaller com.adobe.switchboard-2.0
# :; open -b com.adobe.
#
# CACHING
#
# These functions use Spotlight to find your applications and their
# bundle identifiers. Getting the list of applications is pretty fast
# (after it's done the first time). Getting the bundle identifiers is
# a little slower. To speed it up, you can set the shell variable
# CompleteOpenBundleCache to a path. The first time I need bundle
# identifiers, I will cache them at that path. On subsequent uses, I
# will use the cached identifiers. I don't invalidate the cache
# automatically. Just delete it when it gets out of date:
#
# rm -f "$CompleteOpenBundleCache"
#
_complete_open () {
local priorWord="$3" word="$2"
case "$priorWord" in
-a) _complete_open_app "$word" ;;
-b) _complete_open_bundle "$word" ;;
*) COMPREPLY=() ;;
esac
}
_complete_open_app () {
local word="$1*" appPath appName
declare -i i=0
COMPREPLY=()
while IFS= read -r -d $'\0' appPath; do
appName="${appPath##*/}"
appName="${appName%.app}"
if [[ "$appName" == $word ]]; then
COMPREPLY[i++]="$(_complete_open_helper_escape "$appName")"
fi
done < <(mdfind -0 'kMDItemContentType == "com.apple.application-bundle"')
}
_complete_open_bundle () {
local word="$1*" bundle
declare -i i=0
COMPREPLY=()
while IFS= read -r -d $'\0' bundle; do
if [[ "$bundle" != '' && "$bundle" == $word ]]; then
COMPREPLY[i++]="$(_complete_open_helper_escape "$bundle")"
fi
done < <(_complete_open_helper_bundles)
}
_complete_open_file () {
local file
}
_complete_open_helper_bundles () {
if [[ "$CompleteOpenBundleCache" == '' ]]; then
_complete_open_helper_bundles_uncached
else
if [[ ! -f "$CompleteOpenBundleCache" ]]; then
rm -f "$CompleteOpenBundleCache"
_complete_open_helper_bundles_uncached > "$CompleteOpenBundleCache"
fi
cat "$CompleteOpenBundleCache"
fi
}
_complete_open_helper_bundles_uncached () {
mdfind -0 'kMDItemContentType == "com.apple.application-bundle"' \
| xargs -0 mdls -raw -nullMarker '' -name kMDItemCFBundleIdentifier
}
_complete_open_helper_escape () {
echo -n "$1" | sed 's/[^-A-Za-z0-9_.,:@%=+/]/\\&/g'
}
complete -o bashdefault -o default -F _complete_open open
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment