Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
[PATCH] _mac_applications: merge _retrieve_mac_apps + simplify
- X-seq: zsh-workers 54975
- From: dana <dana@xxxxxxx>
- To: zsh-workers@xxxxxxx
- Subject: [PATCH] _mac_applications: merge _retrieve_mac_apps + simplify
- Date: Tue, 14 Jul 2026 23:02:28 -0500
- Archived-at: <https://zsh.org/workers/54975>
- Feedback-id: i9be146f9:Fastmail
- List-id: <zsh-workers.zsh.org>
while i'm working on feedback here's a follow-up to w/54915
_retrieve_mac_apps is a 'type' function that does nothing but populate a
cache. most of its functionality has been obsolete for 15-20 years. this
simplifies it and merges it into its primary consumer, _mac_applications
in _firefox and _chromium i used this -0 option which is like -O except
it doesn't try to match, isn't as prone to parameter name collisions,
and supports multiple NUL-delimited fields. maybe it's not as useful
here (only one field) but i carried it over anyway. if i'm not stopped
it could spread further
also fixes a small issue with open -b
dana
diff --git a/Completion/Darwin/Command/_open b/Completion/Darwin/Command/_open
index 079dd2987..1a9758769 100644
--- a/Completion/Darwin/Command/_open
+++ b/Completion/Darwin/Command/_open
@@ -53,11 +53,10 @@ _open() {
;;
bundle-ids)
autoload -Uz zargs
- _retrieve_mac_apps
- tmp=( $_mac_apps )
+ _mac_applications -f0 tmp
tmp=( ${(0)"$(
- _call_program bundle-ids \
- zargs -n300 -P2 -- ${(@q)tmp} -- mdls -rn kMDItemCFBundleIdentifier
+ _call_program -q bundle-ids \
+ zargs -r -- $tmp -- mdls -rn kMDItemCFBundleIdentifier
)"} )
tmp=( ${(@)tmp:#\(null\)} com.apple.TextEdit )
_describe -t bundle-identifier 'bundle identifier' tmp && ret=0
@@ -65,7 +64,7 @@ _open() {
arguments)
local app exe
- _retrieve_mac_apps
+ _mac_applications -f0 tmp
# resolve bundle id or app name to path
if (( $+opt_args[-b] )); then
diff --git a/Completion/Darwin/Type/_mac_applications b/Completion/Darwin/Type/_mac_applications
index 7b633579c..137ed9881 100644
--- a/Completion/Darwin/Type/_mac_applications
+++ b/Completion/Darwin/Type/_mac_applications
@@ -1,7 +1,57 @@
#autoload
-_retrieve_mac_apps
+# complete names of macos applications
+# -0 <name> like -O, but return all possible matches
+# -a keep .app extension
+# -f keep full path + extension
+
+local -a ca_opts expl apps ign_pats
+local -A opth
+
+zparseopts -A opth -D -F - \
+ {1,2,A+:,D+:,J+:,M+:,o+:,O+:,P+:,q+,r+:,R+:,S+:,V+:,x+:,X+:}=ca_opts \
+ 0: a f \
+|| return
+
+apps=( ${(f)"$(
+ _call_program -q application-bundles \
+ mdfind "kMDItemContentType == 'com.apple.application-bundle'"
+)"} )
+
+# fall-back in case spotlight is disabled or something. 20 is arbitrary
+(( $#apps < 20 )) && apps+=(
+ {,/System,$HOME}/Applications/*.app(#qNoN-/)
+ {,/System,$HOME}/Applications/^*.app/*.app(#qNoN-/)
+ /Applications/Xcode.app/Contents/{,Developer/}Applications/*.app(#qNoN-/)
+ /System/Library/CoreServices/*.app(#qNoN-/)
+)
+
+# filter out some false positives. it's not clear to me what the search path is
+# for these, whether it varies between e.g. open and defaults. but these don't
+# seem useful in any case
+ign_pats=(
+ '/Library/Apple/System/Library/(|Private)Frameworks/*'
+ '/Library/Developer/CommandLineTools/*'
+ '/Library/Image Capture/*'
+ '/Library/PrivilegedHelperTools/*'
+ '/System/Library/Classroom/*'
+ /System/Library/CoreServices/liquiddetectiond.app # not a real app
+ '/System/Library/(|Private)Frameworks/*'
+ '/Users/*/Library/Application Support/*/Profiles/*/storage/*' # firefox garbage
+ '/Users/*/Library/HTTPStorages/*'
+)
+apps=( ${apps:#(${(j<|>)~ign_pats})} )
+
+if (( $+opth[-a] )); then
+ apps=( ${(@)apps:t} )
+elif (( ! $+opth[-f] )); then
+ apps=( ${(@)${(@)apps:t}%.app} )
+fi
+
+(( $+opth[-0] )) && {
+ trap "${opth[-0]}=( ${(j< >)${(@q+)apps}} )" EXIT
+ return $(( ! $#apps ))
+}
-local expl
_wanted commands expl 'macOS application' \
- compadd "$@" - "${(@)${_mac_apps[@]:t}%.app}"
+ compadd "${(@)ca_opts}" -a - apps
diff --git a/Completion/Darwin/Type/_retrieve_mac_apps b/Completion/Darwin/Type/_retrieve_mac_apps
deleted file mode 100644
index 8cfc3810e..000000000
--- a/Completion/Darwin/Type/_retrieve_mac_apps
+++ /dev/null
@@ -1,122 +0,0 @@
-#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
- local -a oldp
- oldp=( "$1"(Nmw+1) )
- (( $#oldp ))
-}
-
-
-# _mac_apps_*_retrieve
-#
-# Get search applications from directories specified in app_dir_root.
-# Paths to applications are stored in _mac_apps.
-
-_mac_apps_spotlight_retrieve () {
- typeset mdfind_query="kMDItemContentType == 'com.apple.application-bundle'"
-
- for i in ${app_dir_root}; do
- _mac_apps+=(${(f)"$(_call_program command \
- mdfind -onlyin ${(q)i} ${(q)mdfind_query})"})
- done
-}
-
-_mac_apps_old_retrieve () {
- # Get directories which may contain applications
- typeset -aU app_dir
- if [[ -z "$app_dir" ]] && \
- ! zstyle -a ":completion:${curcontext}:commands" application-dir app_dir
- then
- typeset -a app_dir_stop_pattern
- app_dir_stop_pattern=( "*.app" "contents#" "*data" "*plugins#" "*plug?ins#" "fonts#" "document[[:alpha:]]#" "*help" "resources#" "images#" "*configurations#" )
- typeset app_dir_pattern
- app_dir_pattern="(^(#i)(${(j/|/)app_dir_stop_pattern}))"
- app_dir=( ${^app_dir_root}/(${~app_dir_pattern}/)#(N) )
- fi
-
- # Get application bundles
- local -a app_result
-
- 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 -Uz 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
-}
-
-
-_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} == 0 )) || _cache_invalid Mac_applications ) \
- && ! _retrieve_cache Mac_applications; then
-
- # Get application search method
- typeset retrieve
- if ! zstyle -s ":completion:*:*:${service}:commands" search-method retrieve
- then
- if [[ "$( command mdutil -s / 2>&1 )" == *enabled* ]]; then
- # / is indexed to use Spotlight
- retrieve=_mac_apps_spotlight_retrieve
- else
- # Fall back to the old way
- retrieve=_mac_apps_old_retrieve
- fi
- zstyle ":completion:*:*:${service}:commands" search-method $retrieve
- fi
-
- # Get root directories to search applications
- typeset -a app_dir_root
- if ! zstyle -a ":completion:${curcontext}:" application-path app_dir_root
- then
- if [[ $retrieve = _mac_apps_old_retrieve ]]; then
- app_dir_root=(
- {,/Developer,/Network,/System,$HOME}/{Applications*(N),Desktop}
- )
- app_dir_root=( $^app_dir_root(N) )
- else
- app_dir_root=( / )
- fi
-
- zstyle ":completion:*" application-path $app_dir_root
- fi
-
- typeset -g -Ua _mac_apps
- $retrieve
-
- # filter out some false positives
- local -a ign_pats=(
- '/Library/Apple/System/Library/(|Private)Frameworks/*'
- '/Library/Developer/CommandLineTools/*'
- '/Library/Image Capture/*'
- '/Library/PrivilegedHelperTools/*'
- '/System/Library/(|Private)Frameworks/*'
- # firefox garbage
- '/Users/*/Library/Application Support/*/Profiles/*/storage/*'
- '/Users/*/Library/HTTPStorages/*'
- )
- _mac_apps=( ${_mac_apps:#(${(j<|>)~ign_pats})} )
-
- _store_cache Mac_applications _mac_apps
- fi
-}
-
-_retrieve_mac_apps "$@"
Messages sorted by:
Reverse Date,
Date,
Thread,
Author