Is there a way to auto-complete the open command in Terminal?
I frequently use the open -a
command in Terminal to open applications via ssh. How do I make it auto-complete an application's name?
_complete_open() {
COMPREPLY=()
local cur="${COMP_WORDS[$COMP_CWORD]}"
local prev="${COMP_WORDS[COMP_CWORD-1]}"
[[ "$cur" == -* || "$prev" != '-a' ]] && return
apps="$(mdfind kMDItemKind==Application -onlyin /Applications -onlyin ~/Applications -onlyin /Developer -onlyin ~/Developer | grep -v '/.*/.*/.*/.*/' | sed -E 's|.*/||g;s|\.app$||g' | uniq)"$'Finder\nArchive Utility\nCharacterPalette\nKeyboardViewer'
local IFS=$'\n'
if [[ "${cur:0:1}" = '"' || "${cur:0:1}" = "'" ]]; then
quote="${cur:0:1}"
cur="${cur:1}"
fi
local found="$(grep -i "^$cur" <<< "$apps")"
if [[ "$quote" == '"' ]]; then
found="$(sed "s|^|\"|g;s|$|\"|g" <<< "$found")"
elif [[ "$quote" == "'" ]]; then
found="$(sed "s|^|'|g;s|$|'|g" <<< "$found")"
else
found="$(sed 's| |\\ |g' <<< "$found")"
fi
COMPREPLY=($found)
}
complete -o default -F _complete_open open
Third version, which should now both be case insensitive and work within quotes.
Add the following to your .bash_profile
or .bashrc
and launch a new session:
function _complete_open {
cur=$2
COMPREPLY=( );
[[ "$COMP_WORDS" = "open" ]] || return
[[ "${COMP_WORDS[ $(( $COMP_CWORD - 1 )) ]}" = "-a" ]] || return
OLDIFS="$IFS"
IFS=$'\n'
local _part="${COMP_WORDS[$COMP_CWORD]}"
if [[ "${_part:0:1}" = '"' || "${_part:0:1}" = "'" ]] ; then
COMPREPLY=( $( compgen -W "$( mdfind kMDItemKind==Application | sed -e 's|.*/||g' -e 's|.app$||' | sort -u )" -- $cur ) )
else
COMPREPLY=( $( compgen -W "$( mdfind kMDItemKind==Application | sed -e 's|.*/||g' -e 's|.app$||' -e 's| |\\\\ |g' | sort -u )" -- $cur ) )
fi
IFS="$OLDIFS"
}
complete -o default -F _complete_open open
No need to install anything. This works with bash
out of the box.
It will only autocomplete program names if the previous option is -a
and otherwise show default behavior, e.g. return a list of all files in the current directory or complete the current path prefix.
The results are generated from system_profiler SPApplicationsDataType
, which is the easiest way to get all applications that can be launched this way on your system like that. The list is processed to only return the program names, which can contain spaces and can be different from the bundle names (even when ignoring .app
suffix)
Usage: Type open -a
, followed by a space, followed by pressing Tab
or Esc
(twice on my system, not sure if it's everywhere).
Example showing all the helper applications for my scanner:
$ open -a Scan
Scan to E-mail Scan to Excel Scan to Folder Scan to Print Scan to Searchable PDF Scan to Word ScanSnap Manager
Drawbacks and problems of this solution:
There are tons of programs on your system you might not be aware of, like everything in
/System/Library/CoreServices
. You might not want to list all of them. OTOH, it's really easy to see and launch e.g.CharacterPalette
orKeyboardViewer
this way. *Configure themdfind
call(s) appropriately with the-onlyin
argument.It's kind of slow, due toNow usessystem_profiler SPApplicationsDataType
. You might need to wait a second or two before completion shows up.mdfind
to quickly get the programs. Thanks @LriIt can handle spaces in application names, and quotation enclosed program names, but it's rather hacky. It requires the quote to be the first character: While
Scan" to "P
is valid inbash
, this program will not detect it. Completion does not work after an escaped space either (e.g.Scan\ to
), use quotation marks in such cases ("Scan to
). Support for escaped spaces is only good to completeDVD
toDVD\ Player
.