1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-10-02 07:51:09 +02:00

merge changes from 4.1

This commit is contained in:
Oliver Kiddle 2003-02-28 13:50:44 +00:00
parent 937e1b9f79
commit 79d0de7c3a
5 changed files with 471 additions and 4 deletions

View file

@ -2,6 +2,21 @@
* 18303: zshconfig.ac: fix some always-true test evaluations.
2003-02-26 Oliver Kiddle <opk@zsh.org>
* 18300: Completion/Unix/Command/_tar,
Completion/Unix/Type/_tar_archive: handle tar's -C option better
2003-02-20 Oliver Kiddle <opk@zsh.org>
* 18263: Src/glob.c: fix saving of glob state so that globs can
be used from the (e) glob qualifier
2003-02-19 Oliver Kiddle <opk@zsh.org>
* 18262: Completion/Base/Utility/_multi_parts: fix bug where only
the first match was added with expand style set to suffix
2003-02-18 Oliver Kiddle <opk@zsh.org>
* Doug Kearns: 18259: Completion/Unix/Command/_webbrowser,
@ -404,7 +419,7 @@
* Matt Zimmerman: 17211: Completion/Unix/Command/_cvs:
respect $CVSIGNORE.
2002-05-12 Andrej Borsenkow <bor@zsh.org>
2002-05-12 Andrej Borsenkow <bor@zsh.org>
* unposted: Completion/Redhat/Command/_service: fix context
name for tag-order style. For now comment it out because it
@ -1515,7 +1530,7 @@
* 14959: Src/signals.c: more renames for 14951.
2001-06-18 Andrej Borsenkow <bor@zsh.org>
2001-06-18 Andrej Borsenkow <bor@zsh.org>
* unposted: zshconfig.ac: forgot to change
zsh_cv_sys_dynamic_broken -> zsh_cv_shared_environ in one place

View file

