From 24a68220a105c70a54baa543917e1022ae3e7a8d Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 12 Nov 2004 11:47:41 +0000 Subject: improved Mac completion, from Motoi Washida --- Completion/Darwin/Type/_mac_applications | 51 +--------------- Completion/Darwin/Type/_mac_files_for_application | 74 +++++++++++++++++++++++ Completion/Darwin/Type/_retrieve_mac_apps | 59 ++++++++++++++++++ 3 files changed, 136 insertions(+), 48 deletions(-) create mode 100644 Completion/Darwin/Type/_mac_files_for_application create mode 100644 Completion/Darwin/Type/_retrieve_mac_apps (limited to 'Completion/Darwin/Type') diff --git a/Completion/Darwin/Type/_mac_applications b/Completion/Darwin/Type/_mac_applications index 69b23ea7b..ac1df46c1 100644 --- a/Completion/Darwin/Type/_mac_applications +++ b/Completion/Darwin/Type/_mac_applications @@ -1,51 +1,6 @@ #autoload -_mac_applications_caching_policy () { - # rebuild if cache is more than a day old - oldp=( "$1"(Nmw+1) ) - (( $#oldp )) -} +_retrieve_mac_apps -_mac_applications() { - [[ $PREFIX = */* ]] && return 1 - - local cache_policy - zstyle -s ":completion:*:*:$service:*" cache-policy cache_policy - if [[ -z "$cache_policy" ]]; then - zstyle ":completion:*:*:$service:*" cache-policy _mac_applications_caching_policy - fi - - if ( [[ ${+apps} -eq 0 ]] || _cache_invalid Mac_applications ) \ - && ! _retrieve_cache Mac_applications; then - local app_pattern="*.app" - - local -a app_path - zstyle -s ":completion:${curcontext}:commands" application-dir app_path - if [[ -z "$app_path" ]]; then - local -a apdptn - apdptn="((*~$app_pattern~Data~plugins~*Fonts~Contents)/)#" - app_path=({{/,/Developer,/Network,"$HOME"}/Applications/,"/Applications (Mac OS 9)/"}${~apdptn} "$HOME"/Desktop/{,*~${~app_pattern}(/)}) - fi - - local -a apps - - if ! zstyle -t ":completion:${curcontext}:commands" ignore-extention; then - apps=("${apps[@]}" "${app_path[@]}"/${~app_pattern}) - fi - - if ! zstyle -t ":completion:${curcontext}:commands" ignore-cfm; then - local capps - capps="`awk '/^Joy\!peffpwpc/ {print FILENAME; }; { nextfile }' ${app_path}/(*~*.?~*.??~*.???~*.????)(^/)`" - apps=("${apps[@]}" "${(f)capps}") - fi - - typeset -U apps - apps=("${apps[@]:t:r}") - _store_cache Mac_applications apps - fi - - local expl - _wanted commands expl 'mac os x application' compadd -a apps -} - -_mac_applications "$@" +local expl +_wanted commands expl 'Mac OS X application' compadd -- "${(@)${_mac_apps[@]:t}%.app}" diff --git a/Completion/Darwin/Type/_mac_files_for_application b/Completion/Darwin/Type/_mac_files_for_application new file mode 100644 index 000000000..cd4c7860b --- /dev/null +++ b/Completion/Darwin/Type/_mac_files_for_application @@ -0,0 +1,74 @@ +#autoload + +_mac_rsrc_check() { + [[ ! -s "$REPLY/..namedfork/rsrc" ]] && return 1 + if [[ -x /Developer/Tools/GetFileInfo ]]; then + local ftype="$(command /Developer/Tools/GetFileInfo -t $REPLY)" + ftype="${ftype//\"/}" + [[ -n "$types[(r)$ftype]" ]] + else + grep --quiet "\(${(j/\|/)types}\)" "$REPLY/..namedfork/rsrc" + fi +} + +_mac_parse_info_plist() { + # For now, awk is used because builtin function "read" was too slow. + # '<' is used for the delimiter because some Info.plist files use CR as + # newline but read doesn't treat them as so + local s=' + BEGIN { RS="<" } + /^key>/ { sub(/key>/, ""); reading_key=$0 } + /^string>/ { + sub(/string>/, "") + if (reading_key == "CFBundleTypeExtensions") exts=exts " \"" $0 "\"" + if (reading_key == "CFBundleTypeOSTypes") types=types " \"" $0 "\"" + } + END { + print "exts=(" exts ")\ntypes=(" types ")" + } + ' + command awk $s "$app_path/Contents/Info.plist" | while read; do + eval "$REPLY" + done +} + +# Try to complete files for the specified application. +_mac_files_for_application() { + local -a opts + zparseopts -D -a opts q n 1 2 P: S: r: R: W: X+: M+: F: J+: V+: + + local app_path + _retrieve_mac_apps + app_path="${_mac_apps[(r)*/$1(|.app)]:-$1}" + + local -a glob_patterns + glob_patterns=() + + # Try to get extentions from "Info.plist" XML file. + if [[ -f "$app_path/Contents/Info.plist" ]]; then + local -a exts types + _mac_parse_info_plist + + if [[ -n "$exts[(r)\*]" ]]; then + glob_patterns=( "*" ) + else + if (( #exts != 0 )); then + glob_patterns+=( "*.(${(j/|/)exts})(N)" ) + fi + + if (( #types != 0 )); then + glob_patterns+=( "^*.[[:alnum:]]##(.Ne:_mac_rsrc_check:)" ) + fi + fi + else + glob_patterns=( "*" ) + fi + + case ${#glob_patterns} in + 0) return 1 ;; + 1) _files "$opts[@]" -g "$glob_patterns[0]" ;; + *) _files "$opts[@]" -g "{${(j/,/)glob_patterns}}" ;; + esac +} + +_mac_files_for_application "$@" diff --git a/Completion/Darwin/Type/_retrieve_mac_apps b/Completion/Darwin/Type/_retrieve_mac_apps new file mode 100644 index 000000000..cef83913f --- /dev/null +++ b/Completion/Darwin/Type/_retrieve_mac_apps @@ -0,0 +1,59 @@ +#autoload + +# Find paths of applications and preserve them into _mac_apps. +# Used by _mac_applications and _mac_files_for_application. + +_mac_apps_caching_policy () { + # Rebuild if cache is more than a day old + oldp=( "$1"(Nmw+1) ) + (( $#oldp )) +} + +_retrieve_mac_apps() { + local cache_policy + zstyle -s ":completion:*:*:$service:*" cache-policy cache_policy + if [[ -z "$cache_policy" ]]; then + zstyle ":completion:*:*:$service:*" cache-policy _mac_apps_caching_policy + fi + + if ( [[ ${+_mac_apps} -eq 0 ]] || _cache_invalid Mac_applications ) \ + && ! _retrieve_cache Mac_applications; then + + # Get directories which may contain applications + typeset -aU app_dir + if [[ -z "$app_dir" ]] && \ + ! zstyle -s ":completion:${curcontext}:commands" application-dir app_dir + then + typeset -a app_dir_stop_pattern app_dir_root + app_dir_stop_pattern=( "*.app" "contents#" "*data" "*plugins#" "*plug?ins#" "fonts#" "document[[:alpha:]]#" "*help" "resources#" "images#" "*configurations#" ) + app_dir_root=( {,/Developer,/Network,"$HOME"}/{Applications*(N),Desktop} ) + typeset app_dir_pattern + app_dir_pattern="(^(#i)(${(j/|/)app_dir_stop_pattern}))" + app_dir=( ${^app_dir_root}/(${~app_dir_pattern}/)#(N) ) + fi + + typeset -g -Ua _mac_apps + local -a app_result + + # Get application bundles + if ! zstyle -t ":completion:${curcontext}:commands" ignore-bundle; then + app_result=( ${^app_dir}*/Contents/(MacOS|MacOSClassic)(N) ) + _mac_apps+=( ${app_result[@]%/Contents/MacOS*} ) + fi + + # Get single file applications + if ! zstyle -t ":completion:${curcontext}:commands" ignore-single; then + autoload -U zargs + local app_cand nargs envvars + app_cand=( ${^app_dir}^*.[a-z]#/..namedfork/rsrc(.UrN,.RN^U) ) + envvars="$(builtin typeset -x)" + nargs=$(( $(command sysctl -n kern.argmax) - $#envvars - 2048 )) + app_result="$(zargs --max-chars $nargs ${app_cand[@]} -- grep -l APPL)" + _mac_apps+=( ${${(f)app_result}%/..namedfork/rsrc} ) + fi + + _store_cache Mac_applications _mac_apps + fi +} + +_retrieve_mac_apps "$@" -- cgit 1.4.1