#compdef mdfind

 

# Author: W. G. Scott
# Revised for 10.5 on Jan 22 2009
# July 5 2005
# for Mac OS X v. 10.4 and above
 
# set -x

#  Use a new version for 10.5 and above:

if [[  $(uname) == Darwin && $(sw_vers -productVersion) < 10.5  ]]; then



#  Old version of completion function for OS X 10.4:
_mdfind () { 
    
    ########################################################################################################
    # These have to be put in the environment file to work the first time
    #
    zmodload zsh/complist  2>/dev/null
    zstyle ':completion:*' menu select=10  
    zstyle ':completion:*' list-prompt '%S -- more -- %s' 
    zstyle ':completion:*' group-name '' 
    
    #########################################################################################################
    # SYNOPSIS  mdfind [-0] [-live] [-onlyin directory] query  
    #
    #    -0          Prints an ASCII NUL character after each result path.  This
    #                is useful when used in conjunction with xargs -0.
    #
    #     -live       Causes the mdfind command to provide live-updates to the num-
    #                 ber of files matching the query.  When an update causes the
    #                 query results to change the number of matches is updated.
    #                 The find can be cancelled by typing ctrl-C.            
    #
    #     -onlyin dir
    #                 Limit the scope of the search to the directory specified.
    #
    # example:
    # mdfind -onlyin /Applications -onlyin /Developer "kMDItemContentType == 'com.apple.application-*'"
    
    ########################################################################################################
        
       _arguments -C \
        '-gui[use GUI menu of completions]: :->usethegui'\
        '-0[used in conjunction with xargs -0]'\
        '-live[live updates in search]'\
        '-onlyin[specify the Directory]: :->mdsearchpath'\
        '*: :->mdsearchstring'
       
    ####################################################################################     
    # These functions are for "mdsearchstring"
                
                # This function corresponds to simply entering any unrestricted string. 
                # There isn't anything to complete, but we need to add a space to get it to 
                # work right.  (The _nothing fuction I would think should work, but it doesn't.)
                
                function _stringquery { 
                    compadd -X %B'          i.e., type in your search string at the prompt,     %b' " " 
                    #_message "Now type in your search string,"  
                }
                
                ########################################################################################
            
                # This function generates a template for a search that is to be confined to a specified
                # metadata attribute.  It uses mdimport -A to find the list of possibilities, and then
                # generates a template as the completion.  It terminates with a single and double quote.
                # The quoting structure is important.
                
                function _querycomp {
                   compadd  -X %B'          or select one of the metadata attributes for searching from the menu below %b' \
                   -Q -P \" -p kMDItem -S " == '*YourSearchStringGoesHere*'\"" $(/usr/bin/mdimport -A | awk '{print $1}' | \
                   perl -p -e "s;('|kMDItem);;g"    ) 
                }
                
                ########################################################################################
                
                # If we want to add a second metadata search template, we have to first remove the
                # trailing double quote that follows the single quote generated by _querycomp
                
                function _chomp { BUFFER=${BUFFER/\'\"/\'}  }                          #'
                
                ########################################################################################
                
                # This function first calls _chomp to chomp off the double quote, and then it appends the
                # Boolean AND operator (&&) and then the second template, which closes with a single and
                # then double quote.  Any number of these can be added recursively, thanks to putting the
                # _chomp function at the beginning.
                
                function _queryandcomp {   
                    # Boolean and to append a second query   
                    compadd -R _chomp -X %B'The metadata attributes, below, alternate Boolian AND and OR %b' \
                   -Q -P \&\&\  -p kMDItem -S \
                   " == '*YourSearchStringGoesHere*'\"" $(/usr/bin/mdimport -A | awk '{print $1}' | \
                   perl -p -e "s;('|kMDItem);;g"    )  
                }
                
                ########################################################################################
                
                # Same as _queryand, except uses the Boolean OR operator (||).
                
                function _queryorcomp {
                    # Boolean or appends a second query     
                    compadd -R _chomp -X %B'The metadata attributes, below, alternate Boolian AND and OR  %b' \
                   -Q -P \|\|\  -p kMDItem -S \
                   " == '*YourSearchStringGoesHere*'\"" $(/usr/bin/mdimport -A | awk '{print $1}' | \
                   perl -p -e "s;('|kMDItem);;g"    )  
                }   
                
                ########################################################################################
                                                                            
 
    
    ####################################################################################
    ####################################################################################

    
    
      case "$state" in
      
          (usethegui)
              _message 'Using Pashua GUI menu: please select a completion category'
              _mdfind_pashua
              
        ;;
      
          (mdsearchstring)
                if [[ $words == *kMDItem* && $words != *gui* ]];then
                    _message "Adding another searching criterion ..."
                    _alternative _queryandcomp _queryorcomp
                elif [[ $words == *kMDItem* ]];then
                    _message "Adding another searching criterion ..."
                    _message 'Using Pashua GUI menu: please select a completion category'
                    _mdfind_pashua                
                else
                    _message "Enter any string either by itself or by replacing \"YourStringGoesHere\" in the metadata search template."
                    _alternative  _stringquery  _querycomp 
                fi      
          ;;
          
          (mdsearchpath)
                _directories  
                _message 'possible search paths: prepend / for root-level directories'
          ;;
      
      esac
    
    
    
}

else

#  New version of completion function for OS X 10.5 and above:

_mdfind () { 
    
    ########################################################################################################
    # These have to be put in the environment file to work the first time
    #
    zmodload zsh/complist  2>/dev/null
    zstyle ':completion:*' menu select=10  
    zstyle ':completion:*' list-prompt '%S -- more -- %s' 
    zstyle ':completion:*' group-name '' 
    
    #########################################################################################################
    #  
    #  	SYNOPSIS
    #  	     mdfind [-live] [-count] [-onlyin directory] query
    #  
    #  	DESCRIPTION
    #  	     The mdfind command consults the central metadata store and returns a list of files that match the given
    #  	     metadata query. The query can be a string or a query expression.
    #  
    #  	     The following options are available:
    #  
    #  	     -0          Prints an ASCII NUL character after each result path.  This is useful when used in conjunc-
    #  	                 tion with xargs -0.
    #  
    #  	     -live       Causes the mdfind command to provide live-updates to the number of files matching the
    #  	                 query.  When an update causes the query results to change the number of matches is updated.
    #  	                 The find can be cancelled by typing ctrl-C.
    #  
    #  	     -count      Causes the mdfind command to output the total number of matches, instead of the path to the
    #  	                 matching items.
    #  
    #  	     -onlyin dir
    #  	                 Limit the scope of the search to the directory specified.
    #  
    #  	     -literal    Force the provided query string to be taken as a literal query string, without interpreta-
    #  	                 tion.
    #  
    #  	     -interpret  Force the provided query string to be interpreted as if the user had typed the string into
    #  	                 the Spotlight menu.  For example, the string "search" would produce the following query
    #  	                 string:
    #  	                       (* = search* cdw || kMDItemTextContent = search* cdw)
    #  
    #  	EXAMPLES
    #  	     The following examples are shown as given to the shell.
    #  
    #  	     This returns all files with any metadata attribute value matching the string "image":
    #  
    #  	           mdfind image
    #  
    #  	     This returns all files that contain "MyFavoriteAuthor" in the kMDItemAuthor metadata attribute:
    #  
    #  	           mdfind "kMDItemAuthor == '*MyFavoriteAuthor*'"
    #  
    #  	     This returns all files with any metadata attribute value matching the string "skateboard".  The find
    #  	     continues to run after gathering the initial results, providing a count of the number of files that
    #  	     match the query.
    #  
    #  	           mdfind -live skateboard
    #
    #       relevant example:
    #
    #              mdfind -onlyin /Applications -onlyin /Developer "kMDItemContentType == 'com.apple.application-*'"
    
    ########################################################################################################

        
       _arguments -C \
        '-0[used in conjunction with xargs -0]: :->supply_pattern'\
        '-s[show contents of smart folder <name>]: :->savedSearch'\
        '-count[output total number of matches]: :->supply_pattern' \
        '-interpret[user-friendly Spotlight string query]: :->supply_pattern'\
        '-literal[force over-rides interpret]: :->mdsearchstring'\
        '-live[live updates in search]: :->supply_pattern'\
        '-onlyin[specify the Directory]: :->mdsearchpath'\
        '*: :->supply_pattern_or_option'


#       '*:pattern: '


    ####################################################################################     
    # This function is for "savedSearch"

        function _SavedSearches { 
	    compadd  \
	     "${(f)"$( command ls ~/Library/Saved\ Searches/**/*.savedSearch | perl -p -e "s|$HOME/Library/Saved\ Searches/||g",'s|.savedSearch||g' )"}"
	    }

       
    ####################################################################################     
    # These functions are for "mdsearchstring"

		# This function corresponds to simply entering any unrestricted string. 
		# There isn't anything to complete, but we need to add a space to get it to 
		# work right.  (The _nothing fuction I would think should work, but it doesn't.)

		function _stringquery { 
		    compadd -X %B'          i.e., type in your search string at the prompt,     %b' " " 
		    #_message "Now type in your search string,"  
		}

		########################################################################################

		# This function generates a template for a search that is to be confined to a specified
		# metadata attribute.  It uses mdimport -A to find the list of possibilities, and then
		# generates a template as the completion.  It terminates with a single and double quote.
		# The quoting structure is important.

		function _querycomp {
		   compadd  -X %B'          or select one of the metadata attributes for searching from the menu below %b' \
		   -Q -P \" -p kMDItem -S " == '*YourSearchStringGoesHere*'\"" $(/usr/bin/mdimport -A | awk '{print $1}' | \
		   perl -p -e "s;('|kMDItem);;g"    ) 
		}

		########################################################################################

		# If we want to add a second metadata search template, we have to first remove the
		# trailing double quote that follows the single quote generated by _querycomp

		function _chomp { BUFFER=${BUFFER/\'\"/\'}  }                          #'

		########################################################################################

		# This function first calls _chomp to chomp off the double quote, and then it appends the
		# Boolean AND operator (&&) and then the second template, which closes with a single and
		# then double quote.  Any number of these can be added recursively, thanks to putting the
		# _chomp function at the beginning.

		function _queryandcomp {   
		    # Boolean and to append a second query   
		    compadd -R _chomp -X %B'The metadata attributes, below, alternate Boolian AND and OR %b' \
		   -Q -P \&\&\  -p kMDItem -S \
		   " == '*YourSearchStringGoesHere*'\"" $(/usr/bin/mdimport -A | awk '{print $1}' | \
		   perl -p -e "s;('|kMDItem);;g"    )  
		}

		########################################################################################

		# Same as _queryand, except uses the Boolean OR operator (||).

		function _queryorcomp {
		    # Boolean or appends a second query     
		    compadd -R _chomp -X %B'The metadata attributes, below, alternate Boolian AND and OR  %b' \
		   -Q -P \|\|\  -p kMDItem -S \
		   " == '*YourSearchStringGoesHere*'\"" $(/usr/bin/mdimport -A | awk '{print $1}' | \
		   perl -p -e "s;('|kMDItem);;g"    )  
		}   

		########################################################################################
                                                                           
 
    
    ####################################################################################
    ####################################################################################

    
    
      case "$state" in
      
          (mdsearchstring)
                if [[ $words == *kMDItem* && $words != *gui* ]];then
                    _message "Adding another searching criterion ..."
                    _alternative _queryandcomp _queryorcomp
                elif [[ $words == *kMDItem* ]];then
                    _message "Adding another searching criterion ..."
                    _message 'Using Pashua GUI menu: please select a completion category'
                    _mdfind_pashua                
                else
                    _message "Enter any string either by itself or by replacing \"YourStringGoesHere\" in the metadata search template."
                    _alternative  _stringquery  _querycomp 
                fi      
          ;;
          
          (mdsearchpath)
                _directories  
                _message 'possible search paths: prepend / for root-level directories'
          ;;

          (savedSearch)
                _SavedSearches  
                _message 'possible Saved Searches in $HOME/Library/Saved\ Searches'
          ;;
 
          (supply_pattern)
               _message "Enter any string you would supply to SpotLight."
          ;;


  	  	 (supply_pattern_or_option)
		      _message "Enter \"-<tab>\" to choose an option, or simply type any string you would supply to SpotLight."
		  ;;
     
      esac
    

}

fi # Test OS X 10.5 or above

_mdfind "$@" 