@ -0,0 +1,254 @@
#autoload
# This gets two arguments, a separator (which should be only one
# character) and an array. As usual, the array may be given by it's
# name or literal as in `(foo bar baz)' (words separated by spaces in
# parentheses).
# The parts of words from the array that are separated by the
# separator character are then completed independently.
local sep pref npref i tmp2 group expl menu pre suf opre osuf orig cpre
local opts sopts matcher imm
typeset -U tmp1 matches
# Get the options.
zparseopts -D -a sopts \
'J+:=group' 'V+:=group' 'X+:=expl' 'P:=opts' 'F:=opts' \
S: r: R: q 1 2 n f 'M+:=matcher' 'i=imm'
sopts=( "$sopts[@]" "$opts[@]" )
if (( $#matcher )); then
matcher="${matcher[2]}"
else
matcher=
fi
# Get the arguments, first the separator, then the array. The array is
# stored in `tmp1'. Further on the array `matches' will always contain
# those words from the original array that still match everything we have
# tried to match while we walk through the string from the line.
sep="$1"
if [[ "${2[1]}" = '(' ]]; then
tmp1=( ${=2[2,-2]} )
else
tmp1=( "${(@P)2}" )
fi
# In `pre' and `suf' we will hold the prefix and the suffix from the
# line while we walk through them. The original string are used
# temporarily for matching.
pre="$PREFIX"
suf="$SUFFIX"
opre="$PREFIX"
osuf="$SUFFIX"
orig="$PREFIX$SUFFIX"
# Special handling for menu completion?
[[ $compstate[insert] = (*menu|[0-9]*) || -n "$_comp_correct" ||
( $#compstate[pattern_match] -ne 0 &&
"$orig" != "${orig:q}" ) ]] && menu=yes
# In `pref' we collect the unambiguous prefix path.
pref=''
# If the string from the line matches at least one of the strings,
# we use only the matching strings.
compadd -O matches -M "r:|${sep}=* r:|=* $matcher" -a tmp1
(( $#matches )) || matches=( "$tmp1[@]" )
while true; do
# Get the prefix and suffix for matching.
if [[ "$pre" = *${sep}* ]]; then
PREFIX="${pre%%${sep}*}"
SUFFIX=""
else
PREFIX="${pre}"
SUFFIX="${suf%%${sep}*}"
fi
# Check if the component for some of the possible matches is equal
# to the string from the line. If there are such strings, we directly
# use the stuff from the line. This avoids having `foo' complete to
# both `foo' and `foobar'.
if [[ -n "$PREFIX$SUFFIX" || "$pre" = ${sep}* ]]; then
tmp1=( "${(@M)matches:#${PREFIX}${SUFFIX}${sep}*}" )
else
tmp1=()
fi
if (( $#tmp1 )); then
npref="${PREFIX}${SUFFIX}${sep}"
else
# No exact match, see how many strings match what's on the line.
builtin compadd -O tmp1 -M "r:|${sep}=* r:|=* $matcher" - "${(@)${(@)matches%%${sep}*}:#}"
[[ $#tmp1 -eq 0 && -n "$_comp_correct" ]] &&
compadd -O tmp1 -M "r:|${sep}=* r:|=* $matcher" - "${(@)${(@)matches%%${sep}*}:#}"
if [[ $#tmp1 -eq 1 ]]; then
# Only one match. If there are still separators from the line
# we just accept this component. Otherwise we insert what we
# have collected, probably giving it a separator character
# as a suffix.
if [[ "$pre$suf" = *${sep}* ]]; then
npref="${tmp1[1]}${sep}"
else
matches=( "${(@M)matches:#${tmp1[1]}*}" )
PREFIX="${cpre}${pre}"
SUFFIX="$suf"
if [[ $#imm -ne 0 && $#matches -eq 1 ]] ||
zstyle -t ":completion:${curcontext}:" expand suffix; then
compadd "$group[@]" "$expl[@]" "$sopts[@]" \
-M "r:|${sep}=* r:|=* $matcher" - $pref$matches
else
if (( $matches[(I)${tmp1[1]}${sep}*] )); then
compadd "$group[@]" "$expl[@]" -p "$pref" -r "$sep" -S "$sep" "$opts[@]" \
-M "r:|${sep}=* r:|=* $matcher" - "$tmp1[1]"
else
compadd "$group[@]" "$expl[@]" -p "$pref" "$sopts[@]" \
-M "r:|${sep}=* r:|=* $matcher" - "$tmp1[1]"
fi
fi
return
fi
elif (( $#tmp1 )); then
local ret=1
# More than one match. First we get all strings that match the
# rest from the line.
PREFIX="$pre"
SUFFIX="$suf"
compadd -O matches -M "r:|${sep}=* r:|=* $matcher" -a matches
if [[ "$pre" = *${sep}* ]]; then
PREFIX="${cpre}${pre%%${sep}*}"
SUFFIX="${sep}${pre#*${sep}}${suf}"
else
PREFIX="${cpre}${pre}"
SUFFIX="$suf"
fi
matches=( "${(@M)matches:#(${(j:|:)~tmp1})*}" )
if ! zstyle -t ":completion:${curcontext}:" expand suffix ||
[[ -n "$menu" || -z "$compstate[insert]" ]]; then
# With menu completion we add only the ambiguous component with
# the prefix collected and a separator for the matches that
# have more components.
tmp2="$pre$suf"
if [[ "$tmp2" = *${sep}* ]]; then
tmp2=(-s "${sep}${tmp2#*${sep}}")
else
tmp2=()
fi
compadd "$group[@]" "$expl[@]" -r "$sep" -S "$sep" "$opts[@]" \
-p "$pref" "$tmp2[@]" -M "r:|${sep}=* r:|=* $matcher" - \
"${(@)${(@)${(@M)matches:#*${sep}}%%${sep}*}:#}" && ret=0
(( $matches[(I)${sep}*] )) &&
compadd "$group[@]" "$expl[@]" -S '' "$opts[@]" \
-p "$pref" \
-M "r:|${sep}=* r:|=* $matcher" - "$sep" && ret=0
compadd "$group[@]" "$expl[@]" -r "$sep" -S "$sep" "$opts[@]" \
-p "$pref" "$tmp2[@]" -M "r:|${sep}=* r:|=* $matcher" - \
"${(@)${(@)${(@M)matches:#*?${sep}?*}%%${sep}*}:#}" && ret=0
compadd "$group[@]" "$expl[@]" -S '' "$opts[@]" -p "$pref" "$tmp2[@]" \
-M "r:|${sep}=* r:|=* $matcher" - \
"${(@)matches:#*${sep}*}" && ret=0
else
# With normal completion we add all matches one-by-one with
# the unmatched part as a suffix. This will insert the longest
# unambiguous string for all matching strings.
compadd "$group[@]" "$expl[@]" "$opts[@]" \
-p "$pref" -s "${i#*${sep}}" \
-M "r:|${sep}=* r:|=* $matcher" - \
"${(@)${(@)${(@M)matches:#*${sep}*}%%${sep}*}:#}" && ret=0
compadd "$group[@]" "$expl[@]" -S '' "$opts[@]" -p "$pref" \
-M "r:|${sep}=* r:|=* $matcher" - \
"${(@)matches:#*${sep}*}" && ret=0
fi
return ret
else
# We are here if no string matched what's on the line. In this
# case we insert the expanded prefix we collected if it differs
# from the original string from the line.
{ ! zstyle -t ":completion:${curcontext}:" expand prefix ||
[[ "$orig" = "$pref$pre$suf" ]] } && return 1
PREFIX="${cpre}${pre}"
SUFFIX="$suf"
if [[ -n "$suf" ]]; then
compadd "$group[@]" "$expl[@]" -s "$suf" "$sopts[@]" \
-M "r:|${sep}=* r:|=* $matcher" - "$pref$pre"
else
compadd "$group[@]" "$expl[@]" -S '' "$opts[@]" \
-M "r:|${sep}=* r:|=* $matcher" - "$pref$pre"
fi
return
fi
fi
# We just accepted and/or expanded a component from the line. We
# remove it from the matches (using only those that have a least
# the skipped string) and ad it the `pref'.
matches=( "${(@)${(@)${(@M)matches:#${npref}*}#*${sep}}:#}" )
pref="$pref$npref"
# Now we set `pre' and `suf' to their new values.
if [[ "$pre" = *${sep}* ]]; then
cpre="${cpre}${pre%%${sep}*}${sep}"
pre="${pre#*${sep}}"
elif [[ "$suf" = *${sep}* ]]; then
cpre="${cpre}${pre}${suf%%${sep}*}${sep}"
pre="${suf#*${sep}}"
suf=""
else
# The string from the line is fully handled. If we collected an
# unambiguous prefix and that differs from the original string,
# we insert it.
PREFIX="${opre}${osuf}"
SUFFIX=""
if [[ -n "$pref" && "$orig" != "$pref" ]]; then
if [[ "$pref" = *${sep}*${sep} ]]; then
compadd "$group[@]" "$expl[@]" "$opts[@]" \
-p "${pref%${sep}*${sep}}${sep}" -S "$sep" \
-M "r:|${sep}=* r:|=* $matcher" - "${${pref%${sep}}##*${sep}}"
elif [[ "$pref" = *${sep}* ]]; then
compadd "$group[@]" "$expl[@]" -S '' "$opts[@]" \
-p "${pref%${sep}*}${sep}" \
-M "r:|${sep}=* r:|=* $matcher" - "${pref##*${sep}}"
else
compadd "$group[@]" "$expl[@]" -S '' "$opts[@]" \
-M "r:|${sep}=* r:|=* $matcher" - "$pref"
fi
fi
return
fi
done

View file

@ -0,0 +1,171 @@
#compdef tar gtar star
# Tar completion. Features:
# - Tries to collect tar commands from second position, single letter
# option, and long options.
# - `tar' can be called anything, will use the correct name
# - Uses the function `_tar_archive' to complete archive files.
# - Tries to find out if compressed archives should be used.
# - Completes files inside archive. This is supposed to look pretty
# much as if the files are in an ordinary directory hierarchy.
# Handles extraction from compressed archives (GNU tar).
# - Anywhere -- appears, gets a list of long options to complete from
# tar itself (GNU tar)
# - Things like --directory=... are also completed correctly.
local _tar_cmd tf tmp tmpb del index
# First we collect in `_tar_cmd' single letter options describing what
# should be done with the archive and if it is compressed. This
# collected from options arguments that start with only one hyphen,
# from some of the possible long options, and from the second word if
# that does not start with a hyphen.
tmp=("${(@M)words:#-[^-]*}")
_tar_cmd="${(j::)tmp#-}"
(( $words[(I)--(un|)gzip] )) && _tar_cmd="z$_tar_cmd"
(( $words[(I)--(un|)compress] )) && _tar_cmd="Z$_tar_cmd"
(( $words[(I)--list] )) && _tar_cmd="t$_tar_cmd"
(( $words[(I)--(extract|get)] )) && _tar_cmd="x$_tar_cmd"
(( $words[(I)--create] )) && _tar_cmd="c$_tar_cmd"
# Other ways of finding out what we're doing: first
# look in the first argument if it's not an option
if [[ "$words[2]" = *[txcdruA]*~-* ]]; then
_tar_cmd="$words[2]$_tar_cmd"
elif [[ $_tar_cmd != *[txcdruA]* && CURRENT -gt 2 ]]; then
# look for more obscure long options: these aren't all handled.
(( $words[(I)--(diff|compare)] )) && _tar_cmd="d$_tar_cmd"
(( $words[(I)--append] )) && _tar_cmd="r$_tar_cmd"
(( $words[(I)--update] )) && _tar_cmd="u$_tar_cmd"
(( $words[(I)--(con|)catenate] )) && _tar_cmd="A$_tar_cmd"
(( $words[(I)--delete] )) && del=1
fi
# Next, we try to find the archive name and store it in `tf'. The name
# is searched after a `--file=' long option, in the third word if the
# second one didn't start with a hyphen but contained a `f', and after
# an option argument starting with only one hyphen and containing a `f'.
# unless that option argument also contains a `C'.
tmp="$words[(I)--file=*]"
tmpb="$words[(I)-*Cf*~--*]"
if (( tmp )); then
tf=${~words[tmp][8,-1]}
_tar_cmd="f$_tar_cmd"
elif [[ "$words[2]" != -* && "$words[2]" = *f* ]]; then
tf=${~words[3]}
_tar_cmd="f$_tar_cmd"
elif (( tmpb )); then
tf=${~words[tmpb+2]}
wdir=${~words[tmpb+1]}
_tar_cmd="Cf$_tar_cmd"
else
tmp="${words[(I)-*f*~--*]}"
if (( tmp )); then
tf=${~words[tmp+1]}
_tar_cmd="f$_tar_cmd"
fi
fi
# See if we should use a path prefix. We have to use eval as the dir can
# be any unevaluated thing which appears on the command line, including a
# parameter.
# This isn't used right now.
tmp=${words[(r)--dir[a-z]#=*]}
if [[ -n $tmp ]]; then
eval "wdir=(${tmp#*=})"
fi
# Now we complete...
if [[ "$PREFIX" = --* ]]; then
# ...long options after `--'.
_arguments -- '--owner*:user:_users' \
'*=(PROG|COMMAND)*:program:_command_names -e' \
'*=ARCHIVE*:archive: _tar_archive' \
'*=NAME*:file:_files' \
'*=DIR*:directory:_files -/' \
'*=CONTROL*::version control:(t numbered nil existing never simple)'
elif [[ ( CURRENT -gt 2 && "$words[CURRENT-1]" = -[^C]#f* &&
"$words[CURRENT-1]" != --* ) ||
( CURRENT -eq 3 && "$words[2]" = [^C]#f* && "$words[2]" != -* ) ||
( CURRENT -gt 2 && "$words[CURRENT-2]" = -*C*f* &&
"$words[CURRENT-2]" != --* && "$words[CURRENT-1]" != --* ) ||
( CURRENT -eq 4 && "$words[2]" = *C*f* && "$words[2]" != -* ) ]]; then
# ...archive files if we think they are wanted here.
_tar_archive
elif [[ ( CURRENT -gt 2 && "$words[CURRENT-1]" = -[^f]#C*) ||
( CURRENT -eq 3 && "$words[2]" = [^f]#C* ) ]]; then
# a directory for -C
_directories
elif [[ ( "$_tar_cmd" = *[xt]* || -n $del ) && -n "$tf" ]]; then
# ...and files from the archive if we found an archive name and tar
# commands. We run `tar t...' on the file, keeping the list of
# filenames cached, plus the name of the tarfile so we know if it
# changes. We skip this test if the alleged archive is not a file.
local largs=-tf expl
if [[ $_tar_cmd = *z* ]]; then
largs=-tzf
elif [[ $_tar_cmd = *j* ]]; then
largs=-tjf
elif [[ $_tar_cmd = *y* ]]; then
largs=-tyf
elif [[ $_tar_cmd = *Z* ]]; then
largs=-tZf
elif [[ $_tar_cmd = *I* ]]; then
largs=-tIf
else
# Some random compression program
tmp="${words[(r)--use-comp*]}"
[[ -n $tmp ]] && largs=($tmp -tf)
fi
if [[ $tf != $_tar_cache_name && -f $tf ]]; then
_tar_cache_list=("${(@f)$($words[1] $largs $tf)}")
_tar_cache_name=$tf
fi
_wanted files expl 'file from archive' _multi_parts / _tar_cache_list
elif (( CURRENT == 2 )); then
_values -s '' 'tar function' \
'(c t u x)A[append to an archive]' \
'(A t u x)c[create a new archive]' \
'(A c u x)t[list archive contents]' \
'(A c t x)u[update archive]' \
'(A c t u)x[extract files from an archive]' \
'v[verbose output]' \
'f[specify archive file or device]'
else
if ! (( index=$words[(I)-*C*] )); then
if [[ $words[2] = [^f]#C* ]]; then
index=1
elif [[ $words[2] = *f*C* ]]; then
index=2
fi
fi
if (( index )); then
index="$~words[index+1]"
[[ $index = (.|..|)/* ]] || index=~+/$index
_files -W $index
else
_files
fi
fi

View file

@ -0,0 +1,26 @@
#autoload
# This is used to generate filenames usable as a tar archive. This may
# get one argument, a collection of tar option characters that may be
# used to find out what kind of filename is needed. If no argument is
# given but the parameter `_tar_cmd' is set, that is used.
# If your version of `tar' supports this you may want to complete
# things like `host:file' or `user@host:file' here.
local expl
[[ $# -eq 0 && $+_tar_cmd -ne 0 ]] && set "$_tar_cmd"
_description files expl 'archive file'
if [[ "$1" = *[urtx]* ]]; then
if [[ "$1" = *[zZ]* ]]; then
_files "$expl[@]" -g '*.((tar|TAR).(gz|GZ|Z)|tgz)'
elif [[ "$1" = *[Ijy]* ]]; then
_files "$expl[@]" -g '*.(tar|TAR).bz2'
else
_files "$expl[@]" -g '*.(tar|TAR)'
fi
else
_files "$expl[@]"
fi

View file

@ -181,9 +181,9 @@ static struct globdata curglobdata;
(N).gd_pathpos = pathpos; \
(N).gd_pathbuf = pathbuf; \
(N).gd_pathbufsz = 0; \
(N).gd_pathbuf = NULL; \
(N).gd_glob_pre = glob_pre; \
(N).gd_glob_suf = glob_suf; \
pathbuf = NULL; \
} while (0)
#define restore_globstate(N) \
@ -234,7 +234,7 @@ addpath(char *s)
}
/* stat the filename s appended to pathbuf. l should be true for lstat, *
* false for stat. If st is NULL, the file is only chechked for existance. *
* false for stat. If st is NULL, the file is only checked for existance. *
* s == "" is treated as s == ".". This is necessary since on most systems *
* foo/ can be used to reference a non-directory foo. Returns nonzero if *
* the file does not exists. */
@ -1421,6 +1421,7 @@ zglob(LinkList list, LinkNode np, int nountok)
} else if (isset(NOMATCH)) {
zerr("no matches found: %s", ostr, 0);
free(matchbuf);
restore_globstate(saved);
return;
} else {
/* treat as an ordinary string */