mirror of
				git://git.code.sf.net/p/zsh/code
				synced 2025-10-31 06:00:54 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			347 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			347 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| #autoload
 | |
| 
 | |
| # usage: _apt_arguments funcname option-spec... -- rest-regex
 | |
| 
 | |
| local funcname
 | |
| funcname="$1"
 | |
| shift
 | |
| 
 | |
| typeset -A canonicalize options
 | |
| local short_hasarg short_bool short_intlevel short_configfile short_arbitem
 | |
| local long_hasarg long_bool long_intlevel long_configfile long_arbitem
 | |
| local comp_hasarg=''
 | |
| local opt opts type
 | |
| 
 | |
| while [[ 0 -lt $# && $1 != -- ]]; do
 | |
|   opts="${1%%:*}"
 | |
|   type="${1#*:}"
 | |
| 
 | |
|   case $type in
 | |
|     bool) options[$opts]=1;;
 | |
|     intlevel) options[$opts]=-1;;
 | |
|     configfile) options[$opts]=1;;
 | |
|     arbitem) options[$opts]=-1;;
 | |
|     *) options[$opts]=1
 | |
|        comp_hasarg="${comp_hasarg}$opts) $type;;
 | |
| "
 | |
|        type=hasarg;;
 | |
|   esac
 | |
| 
 | |
|   for opt in ${(s:,:)=opts}; do
 | |
|     canonicalize[$opt]="$opts"
 | |
|     case $opt in
 | |
|       --*) eval "long_$type=(\$long_$type ${opt#--})";;
 | |
|       -?) eval "short_$type=(\$short_$type ${opt#-})";;
 | |
|     esac
 | |
|   done
 | |
|   shift
 | |
| done
 | |
| 
 | |
| # skip --
 | |
