about summary refs log tree commit diff
path: root/Completion/Darwin/Type
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2004-11-12 11:47:41 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2004-11-12 11:47:41 +0000
commit24a68220a105c70a54baa543917e1022ae3e7a8d (patch)
treebb89747d3925cbb9c97afef53db3659ecedf027e /Completion/Darwin/Type
parente4ba1a2ec8cd6b73d6e931e00e4a5d16e131a473 (diff)
downloadzsh-24a68220a105c70a54baa543917e1022ae3e7a8d.tar.gz
zsh-24a68220a105c70a54baa543917e1022ae3e7a8d.tar.xz
zsh-24a68220a105c70a54baa543917e1022ae3e7a8d.zip
improved Mac completion, from Motoi Washida
Diffstat (limited to 'Completion/Darwin/Type')
-rw-r--r--Completion/Darwin/Type/_mac_applications51
-rw-r--r--Completion/Darwin/Type/_mac_files_for_application74
-rw-r--r--Completion/Darwin/Type/_retrieve_mac_apps59
3 files changed, 136 insertions, 48 deletions
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 "$@"