| [[ 0 -lt $# ]] && shift
 | |
| 
 | |
| comp_hasarg="\
 | |
| case \$current_option in
 | |
| ${comp_hasarg}esac"
 | |
| 
 | |
| local short_seq false true bool __bool_ intlevel word word1 nul
 | |
| local comp_bool comp_intlevel comp_configfile comp_arbitem comp_long comp_opt
 | |
| local regex_short regex_long regex_all
 | |
| 
 | |
| regex_all=("$@")
 | |
| 
 | |
| short_seq="(${(j:|:)short_bool}|${(j:|:)short_intlevel})#"
 | |
| 
 | |
| false=(no false without off disable)
 | |
| true=(yes true with on enable)
 | |
| bool=($false $true)
 | |
| 
 | |
| __bool_=(--${^bool}-)
 | |
| 
 | |
| intlevel='[0-9]##'
 | |
| 
 | |
| word=$'[^\0]#\0'
 | |
| word1=$'[^\0]##\0'
 | |
| nul=$'\0'
 | |
| 
 | |
| comp_bool='compadd "$expl_bool[@]" '"$bool"
 | |
| comp_intlevel= #"_message 'intlevel'"
 | |
| comp_configfile='_files "$expl_configfile[@]"'
 | |
| comp_arbitem= #"_message 'Foo::Bar=bar'"
 | |
| 
 | |
| comp_short=\
 | |
| 'if [[ $PREFIX = -'"$short_seq"' ]]; then
 | |
|   apt_consume_short ${PREFIX[2,-1]}
 | |
|   tmp1=(${${(M)${(s:,:)${(kj:,:)options[(R)*~0]}}:#-?}#-})
 | |
|   if [[ $PREFIX = - ]]; then
 | |
|     compadd "$expl_opt[@]" - -${^tmp1}
 | |
|   else
 | |
|     tmp2=(-${^tmp1})
 | |
|     compadd "$expl_opt[@]" -y "($tmp2)" - ${PREFIX}${^tmp1}
 | |
|   fi
 | |
| elif [[ -z "$PREFIX" ]]; then
 | |
|   compadd "$expl_opt[@]" - ${(M)${(s:,:)${(kj:,:)options[(R)*~0]}}:#-?}
 | |
| fi'
 | |
| 
 | |
| comp_long=\
 | |
| 'tmp1="${(j:|:)${(@)${(@M)${(@s:,:)${(@kj:,:)options[(R)*~0]}}:#--*}#--}}"
 | |
| tmp2=(--${(M)^long_bool:#$~tmp1} --${(M)^long_intlevel:#$~tmp1})
 | |
| compadd "$expl_opt[@]" - $tmp2
 | |
| tmp2=(--${(M)^long_hasarg:#$~tmp1} --${(M)^long_configfile:#$~tmp1} --${(M)^long_arbitem:#$~tmp1})
 | |
| compadd "$expl_opt[@]" -S= - $tmp2
 | |
| compadd "$expl_opt[@]" -S "" - '"$__bool_"
 | |
| 
 | |
| comp_long_prefix=\
 | |
| 'tmp1="${(j:|:)${(@)${(@M)${(@s:,:)${(@kj:,:)options[(R)*~0]}}:#--*}#--}}"
 | |
| tmp2=($_ra_left${(M)^long_bool:#$~tmp1} $_ra_left${(M)^long_intlevel:#$~tmp1})
 | |
| compadd "$expl_opt[@]" - $tmp2
 | |
| tmp2=($_ra_left${(M)^long_hasarg:#$~tmp1} $_ra_left${(M)^long_configfile:#$~tmp1} $_ra_left${(M)^long_arbitem:#$~tmp1})
 | |
| compadd "$expl_opt[@]" -S= - $tmp2
 | |
| tmp1="${(j:|:)${(@)${(@M)${(@s:,:)${(@kj:,:)options[(R)*~0]}}:#-?}#-}}"
 | |
| tmp2=($_ra_left${(M)^short_bool:#$~tmp1} $_ra_left${(M)^short_intlevel:#$~tmp1})
 | |
| compadd "$expl_opt[@]" - $tmp2
 | |
| tmp2=($_ra_left${(M)^short_hasarg:#$~tmp1} $_ra_left${(M)^short_configfile:#$~tmp1} $_ra_left${(M)^short_arbitem:#$~tmp1})
 | |
| compadd "$expl_opt[@]" -S= - $tmp2'
 | |
| 
 | |
| comp_opt='[[ -prefix - || -z "$compconfig[option_prefix]" ]]'" && { $comp_short; $comp_long }"
 | |
| 
 | |
| regex_short=()
 | |
| regex_long=()
 | |
| regex_long_prefix=()
 | |
| 
 | |
| if (( $#short_hasarg )); then
 | |
|   regex_short=("$regex_short[@]"
 | |
|     /"$short_seq(${(j:|:)short_hasarg})(=|)"
 | |
|       -'apt_consume_short ${_ra_match%=}; current_option=${canonicalize[-${${_ra_match%=}[-1]}]}'
 | |
|       \( /"$word1" !"$comp_hasarg" \| /"$nul" /"$word" !"$comp_hasarg" \) \|
 | |
|   )
 | |
|   regex_long_prefix=("$regex_long_prefix[@]"
 | |
|     /"(${(j:|:)short_hasarg})$nul"
 | |
|       -'apt_consume_short ${_ra_match[-2]}; current_option=${canonicalize[-${${_ra_match%$nul}[-1]}]}'
 | |
|       /"$word" !"$comp_hasarg" \|
 | |
|     /"(${(j:|:)short_hasarg})="
 | |
|       -'apt_consume_short ${_ra_match[-2]}; current_option=${canonicalize[-${${_ra_match%=}[-1]}]}'
 | |
|       \( /"$word1" !"$comp_hasarg" \| /"$nul" /"$word" !"$comp_hasarg" \) \|
 | |
|   )
 | |
| fi
 | |
| 
 | |
| if (( $#short_bool )); then
 | |
|   regex_short=("$regex_short[@]"
 | |
|     /"$short_seq(${(j:|:)short_bool})($nul(${(j:|:)bool})|(${(j:|:)bool})|)$nul"
 | |
|       -"apt_consume_short \${_ra_match%%($nul(${(j:|:)bool})|(${(j:|:)bool})|)$nul}" \|
 | |
|     /"$short_seq(${(j:|:)short_bool})="
 | |
|       -"apt_consume_short \${_ra_match%=}"
 | |
|       \( /"$word1" !"$comp_bool" \| /"$nul" /"$word" !"$comp_bool" \) \|
 | |
|   )
 | |
|   regex_long_prefix=("$regex_long_prefix[@]"
 | |
|     /"(${(j:|:)short_bool})="
 | |
|       -"apt_consume_short \${_ra_match[-2]}"
 | |
|       \( /"$word1" !"$comp_bool" \| /"$nul" /"$word" !"$comp_bool" \) \|
 | |
|     /"(${(j:|:)short_bool})$nul"
 | |
|       -"apt_consume_short \${_ra_match[-2]}"
 | |
|       /"((${(j:|:)bool})$nul|)" !"$comp_bool" \|
 | |
|   )
 | |
| fi
 | |
| 
 | |
| if (( $#short_intlevel )); then
 | |
|   regex_short=("$regex_short[@]"
 | |
|     /"$short_seq(${(j:|:)short_intlevel})($nul$intlevel|$intlevel|)$nul"
 | |
|       -"apt_consume_short \${_ra_match%%($nul$intlevel|$intlevel|)$nul}" \|
 | |
|     /"$short_seq(${(j:|:)short_intlevel})="
 | |
|       -"apt_consume_short \${_ra_match%=}"
 | |
|       \( /"$word1" !"$comp_intlevel" \| /"$nul" /"$word" !"$comp_intlevel" \) \|
 | |
|   )
 | |
|   regex_long_prefix=("$regex_long_prefix[@]"
 | |
|     /"(${(j:|:)short_intlevel})="
 | |
|       -"apt_consume_short \${_ra_match[-2]}"
 | |
|       \( /"$word1" !"$comp_intlevel" \| /"$nul" /"$word" !"$comp_intlevel" \) \|
 | |
|     /"(${(j:|:)short_intlevel})$nul"
 | |
|       -"apt_consume_short \${_ra_match[-2]}"
 | |
|       /"($intlevel$nul|)" !"$comp_intlevel" \|
 | |
|   )
 | |
| fi
 | |
| 
 | |
| if (( $#short_configfile )); then
 | |
|   regex_short=("$regex_short[@]"
 | |
|     /"$short_seq(${(j:|:)short_configfile})(=|)"
 | |
|       -"apt_consume_short \${_ra_match%=}"
 | |
|       \( /"$word1" !"$comp_configfile" \| /"$nul" /"$word" !"$comp_configfile" \) \|
 | |
|   )
 | |
|   regex_long_prefix=("$regex_long_prefix[@]"
 | |
|     /"(${(j:|:)short_configfile})$nul"
 | |
|       -"apt_consume_short \${_ra_match[-2]}"
 | |
|       /"$word" !"$comp_configfile" \|
 | |
|     /"(${(j:|:)short_configfile})="
 | |
|       -"apt_consume_short \${_ra_match[-2]}"
 | |
|       \( /"$word1" !"$comp_configfile" \| /"$nul" /"$word" !"$comp_configfile" \) \|
 | |
|   )
 | |
| fi
 | |
| 
 | |
| if (( $#short_arbitem )); then
 | |
|   regex_short=("$regex_short[@]"
 | |
|     /"$short_seq(${(j:|:)short_arbitem})(=|)"
 | |
|       -"apt_consume_short \${_ra_match%=}"
 | |
|       \( /"$word1" !"$comp_arbitem" \| /"$nul" /"$word" !"$comp_arbitem" \) \|
 | |
|   )
 | |
|   regex_long_prefix=("$regex_long_prefix[@]"
 | |
|     /"(${(j:|:)short_arbitem})$nul"
 | |
|       -"apt_consume_short \${_ra_match[-2]}"
 | |
|       /"$word" !"$comp_arbitem" \|
 | |
|     /"(${(j:|:)short_arbitem})="
 | |
|       -"apt_consume_short \${_ra_match[-2]}"
 | |
|       \( /"$word1" !"$comp_arbitem" \| /"$nul" /"$word" !"$comp_arbitem" \) \|
 | |
|   )
 | |
| fi
 | |
| 
 | |
| if (( $#long_hasarg )); then
 | |
|   regex_long=("$regex_long[@]"
 | |
|     /"(${(j:|:)long_hasarg})$nul"
 | |
|       -"apt_consume_long \${_ra_match%$nul}; current_option=\${canonicalize[--\${_ra_match%$nul}]}"
 | |
|       /"$word" !"$comp_hasarg" \|
 | |
|     /"(${(j:|:)long_hasarg})="
 | |
|       -"apt_consume_long \${_ra_match%=}; current_option=\${canonicalize[--\${_ra_match%=}]}"
 | |
|       \( /"$word1" !"$comp_hasarg" \| /"$nul" /"$word" !"$comp_hasarg" \) \|
 | |
|   )
 | |
|   regex_long_prefix=("$regex_long_prefix[@]"
 | |
|     /"(${(j:|:)long_hasarg})$nul"
 | |
|       -"apt_consume_long \${_ra_match%$nul}; current_option=\${canonicalize[--\${_ra_match%$nul}]}"
 | |
|       /"$word" !"$comp_hasarg" \|
 | |
|     /"(${(j:|:)long_hasarg})="
 | |
|       -"apt_consume_long \${_ra_match%=}; current_option=\${canonicalize[--\${_ra_match%=}]}"
 | |
|       \( /"$word1" !"$comp_hasarg" \| /"$nul" /"$word" !"$comp_hasarg" \) \|
 | |
|   )
 | |
| fi
 | |
| 
 | |
| if (( $#long_bool )); then
 | |
|   regex_long=("$regex_long[@]"
 | |
|     /"(${(j:|:)long_bool})="
 | |
|       -"apt_consume_long \${_ra_match%=}"
 | |
|       \( /"$word1" !"$comp_bool" \| /"$nul" /"$word" !"$comp_bool" \) \|
 | |
|     /"(${(j:|:)long_bool})$nul"
 | |
|       -"apt_consume_long \${_ra_match%$nul}"
 | |
|       /"((${(j:|:)bool})$nul|)" !"$comp_bool" \|
 | |
|   )
 | |
|   regex_long_prefix=("$regex_long_prefix[@]"
 | |
|     /"(${(j:|:)long_bool})="
 | |
|       -"apt_consume_long \${_ra_match%=}"
 | |
|       \( /"$word1" !"$comp_bool" \| /"$nul" /"$word" !"$comp_bool" \) \|
 | |
|     /"(${(j:|:)long_bool})$nul"
 | |
|       -"apt_consume_long \${_ra_match%$nul}"
 | |
|       /"((${(j:|:)bool})$nul|)" !"$comp_bool" \|
 | |
|   )
 | |
| fi
 | |
| 
 | |
| if (( $#long_intlevel )); then
 | |
|   regex_long=("$regex_long[@]"
 | |
|     /"(${(j:|:)long_intlevel})="
 | |
|       -"apt_consume_long \${_ra_match%=}"
 | |
|       \( /"$word1" !"$comp_intlevel" \| /"$nul" /"$word" !"$comp_intlevel" \) \|
 | |
|     /"(${(j:|:)long_intlevel})$nul"
 | |
|       -"apt_consume_long \${_ra_match%$nul}"
 | |
|       /"($intlevel$nul|)" !"$comp_intlevel" \|
 | |
|   )
 | |
|   regex_long_prefix=("$regex_long_prefix[@]"
 | |
|     /"(${(j:|:)long_intlevel})$nul"
 | |
|       -"apt_consume_long \${_ra_match%$nul}"
 | |
|       /"$intlevel" !"$comp_intlevel" /"$nul" \|
 | |
|     /"(${(j:|:)long_intlevel})="
 | |
|       -"apt_consume_long \${_ra_match%=}"
 | |
|       \( /"$word1" !"$comp_intlevel" \| /"$nul" /"$word" !"$comp_intlevel" \) \|
 | |
|     /"(${(j:|:)long_intlevel})$nul"
 | |
|       -"apt_consume_long \${_ra_match%$nul}"
 | |
|       /"($intlevel$nul|)" !"$comp_intlevel" \|
 | |
|   )
 | |
| fi
 | |
| 
 | |
| if (( $#long_configfile )); then
 | |
|   regex_long=("$regex_long[@]"
 | |
|     /"(${(j:|:)long_configfile})$nul"
 | |
|       -"apt_consume_long \${_ra_match%$nul}"
 | |
|       /"$word" !"$comp_configfile" \|
 | |
|     /"(${(j:|:)long_configfile})="
 | |
|       -"apt_consume_long \${_ra_match%=}"
 | |
|       \( /"$word1" !"$comp_configfile" \| /"$nul" /"$word" !"$comp_configfile" \) \|
 | |
|   )
 | |
|   regex_long_prefix=("$regex_long_prefix[@]"
 | |
|     /"(${(j:|:)long_configfile})$nul"
 | |
|       -"apt_consume_long \${_ra_match%$nul}"
 | |
|       /"$word" !"$comp_configfile" \|
 | |
|     /"(${(j:|:)long_configfile})="
 | |
|       -"apt_consume_long \${_ra_match%=}"
 | |
|       \( /"$word1" !"$comp_configfile" \| /"$nul" /"$word" !"$comp_configfile" \) \|
 | |
|   )
 | |
| fi
 | |
| 
 | |
| if (( $#long_arbitem )); then
 | |
|   regex_long=("$regex_long[@]"
 | |
|     /"(${(j:|:)long_arbitem})$nul"
 | |
|       -"apt_consume_long \${_ra_match%$nul}"
 | |
|       /"$word" !"$comp_arbitem" \|
 | |
|     /"(${(j:|:)long_arbitem})="
 | |
|       -"apt_consume_long \${_ra_match%=}"
 | |
|       \( /"$word1" !"$comp_arbitem" \| /"$nul" /"$word" !"$comp_arbitem" \) \|
 | |
|   )
 | |
|   regex_long_prefix=("$regex_long_prefix[@]"
 | |
|     /"(${(j:|:)long_arbitem})$nul"
 | |
|       -"apt_consume_long \${_ra_match%$nul}"
 | |
|       /"$word" !"$comp_arbitem" \|
 | |
|     /"(${(j:|:)long_arbitem})="
 | |
|       -"apt_consume_long \${_ra_match%=}"
 | |
|       \( /"$word1" !"$comp_arbitem" \| /"$nul" /"$word" !"$comp_arbitem" \) \|
 | |
|   )
 | |
| fi
 | |
| 
 | |
| regex_all=(
 | |
|   /"$word"
 | |
|   \( %-- \( "$regex_long[@]"
 | |
| 	    %"(${(j:|:)bool})-"
 | |
| 	    \( "$regex_long_prefix[@]" /"[]" !"$comp_long_prefix" \) \|
 | |
| 	    /"[]" !"$comp_long" \) \|
 | |
|      %- \( "$regex_short[@]" /"[]" !"$comp_short; $comp_long" \) \|
 | |
|      /"[]" !"$comp_opt" \) \#
 | |
|   "$regex_all[@]"
 | |
| )
 | |
| 
 | |
| apt_consume_short () {
 | |
|   local short opt
 | |
|   for short in ${(s::)1}; do
 | |
|     opt="$canonicalize[-$short]"
 | |
|     (( 0 < options[$opt] && options[$opt]-- ))
 | |
|   done
 | |
| }
 | |
| 
 | |
| apt_consume_long () {
 | |
|   local long opt
 | |
|   opt="$canonicalize[--$1]"
 | |
|   (( 0 < options[$opt] && options[$opt]-- ))
 | |
| }
 | |
| 
 | |
| _regex_arguments "${funcname}_sm" "$regex_all[@]"
 | |
| 
 | |
| eval "$funcname () {
 | |
|   typeset -A canonicalize options
 | |
|   canonicalize=(${(kv)canonicalize})
 | |
|   options=(${(kv)options})
 | |
| 
 | |
|   local short_hasarg short_bool short_intlevel short_configfile short_arbitem
 | |
|   local long_hasarg long_bool long_intlevel long_configfile long_arbitem
 | |
|   short_hasarg=($short_hasarg)
 | |
|   short_bool=($short_bool)
 | |
|   short_intlevel=($short_intlevel)
 | |
|   short_configfile=($short_configfile)
 | |
|   short_arbitem=($short_arbitem)
 | |
|   long_hasarg=($long_hasarg)
 | |
|   long_bool=($long_bool)
 | |
|   long_intlevel=($long_intlevel)
 | |
|   long_configfile=($long_configfile)
 | |
|   long_arbitem=($long_arbitem)
 | |
| 
 | |
|   local expl_opt expl_bool expl_configfile
 | |
|   _description expl_opt option
 | |
|   _description expl_bool 'bool value'
 | |
|   _description expl_configfile 'config file'
 | |
| 
 | |
|   local current_option tmp1 tmp2
 | |
| 
 | |
|   ${funcname}_sm
 | |
| }"
 |