1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-06-21 10:28:05 +02:00

zsh-3.1.6-test-2

This commit is contained in:
Tanaka Akira 1999-07-19 14:26:14 +00:00
parent 1f6786ef7a
commit d6d4a3abfc
50 changed files with 821 additions and 295 deletions

141
ChangeLog
View file

@ -1,5 +1,146 @@
1999-07-19 Peter Stephenson <pws@ibmth.df.unipi.it>
* pws: version 3.1.6-test-2
* pws: 7192: Src/glob.c: bug with null in pattern if at end of
test string (matched as if a real character).
1999-07-18 Peter Stephenson <pws@ibmth.df.unipi.it>
* pws: 7185: Src/glob.c: don't use strcoll() for character
ranges [...] because it can have side effects.
* pws: 7184: Src/lex.c: histactive didn't get get zeroed before
non-interactive history use, hence interactive lines with
remhist() were junked more than once.
* Wayne: 7181: Doc/Zsh/options.y, Doc/Zsh/params.yo: history docs.
* Wayne: 7180: Src/Zle/complist.c, Src/utils.c: warnings.
1999-07-16 Peter Stephenson <pws@ibmth.df.unipi.it>
* pws: 7172: Doc/Zsh/options.yo, Src/builtin.c, Src/exec.c,
Src/options.c, Src/utils.c, Src/zsh.h: minor bugs with
7164 fixed; CHASE_DOTS resolves ..'s to physical path;
CHASE_LINKS doesn't do logical path rationalization;
xsymlink() and xsymlinks() simplified and option-dependence
removed.
* Sven: 7171: Src/builtin.c: alternate form of Digital/gcc
bug workaround.
1999-07-15 Peter Stephenson <pws@ibmth.df.unipi.it>
* pws: 7164: Src/builtin.c, Src/exec.c: AUTOCD now allows
paths with symlinks (as real cd always did); simplify code
for testing for existing directory on foo/.. before removing
foo/..; as a side effect, relative cd's from directory which
has been deleted don't work.
* Sven: 7161: Src/Zle/comp.h, Src/Zle/complist.c,
Src/Zle/zle_tricky.c, Completion/Base/_brace_parameter:
be more careful with quote-prefix/suffix and path-prefix/suffix
especially with accept-and-menu-complete.
* pws: 7155: Functions/Zftp/zfgoto, Functions/Zftp/zfinit:
zfgoto can cd without needing to re-login; zfinit uses
zmodload -e to check for zftp.
* Sven: 7154: Src/Zle/complist.c, Src/Zle/zle_refresh.c,
Src/Zle/zle_tricky.c, Doc/Zsh/mod_complist.yo: don't
list too many times on ambiguous completion; don't do
menu-selection if no alwayslastprompt behaviour.
1999-07-14 Peter Stephenson <pws@ibmth.df.unipi.it>
* pws: 7148: INSTALL: User subdirectory
* Thomas Köhler: 7146: Completion/User/_make: didn't work.
* pws: 7145: Completion/User/_sh: use compset -q for completing
after -c option
* Sven: 7143: Src/Zle/complist.c, Src/Zle/zle_tricky.c:
listing got confused with only hidden matches.
* Sven: 7141: Completion/Core/_path_files: if there are
no completions in a valid directory when we have a path ending
in /, use the directory as a completion, to avoid
correction/approximation of the existing directory.
* pws: 7139: Src/builtin.c: not particularly pleasant fix
to problem that `cd nonexistent/..' silently did nothing, while
making `cd ..' work even if current directory has gone.
* Sven: 7138: Completion/User/_hosts, Completion/User/_x_options:
_hosts passes arguments as options to compadd.
* Oliver: 7136: Completion/User/_rlogin,
Completion/User/_x_options: use _hosts.
* Sven: 7135: Src/Zle/zle_tricky.c, Completion/Core/_path_files:
change quoting of files again.
* Sven: 7133: Doc/Zsh/expn.yo, Doc/Zsh/mod_complist.yo:
ZLS_COLOURS not required for complist to work.
* pws: 7127: configure.in: help now shows --disable-dynamic
and --disable-lfs.
* Sven: 7126: Src/Zle/comp.h, Src/Zle/comp1.c, Src/Zle/compctl.c,
Src/Zle/zle_tricky.c, Doc/Zsh/compwid.yo,
Functions/Zle/incremental-complete-word: compstate key
normal_nmatches; more i-c-w prompt escapes
* Sven: 7123: Src/Zle/zle_tricky.c: clear list on expansion
failure.
1999-07-13 Peter Stephenson <pws@ibmth.df.unipi.it>
* pws: 7119: Src/Zle/zle_tricky.c: status from expansion
functions.
* Sven: 7116: Doc/Zsh/compwid.yo, Doc/Zsh/expn.yo: minor
changes.
* pws: 7114: Src/parse.c, Src/utils.c: line numbers again:
flushing line in a script made lineno appear one too large;
introduce zwarn() function.
* Sven/pws: 7112: Src/Zle/zle_params.c, Doc/Zsh/zle.yo: change
array keys to scalar KEYS, works more like read -k;
documentation.
* Sven: 7110: Src/Modules/zftp.c, Doc/Zsh/compsys.yo,
Etc/MACHINES: signed char warnings in zftp; document
_long_options options; Digital UNIX problem.
* Sven: 2432: Src/builtin.c: workaround Digital UNIX 4.0 +
gcc 2.8.1 bug.
* Sven: zsh-users/2430: Etc/NEWS: mention chmod-like mode glob
qualifier.
* Sven: 7108: Misc/job-control-tests: more tests
* Bart: 7107: configure.in: too many x's in lfs handling.
* Sven: 7106: Functions/Zle/incremental-complete-word: prompting
changes.
* pws: unposted: update .distfiles and .cvsignore: _sh, _su
zshcompsys.yo, zshcompwid.yo, zshzftp.yo, zshcompsys.1,
zshcompwid.1, zshzftp.1 were missing from the distribution.
* Sven: 7105: Src/Zle/Zle_tricky.c: restore the command line
in more places.
1999-07-12 Peter Stephenson <pws@ibmth.df.unipi.it> 1999-07-12 Peter Stephenson <pws@ibmth.df.unipi.it>
* Sven: 7103: Src/Zle/zle_tricky.c, Doc/Zsh/compwid.yo: update
CURRENT with compset -q; modify test for quoted delimiters.
* pws: version 3.1.6-test-1 * pws: version 3.1.6-test-1
* Sven: 7099: Completion/Core/_main_complete, Doc/Zsh/compsys.yo: * Sven: 7099: Completion/Core/_main_complete, Doc/Zsh/compsys.yo:

1
Completion/.cvsignore Normal file
View file

@ -0,0 +1 @@
Makefile

View file

@ -1,3 +1,3 @@
DISTFILES_SRC=' DISTFILES_SRC='
.distfiles README Makefile.in .cvsignore .distfiles README Makefile.in
' '

View file

@ -18,4 +18,4 @@ q=${(M)lp%%\"#}
[[ n -gt 0 ]] && suf='' [[ n -gt 0 ]] && suf=''
_parameters -s "${q[1,-n-1]}" -S "$suf" -r '-:?#%+=[/' _parameters -Qs "${q[1,-n-1]}" -S "$suf" -r '-:?#%+=[/'

View file

@ -244,7 +244,7 @@ for prepath in "$prepaths[@]"; do
if [[ "$tmp2[1]" = */* ]]; then if [[ "$tmp2[1]" = */* ]]; then
tmp2=( "${(@)tmp2#${prepath}${realpath}}" ) tmp2=( "${(@)tmp2#${prepath}${realpath}}" )
if [[ "$tmp2[1]" = */* ]]; then if [[ "$tmp2[1]" = */* ]]; then
exppaths=( "$exppaths[@]" ${^tmp2:h}/${tpre}${tsuf} ) exppaths=( "$exppaths[@]" ${^tmp2:h:q}/${tpre}${tsuf} )
else else
exppaths=( "$exppaths[@]" ${tpre}${tsuf} ) exppaths=( "$exppaths[@]" ${tpre}${tsuf} )
fi fi
@ -252,6 +252,18 @@ for prepath in "$prepaths[@]"; do
continue 2 continue 2
fi fi
elif (( ! $#tmp1 )); then elif (( ! $#tmp1 )); then
# A little extra hack: if we were completing `foo/<TAB>' and `foo'
# contains no files, this will normally produce no matches and other
# completers might think that's it's their time now. But if the next
# completer is _correct or something like that, this will result in
# an attempt to correct a valid directory name. So we just add the
# original string in such a case so that the command line doesn't
# change but other completers still think there are matches.
if [[ -z "$tpre$tsuf" && "$pre" = */ && -z "$suf" ]]; then
compadd -nQS '' - "$linepath$donepath$orig"
tmp4=-
fi
continue 2 continue 2
fi fi
@ -310,33 +322,33 @@ for prepath in "$prepaths[@]"; do
if [[ -n $menu ]]; then if [[ -n $menu ]]; then
[[ -n "$compconfig[path_cursor]" ]] && compstate[to_end]='' [[ -n "$compconfig[path_cursor]" ]] && compstate[to_end]=''
if [[ "$tmp3" = */* ]]; then if [[ "$tmp3" = */* ]]; then
compadd -Uf -p "$linepath$testpath" -s "/${tmp3#*/}" \ compadd -QUf -p "$linepath${testpath:q}" -s "/${tmp3#*/}" \
-W "$prepath$realpath$testpath" "$ignore[@]" \ -W "$prepath$realpath$testpath" "$ignore[@]" \
"$addpfx[@]" "$addsfx[@]" "$remsfx[@]" -M 'r:|/=* r:|=*' \ "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" -M 'r:|/=* r:|=*' \
"$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
- "${(@)tmp1%%/*}" - "${(@)${(@)tmp1%%/*}:q}"
else else
compadd -Uf -p "$linepath$testpath" \ compadd -QUf -p "$linepath${testpath:q}" \
-W "$prepath$realpath$testpath" "$ignore[@]" \ -W "$prepath$realpath$testpath" "$ignore[@]" \
"$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \ "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
"$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
- "$tmp1[@]" - "${(@)tmp1:q}"
fi fi
else else
if [[ "$tmp3" = */* ]]; then if [[ "$tmp3" = */* ]]; then
for i in "$tmp1[@]"; do for i in "$tmp1[@]"; do
compadd -Uf -p "$linepath$testpath" -s "/${i#*/}" \ compadd -QUf -p "$linepath${testpath:q}" -s "/${${i#*/}:q}" \
-W "$prepath$realpath$testpath" "$ignore[@]" \ -W "$prepath$realpath$testpath" "$ignore[@]" \
"$addpfx[@]" "$addsfx[@]" "$remsfx[@]" -M 'r:|/=* r:|=*' \ "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" -M 'r:|/=* r:|=*' \
"$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
- "${i%%/*}" - "${${i%%/*}:q}"
done done
else else
compadd -Uf -p "$linepath$testpath" \ compadd -QUf -p "$linepath${testpath:q}" \
-W "$prepath$realpath$testpath" "$ignore[@]" \ -W "$prepath$realpath$testpath" "$ignore[@]" \
"$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \ "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
"$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
- "$tmp1[@]" - "${(@)tmp1:q}"
fi fi
fi fi
tmp4=- tmp4=-
@ -361,11 +373,11 @@ for prepath in "$prepaths[@]"; do
done done
if [[ -z "$tmp4" ]]; then if [[ -z "$tmp4" ]]; then
compadd -Uf -p "$linepath$testpath" \ compadd -QUf -p "$linepath${testpath:q}" \
-W "$prepath$realpath$testpath" "$ignore[@]" \ -W "$prepath$realpath$testpath" "$ignore[@]" \
"$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \ "$addpfx[@]" "$addsfx[@]" "$remsfx[@]" \
"$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
- "$tmp1[@]" - "${(@)tmp1:q}"
fi fi
done done
@ -376,9 +388,9 @@ done
exppaths=( "${(@)exppaths:#$orig}" ) exppaths=( "${(@)exppaths:#$orig}" )
if [[ -n "$compconfig[path_expand]" && if [[ -n "$compconfig[path_expand]" &&
$#exppaths -eq 1 && nm -eq compstate[nmatches] ]]; then $#exppaths -gt 0 && nm -eq compstate[nmatches] ]]; then
compadd -QU -S '' "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \ compadd -QU -S '' "$group[@]" "$expl[@]" -i "$IPREFIX" -I "$ISUFFIX" \
-M 'r:|/=* r:|=*' -p "$linepath" - "${(@)exppaths}" -M 'r:|/=* r:|=*' -p "$linepath" - "$exppaths[@]"
fi fi
[[ nm -ne compstate[nmatches] ]] [[ nm -ne compstate[nmatches] ]]

View file

@ -1,6 +1,8 @@
DISTFILES_SRC=' DISTFILES_SRC='
.distfiles .distfiles
_a2ps _chown _compress _configure _dd _dvi _find _groups _gunzip _gzip _a2ps _chown _compress _configure _dd _dvi _find
_hosts _use_lo _make _man _mh _pdf _ps _rcs _rlogin _strip _stty _gdb _groups _gunzip _gzip
_hosts _use_lo _make _man _mh _pdf _ps
_rcs _rlogin _sh _strip _stty _su
_tar _tar_archive _tex _uncompress _x_options _xfig _tar _tar_archive _tex _uncompress _x_options _xfig
' '

50
Completion/User/_gdb Normal file
View file

@ -0,0 +1,50 @@
#compdef gdb
# This uses the configuration keys `ps_args' and `ps_listargs'
# described in the `_wait' function.
local cur="$words[CURRENT]" prev w list ret=1
_long_options -t '*=(CORE|SYM)FILE' '_files' \
'*=EXECFILE' '_files *(*)' \
'*=TTY' 'compadd /dev/tty*' && return 0
if compset -P '-(cd|directory)='; then
_files -/
elif compset -P '-tty='; then
compadd - /dev/tty*
elif compset -P '-(exec|se)='; then
_files -/g '*(*)'
elif compset -P '-(symbols|core|command)='; then
_files
elif compset -P -; then
compadd -QS '' - symbols\= exec\= se\= core\= command\= directory\= \
cd\= tty\=
compadd - help h s e c x d nx n quiet q batch fullname f b
else
prev="$words[CURRENT-1]"
case "$prev" in
(-d) _files -/ && return 0 ;;
(-e) _files -/g '*(*)' && return 0 ;;
(-[csx]) _files && return 0 ;;
(-b) compadd -V baud 0 50 75 110 134 150 200 300 600 1200 1800 2400 4800 \
9600 19200 38400 57600 115200 230400 && return 0 ;;
esac
w=( "${(@)words[2,-1]}" )
while [[ "$w[1]" = -* ]]; do
[[ "$w[1]" = -[decsxb] ]] && shift 1 w
shift 1 w
done
if [[ $#w -gt 1 ]]; then
_files && ret=0
list=("${(F)${(@Mr:COLUMNS-1:)${(f)$(ps ${compconfig[ps_listargs]:-$compconfig[ps_args]} 2>/dev/null)}[2,-1]:#[ ]#${PREFIX}[0-9]#${SUFFIX}[ ]*${w[1]:t}}}
")
compadd -y list - ${${${(M)${(f)"$(ps $compconfig[ps_args] 2>/dev/null)"}:#*${w[1]:t}*}## #}%% *} && ret=0
return ret
else
_files -/g '*(*)'
fi
fi

View file

@ -2,4 +2,4 @@
: ${(A)hosts:=${(s: :)${(ps:\t:)${${(f)"$(</etc/hosts)"}%%\#*}##[:blank:]#[^[:blank:]]#}}} : ${(A)hosts:=${(s: :)${(ps:\t:)${${(f)"$(</etc/hosts)"}%%\#*}##[:blank:]#[^[:blank:]]#}}}
compgen -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' -k hosts compadd -M 'm:{a-zA-Z}={A-Za-z} r:|.=* r:|=*' "$@" - "$hosts[@]"

View file

@ -19,6 +19,6 @@ else
fi fi
[[ -n "$file" ]] && [[ -n "$file" ]] &&
compadd - $(awk '/^[a-zA-Z0-9][^/ ]+:/ {print $1}' FS=: $file) && ret=0 compadd - $(awk '/^[a-zA-Z0-9][^\/ ]+:/ {print $1}' FS=: $file) && ret=0
(( ret )) && _files (( ret )) && _files
fi fi

View file

@ -1,7 +1,7 @@
#compdef rlogin rsh ssh #compdef rlogin rsh ssh
if [[ CURRENT -eq 2 ]]; then if [[ CURRENT -eq 2 ]]; then
compgen -k hosts _hosts
elif [[ CURRENT -eq 3 ]]; then elif [[ CURRENT -eq 3 ]]; then
compadd - -l compadd - -l
else else

8
Completion/User/_sh Normal file
View file

@ -0,0 +1,8 @@
#compdef sh ksh bash zsh csh tcsh rc
if (( CURRENT == ${words[(i)-c]} + 1 )); then
compset -q
_normal
else
_default
fi

22
Completion/User/_su Normal file
View file

@ -0,0 +1,22 @@
#compdef su
local shell comp name usr base
[[ $words[2] != - ]]
(( base=$?+2 ))
if [[ CURRENT -eq base ]]; then
compgen -u && return
usr=root
elif [[ CURRENT -ge base+1 ]]; then
usr=$words[base]
else
return
fi
shell=${"$(egrep "^$usr:" </etc/passwd)"##*:}
compset -n $base
for name in $shell $shell:t -default-; do
comp="$_comps[$name]"
[[ ! -z "$comp" ]] && "$comp" && return
done

View file

@ -3,7 +3,8 @@
# A simple pattern completion, just as an example. # A simple pattern completion, just as an example.
if [ "$words[CURRENT-1]" = "-display" ]; then if [ "$words[CURRENT-1]" = "-display" ]; then
compgen -k hosts -S':0' _compskip=''
_hosts -S :0
else else
compadd -J options - -display -name -xrm compadd -P- -J options - display name xrm
fi fi

View file

@ -27,5 +27,5 @@
# This must also serve as a shell script, so do not add spaces around the # This must also serve as a shell script, so do not add spaces around the
# `=' signs. # `=' signs.
VERSION=3.1.6-test-1 VERSION=3.1.6-test-2
VERSION_DATE='July 9, 1999' VERSION_DATE='July 19, 1999'

View file

@ -2,11 +2,13 @@ DISTFILES_SRC='
.cvsignore .distfiles Makefile.in .cvsignore .distfiles Makefile.in
META-FAQ.yo intro.ms META-FAQ.yo intro.ms
version.yo zmacros.yo zman.yo ztexi.yo version.yo zmacros.yo zman.yo ztexi.yo
zsh.yo zshbuiltins.yo zshcompctl.yo zshexpn.yo zshmisc.yo zsh.yo zshbuiltins.yo zshcompctl.yo zshcompsys.yo zshcompwid.yo
zshmodules.yo zshoptions.yo zshparam.yo zshzle.yo zshexpn.yo zshmisc.yo zshmodules.yo zshoptions.yo zshparam.yo
zshzftpsys.yo zshzle.yo
zsh.texi zsh.texi
zsh.1 zshbuiltins.1 zshcompctl.1 zshexpn.1 zshmisc.1 zshmodules.1 zsh.1 zshbuiltins.1 zshcompctl.1 zshcompsys.1 zshcompwid.1 zshexpn.1
zshoptions.1 zshparam.1 zshzle.1 zshall.1 zshmisc.1 zshmodules.1 zshoptions.1 zshparam.1 zshzle.1 zshall.1
zshzftpsys.1
' '
DISTFILES_DOC=' DISTFILES_DOC='

View file

@ -31,7 +31,7 @@ next section.
Usually, tt(compinstall) will insert code into tt(.zshrc), although if Usually, tt(compinstall) will insert code into tt(.zshrc), although if
that is not writable it will save it in another file and tell you that that is not writable it will save it in another file and tell you that
file's locations. Note that it is up to you to make sure that the lines file's location. Note that it is up to you to make sure that the lines
added to tt(.zshrc) are actually run; you may, for example, need to move added to tt(.zshrc) are actually run; you may, for example, need to move
them to an earlier place in the file if tt(.zshrc) usually returns early. them to an earlier place in the file if tt(.zshrc) usually returns early.
So long as you keep them all together (including the comment lines at the So long as you keep them all together (including the comment lines at the
@ -92,7 +92,7 @@ will only need to run this yourself if you change the configuration
(e.g. using tt(compdef)) and then want to dump the new one. The name of (e.g. using tt(compdef)) and then want to dump the new one. The name of
the old dumped file will be remembered for this purpose. the old dumped file will be remembered for this purpose.
If the parameter tt(_compdir) is set, tt(compinit) uses it has a directory If the parameter tt(_compdir) is set, tt(compinit) uses it as a directory
where completion functions can be found; this is only necessary if they are where completion functions can be found; this is only necessary if they are
not already in the function search path. not already in the function search path.
@ -489,7 +489,7 @@ non-empty string it should be an expression usable inside a `tt($((...)))'
arithmetical expression. In this case, expansion of substitutions will arithmetical expression. In this case, expansion of substitutions will
be done if the expression evaluates to `tt(1)'. For example, with be done if the expression evaluates to `tt(1)'. For example, with
example(compconf expand_substitute='NUMERIC != 1') example(compconf expand_substitute='${NUMERIC:-1} != 1')
substitution will be performed only if given an explicit numeric substitution will be performed only if given an explicit numeric
argument other than `tt(1)', as by typing `tt(ESC 2 TAB)'. argument other than `tt(1)', as by typing `tt(ESC 2 TAB)'.
@ -720,8 +720,8 @@ is used.
) )
item(tt(_parameters))( item(tt(_parameters))(
This should be used to complete parameter names if you need some of the This should be used to complete parameter names if you need some of the
extra options of tt(compadd). It first tries to complete only non-local extra options of tt(compadd). All arguments are passed unchanged to
parameters. All arguments are passed unchanged to the tt(compadd) builtin. the tt(compadd) builtin.
) )
item(tt(_options))( item(tt(_options))(
This can be used to complete option names. The difference to the This can be used to complete option names. The difference to the
@ -780,9 +780,19 @@ descriptions that contain `tt(=DIR)' or `tt(=PATH)'. These builtin
patterns can be overridden by patterns given as arguments, however. patterns can be overridden by patterns given as arguments, however.
This function also accepts the `tt(-X)', `tt(-J)', and `tt(-V)' This function also accepts the `tt(-X)', `tt(-J)', and `tt(-V)'
options which are passed unchanged to `tt(compadd)'. Finally, it options which are passed unchanged to `tt(compadd)'. If the
accepts the option `tt(-t)'; if this is given, completion is only done option `tt(-t)' is given, completion is only done on words starting
on words starting with two hyphens. with two hyphens. The option `tt(-i) var(patterns)' can be used to
give patterns for options which should not be completed. The patterns
can be given as the name of an array parameter or as a literal list in
parentheses. E.g. `tt(-i "(--(en|dis)able-FEATURE*)")' will ignore the
options `tt(--enable-FEATURE)' and `tt(--diable-FEATURE)'. Finally,
the option `tt(-s) var(pairs)' can be used to describe options
aliases. Each var(pair) consists of a pattern and a
replacement. E.g. some tt(configure)-scripts describe options only as
`tt(--enable-foo)', but also accept `tt(disable-foo)'. To allow
completion of the second form, one would use
`tt(-s "(#--enable- --disable-)")'.
) )
enditem() enditem()

View file

@ -175,6 +175,12 @@ is unset.
item(tt(nmatches))( item(tt(nmatches))(
The number of matches generated and accepted by the completion code so far. The number of matches generated and accepted by the completion code so far.
) )
item(tt(normal_nmatches))(
Like tt(nmatches), but counts only matches in the normal set. I.e. file
names with one of the suffixes from the tt(fignore) array and matches
put into the alternate set using the tt(-a) option of the tt(compadd)
builtin command (see below) are not counted.
)
item(tt(matcher))( item(tt(matcher))(
When completion is performed with a global match specification as defined When completion is performed with a global match specification as defined
by by
@ -410,7 +416,7 @@ item(tt(-I) var(ignored-suffix))(
Like tt(-i), but gives an ignored suffix. Like tt(-i), but gives an ignored suffix.
) )
item(tt(-y) var(array))( item(tt(-y) var(array))(
This gives a number of string to display instead of the matches. This This gives a number of strings to display instead of the matches. This
is like the tt(-y) option of the tt(compctl) builtin command but the is like the tt(-y) option of the tt(compctl) builtin command but the
var(array) argument may only be the name of an array parameter or a var(array) argument may only be the name of an array parameter or a
literal array in parentheses containing the strings to display. literal array in parentheses containing the strings to display.
@ -483,7 +489,7 @@ from the first set are stored. Normally only the matches in the first
set are used, but if this set is empty, the words from the alternate set are used, but if this set is empty, the words from the alternate
set are used. set are used.
The tt(compadd) builtin does not use tt(fignore) parameter and The tt(compadd) builtin does not use the tt(fignore) parameter and
normally stores all words in the first set. With the tt(-a)-flag normally stores all words in the first set. With the tt(-a)-flag
given, however, the given var(words) are stored in the alternate set unless given, however, the given var(words) are stored in the alternate set unless
this flag is overridden by the tt(-F) option. this flag is overridden by the tt(-F) option.
@ -518,7 +524,7 @@ will be done by the completion code. Normally this is used in
functions that do the matching themselves. functions that do the matching themselves.
Note that with tt(compadd) this option does not automatically turn on Note that with tt(compadd) this option does not automatically turn on
menu completion if tt(AUTO_LIST), unlike the corresponding option of menu completion if tt(AUTO_LIST) is set, unlike the corresponding option of
tt(compctl) and tt(compgen) commands. tt(compctl) and tt(compgen) commands.
) )
item(tt(-O) var(array))( item(tt(-O) var(array))(
@ -622,9 +628,9 @@ testing and modification is performed as if it were not given.
item(tt(-q))( item(tt(-q))(
The word The word
currently being completed is split in separate words at the spaces. The currently being completed is split in separate words at the spaces. The
resulting words are stored in the tt(words) array, and tt(PREFIX), resulting words are stored in the tt(words) array, and tt(CURRENT),
tt(SUFFIX), tt(QIPREFIX), and tt(QISUFFIX) are modified to reflect the tt(PREFIX), tt(SUFFIX), tt(QIPREFIX), and tt(QISUFFIX) are modified to
word part that is completed. reflect the word part that is completed.
) )
enditem() enditem()

View file

@ -1192,7 +1192,7 @@ grouping the string as tt([d][cb][a]) and tt([a][bc][d]).
Non-literal parts of the pattern must match exactly, including characters Non-literal parts of the pattern must match exactly, including characters
in character ranges: hence tt(LPAR()#a1)tt(RPAR()???) matches strings of in character ranges: hence tt(LPAR()#a1)tt(RPAR()???) matches strings of
length four, by applying rule 4 to an empty part of the pattern, but not length four, by applying rule 4 to an empty part of the pattern, but not
strings of length three, since all the tt(?) must match. Other characters strings of length two, since all the tt(?) must match. Other characters
which must match exactly are initial dots in filenames (unless the which must match exactly are initial dots in filenames (unless the
tt(GLOB_DOTS) option is set), and all slashes in file names, so that tt(GLOB_DOTS) option is set), and all slashes in file names, so that
tt(a/bc) is two errors from tt(ab/c) (the slash cannot be transposed with tt(a/bc) is two errors from tt(ab/c) (the slash cannot be transposed with
@ -1351,7 +1351,7 @@ bit.
Thus, `tt(*(f70?))' gives the files for which the owner has read, Thus, `tt(*(f70?))' gives the files for which the owner has read,
write, and execute permission, and for which other group members have write, and execute permission, and for which other group members have
no rights, independent of the permissions for other user. The pattern no rights, independent of the permissions for other users. The pattern
`tt(*(f-100))' gives all files for which the owner does not have `tt(*(f-100))' gives all files for which the owner does not have
execute permission, and `tt(*(f:gu+w,o-rx))' gives the files for which execute permission, and `tt(*(f:gu+w,o-rx))' gives the files for which
the owner and the other members of the group have at least write the owner and the other members of the group have at least write
@ -1455,7 +1455,7 @@ returned list. The syntax is the same as for array
subscripts. var(beg) and the optional var(end) may be mathematical subscripts. var(beg) and the optional var(end) may be mathematical
expressions. As in parameter subscripting they may be negative to make expressions. As in parameter subscripting they may be negative to make
them count from the last match backward. E.g.: `tt(*(-OL[1,3]))' them count from the last match backward. E.g.: `tt(*(-OL[1,3]))'
gives a list of the names of three biggest files. gives a list of the names of the three largest files.
) )
enditem() enditem()

View file

@ -12,9 +12,9 @@ not automatically be loaded if it is not linked in: on systems with
dynamic loading, `tt(zmodload complist)' is required. dynamic loading, `tt(zmodload complist)' is required.
subsect(Parameters) subsect(Parameters)
For both extensions one of the parameters tt(ZLS_COLORS) or tt(ZLS_COLOURS) The parameters tt(ZLS_COLORS) and tt(ZLS_COLOURS) describe how matches
must be set, even if the value is empty (which uses all the default values are highlighted. To turn on highlighting an empty value suffices, in
given below). These describe how matches are highlighted. The format of the which case all the default values given below will be used. The format of the
value of these parameters is the same as used by the GNU version of the value of these parameters is the same as used by the GNU version of the
tt(ls) command: a colon-separated list of specifications of the form tt(ls) command: a colon-separated list of specifications of the form
`var(name)=var(value)'. The var(name) may be one of the following strings, `var(name)=var(value)'. The var(name) may be one of the following strings,
@ -79,7 +79,12 @@ the default values will have no visual effect.
subsect(Menu selection) subsect(Menu selection)
The tt(complist) module also offers an alternative style of selecting The tt(complist) module also offers an alternative style of selecting
matches from a list, called menu-selection. It can be invoked directly by matches from a list, called menu-selection, which can be used if the
shell is set up to return to the last prompt after showing a
completion list (see the tt(ALWAYS_LAST_PROMPT) option in
ifzman(zmanref(zshoptions))\
ifnzman(noderef(Options))\
). It can be invoked directly by
the widget tt(menu-select) defined by the module. Alternatively, the widget tt(menu-select) defined by the module. Alternatively,
the parameter tt(SELECTMIN) can be set to an integer, which give the the parameter tt(SELECTMIN) can be set to an integer, which give the
minimum number of matches that must be present before menu selection is minimum number of matches that must be present before menu selection is

View file

@ -205,11 +205,30 @@ tt(AUTO_CD) option set) is not a directory, and does not begin with a
slash, try to expand the expression as if it were preceded by a `tt(~)' (see slash, try to expand the expression as if it were preceded by a `tt(~)' (see
noderef(Filename Expansion)). noderef(Filename Expansion)).
) )
pindex(CHASE_DOTS)
cindex(cd, with .. in argument)
item(tt(CHASE_DOTS))(
When changing to a directory containing a path segment `tt(..)' which would
otherwise be treated as cancelling the previous segment in the path (in
other words, `tt(foo/..)' would be removed from the path, or if `tt(..)' is
the first part of the path, the last part of tt($PWD) would be deleted),
instead resolve the path to the physical directory. This option is
overridden by tt(CHASE_LINKS).
For example, suppose tt(/foo/bar) is a link to the directory tt(/alt/rod).
Without this option set, `tt(cd /foo/bar/..)' changes to tt(/foo); with it
set, it changes to tt(/alt). The same applies if the current directory
is tt(/foo/bar) and `tt(cd ..)' is used. Note that all other symbolic
links in the path will also be resolved.
)
pindex(CHASE_LINKS) pindex(CHASE_LINKS)
cindex(links, symbolic) cindex(links, symbolic)
cindex(symbolic links) cindex(symbolic links)
item(tt(CHASE_LINKS) (tt(-w)))( item(tt(CHASE_LINKS) (tt(-w)))(
Resolve symbolic links to their true values when changing directory. Resolve symbolic links to their true values when changing directory.
This also has the effect of tt(CHASE_DOTS), i.e. a `tt(..)' path segment
will be treated as referring to the physical parent, even if the preceeding
path segment is a symbolic link.
) )
pindex(CLOBBER) pindex(CLOBBER)
cindex(clobbering, of files) cindex(clobbering, of files)
@ -416,9 +435,13 @@ isn't there.
pindex(HIST_EXPIRE_DUPS_FIRST) pindex(HIST_EXPIRE_DUPS_FIRST)
cindex(history, expiring duplicates) cindex(history, expiring duplicates)
item(tt(HIST_EXPIRE_DUPS_FIRST))( item(tt(HIST_EXPIRE_DUPS_FIRST))(
If the internal history needs to be trimmed to add a new line, If the internal history needs to be trimmed to add the current command line,
setting this option will cause the oldest duplicate history line to setting this option will cause the oldest history event that has a duplicate
be lost before losing a unique line from the list. to be lost before losing a unique event from the list.
You should be sure to set the value of tt(HISTSIZE) to a larger number
than tt(SAVEHIST) in order to give you some room for the duplicated
events, otherwise this option will behave just like
tt(HIST_IGNORE_ALL_DUPS) once the history fills up with unique events.
) )
pindex(HIST_IGNORE_ALL_DUPS) pindex(HIST_IGNORE_ALL_DUPS)
cindex(history, ignoring all duplicates) cindex(history, ignoring all duplicates)

View file

@ -507,7 +507,10 @@ If unset, the history is not saved.
) )
vindex(HISTSIZE) vindex(HISTSIZE)
item(tt(HISTSIZE) <S>)( item(tt(HISTSIZE) <S>)(
The maximum size of the history list. The maximum number of events stored in the internal history list.
If you use the tt(HIST_EXPIRE_DUPS_FIRST) option, setting this value
larger than the tt(SAVEHIST) size will give you the difference as a
cushion for saving duplicated history events.
) )
vindex(HOME) vindex(HOME)
item(tt(HOME) <S>)( item(tt(HOME) <S>)(

View file

@ -154,12 +154,9 @@ vindex(LASTWIDGET)
item(tt(LASTWIDGET) (scalar))( item(tt(LASTWIDGET) (scalar))(
The name of the last widget that was executed. The name of the last widget that was executed.
) )
vindex(keys) vindex(KEYS)
item(tt(keys) (array))( item(tt(KEYS) (scalar))(
The keys typed to invoke this widget, one element per The keys typed to invoke this widget, as a literal string.
key. Control-keys are reported with a leading `tt(^)', as in `tt(^A)',
and meta-keys are reported with a leading `tt(M-)', as in `tt(M-a)' and
`tt(M-^A)'.
) )
vindex(NUMERIC) vindex(NUMERIC)
item(tt(NUMERIC) (integer))( item(tt(NUMERIC) (integer))(

View file

@ -39,15 +39,21 @@ DEC: OSF/1 1.2, 1.3, 2.0, 3.*, DEC Unix 4.* (Alpha)
remove the bogus strip and use /bin/strip instead. remove the bogus strip and use /bin/strip instead.
On Digital UNIX 4.0, compilation with gcc and with --enable-dynamic On Digital UNIX 4.0, compilation with gcc and with --enable-dynamic
apparently needs configuring with explicit flags: apparently needs configuring with explicit flags when compiling
with debugging enabled:
DLLD=gcc LDFLAGS='-g -rpath <path-to-.so-files>' ./configure ... DLLD=gcc LDFLAGS='-g -rpath <path-to-.so-files>' ./configure ...
FreeBSD: FreeBSD 2.2.7 [3.1.4] FreeBSD: FreeBSD 2.2.7 [3.1.4]
Should build `out-of-the-box'. Should build `out-of-the-box'.
HP: HP-UX 9, 10.20 HP: HP-UX 9, 10.20, 11.0
Should build `out-of-the-box'. Should build `out-of-the-box'.
Problems with dynamic loading have been reported under 11, but
this should compile using the standard dlopen() function set
(rather than the 10.20 shl_load() function set). More details of
any difficulties would be appreciated.
IBM: AIX IBM: AIX
Should build `out-of-the-box'. On AIX 3.x (at least), Should build `out-of-the-box'. On AIX 3.x (at least),
--enable-zsh-mem will not work. --enable-zsh-mem will not work.
@ -87,9 +93,6 @@ SGI: IRIX 5.1.1.1, 5.2, 5.3, 6.2, 6.3, 6.5
full optimization (cc -O3 -OPT:Olimit=0) causes problems. full optimization (cc -O3 -OPT:Olimit=0) causes problems.
Sun: SunOS 4.1.* Sun: SunOS 4.1.*
Dynamic loading does not work under SunOS 4.1. Sometimes,
you may need to turn it off explicitly with --disable-dynamic.
Under 4.1.3 if yellow pages is used, username completion may cause Under 4.1.3 if yellow pages is used, username completion may cause
segmentation violation. This is a bug in the shared library not segmentation violation. This is a bug in the shared library not
in zsh. Some libc.so.1.9.* has this bug (it fails in yp_all). in zsh. Some libc.so.1.9.* has this bug (it fails in yp_all).

View file

@ -34,6 +34,7 @@ Globbing changes:
- Case-insensitive and approximate globbing. - Case-insensitive and approximate globbing.
- Ordering and indexing of globbing matches, e.g. *(om[1]) picks - Ordering and indexing of globbing matches, e.g. *(om[1]) picks
most recently modified file. most recently modified file.
- General file mode qualifier with chmod(1)-like syntax, e.g. *(f:u+wx:)
New loadable modules: New loadable modules:
- zftp, plus associated function suite, for turning your zsh session - zftp, plus associated function suite, for turning your zsh session

1
Functions/.cvsignore Normal file
View file

@ -0,0 +1 @@
Makefile

View file

@ -1,3 +1,3 @@
DISTFILES_SRC=' DISTFILES_SRC='
.distfiles Makefile.in README.zftp .cvsignore .distfiles Makefile.in README.zftp
' '

View file

@ -67,7 +67,10 @@ line=${line#*@}
host=${line%%:*} host=${line%%:*}
dir=${line#*:} dir=${line#*:}
if [[ $user = ftp || $user = anonymous ]]; then if [[ $ZFTP_USER = $user && $ZFTP_HOST = $host ]]; then
# We're already there, just change directory
zfcd ${dir:-~}
elif [[ $user = ftp || $user = anonymous ]]; then
# Anonymous ftp, so we don't need password etc. # Anonymous ftp, so we don't need password etc.
zfanon $host && [[ -n $dir ]] && zfcd $dir zfanon $host && [[ -n $dir ]] && zfcd $dir
elif [[ $zflastsession = ${host}:* && $user = $zflastuser ]]; then elif [[ $zflastsession = ${host}:* && $user = $zflastuser ]]; then

View file

@ -1,6 +1,6 @@
emulate -L zsh emulate -L zsh
[[ $1 = -n ]] || zmodload -ia zftp [[ $1 = -n ]] || zmodload -e zftp || zmodload -ia zftp
alias zfcd='noglob zfcd' alias zfcd='noglob zfcd'
alias zfget='noglob zfget' alias zfget='noglob zfget'

View file

@ -4,32 +4,55 @@
# to a key. # to a key.
# This allows incremental completion of a word. After starting this # This allows incremental completion of a word. After starting this
# command, a list of completion choices is shown after every character you # command, a list of completion choices can be shown after every character
# type, which you can delete with ^h or DEL. RET will accept the # you type, which you can delete with ^h or DEL. RET will accept the
# completion so far. You can hit TAB to do normal completion and ^g to # completion so far. You can hit TAB to do normal completion, ^g to
# abort back to the state when you started. # abort back to the state when you started, and ^d to list the matches.
# #
# Completion keys: # This works best with the new function based completion system.
# incremental_prompt Prompt to show in status line during icompletion; #
# the sequence `%u' is replaced by the unambiguous # Configuration keys:
# part of all matches if there is any and it is #
# different from the word on the line # incremental_prompt
# incremental_stop Pattern matching keys which will cause icompletion # Prompt to show in status line during icompletion. The sequence `%u'
# to stop and the key to be re-executed # is replaced by the unambiguous part of all matches if there is any
# incremental_break Pattern matching keys which will cause icompletion # and it is different from the word on the line. A `%s' is replaced
# to stop and the key to be discarded # with `-no match-', `-no prefix-', or an empty string if there is
# incremental_completer Set of completers, like the `completer' key # no completion matching the word on the line, if the matches have
# incremental_list If set to a non-empty string, the matches will be # no common prefix different from the word on the line or if there is
# listed on every key-press # such a common prefix, respectively. The sequence `%c' is replaced
# by the name of the completer function that generated the matches
# (without the leading underscore). Finally, `%n' is replaced by the
# number of matches generated and `%a' is replaced by an empty string
# if the matches are in the normal set (i.e. the one without file names
# with one of the suffixes from `fignore') and with ` -alt-' if the
# matches are in the alternate set.
#
# incremental_stop
# Pattern matching keys which will cause icompletion to stop and the
# key to be re-executed.
#
# incremental_break
# Pattern matching keys which will cause icompletion to stop and the
# key to be discarded.
#
# incremental_completer
# Set of completers, like the `completer' key for normal completion.
#
# incremental_list
# If set to a non-empty string, the matches will be listed on every
# key-press.
emulate -L zsh emulate -L zsh
unsetopt autolist menucomplete automenu # doesn't work well unsetopt autolist menucomplete automenu # doesn't work well
local key lbuf="$LBUFFER" rbuf="$RBUFFER" pmpt word lastl lastr wid twid local key lbuf="$LBUFFER" rbuf="$RBUFFER" pmpt word
local lastl lastr wid twid num alt
[[ -n "$compconfig[incremental_completer]" ]] && [[ -n "$compconfig[incremental_completer]" ]] &&
set ${(s.:.)compconfig[incremental_completer]} set ${(s.:.)compconfig[incremental_completer]}
pmpt="${compconfig[incremental_prompt]-incremental completion...}" pmpt="${compconfig[incremental_prompt]-incremental (%c): %u%s}"
if [[ -n "$compconfig[incremental_list]" ]]; then if [[ -n "$compconfig[incremental_list]" ]]; then
wid=list-choices wid=list-choices
@ -40,12 +63,22 @@ fi
zle $wid "$@" zle $wid "$@"
LBUFFER="$lbuf" LBUFFER="$lbuf"
RBUFFER="$rbuf" RBUFFER="$rbuf"
if [[ "${LBUFFER}${RBUFFER}" = *${_lastcomp[unambiguous]}* ]]; then if (( ! _lastcomp[nmatches] )); then
word='' word=''
state='-no match-'
elif [[ "${LBUFFER}${RBUFFER}" = *${_lastcomp[unambiguous]}* ]]; then
word=''
state='-no prefix-'
else else
word="${_lastcomp[unambiguous]}" word="${_lastcomp[unambiguous]}"
state=''
fi fi
zle -R "${pmpt//\\%u/$word}" num=$_lastcomp[normal_nmatches]
if (( ! num )); then
num="${_lastcomp[nmatches]}"
alt=' -alt-'
fi
zle -R "${${${${${pmpt//\\%u/$word}//\\%s/$state}//\\%c/${_lastcomp[completer][2,-1]}}//\\%n/$num}//\\%a/$alt}"
read -k key read -k key
while [[ '#key' -ne '#\\r' && '#key' -ne '#\\n' && while [[ '#key' -ne '#\\r' && '#key' -ne '#\\n' &&
@ -72,12 +105,24 @@ while [[ '#key' -ne '#\\r' && '#key' -ne '#\\n' &&
zle $twid "$@" zle $twid "$@"
LBUFFER="$lastl" LBUFFER="$lastl"
RBUFFER="$lastr" RBUFFER="$lastr"
if [[ "${LBUFFER}${RBUFFER}" = *${_lastcomp[unambiguous]}* ]]; then if (( ! _lastcomp[nmatches] )); then
word='' word=''
state='-no match-'
elif [[ "${LBUFFER}${RBUFFER}" = *${_lastcomp[unambiguous]}* ]]; then
word=''
state='-no prefix-'
else else
word="${_lastcomp[unambiguous]}" word="${_lastcomp[unambiguous]}"
state=''
fi fi
zle -R "${pmpt//\\%u/$word}" num=$_lastcomp[normal_nmatches]
if (( ! num )); then
num="${_lastcomp[nmatches]}"
alt=' -alt-'
else
alt=''
fi
zle -R "${${${${${pmpt//\\%u/$word}//\\%s/$state}//\\%c/${_lastcomp[completer][2,-1]}}//\\%n/$num}//\\%a/$alt}"
read -k key read -k key
done done

View file

@ -246,9 +246,12 @@ plus those provide functions for the line editor, i.e.
FUNCTIONS_INSTALL='Core/* Base/* Builtins/* User/* Commands/* Zle/*' FUNCTIONS_INSTALL='Core/* Base/* Builtins/* User/* Commands/* Zle/*'
and if the --enable-dynamic option was given, the functions in and if the --enable-dynamic option was given, the functions in
Functions/Zftp, which require the zftp module to be available (see the Functions/Zftp, which require the zftp module to be available (see the
zshzftpsys manual page), will be included as well. There are also some zshzftpsys manual page), will be included as well. Note, however, that
miscellaneous functions with documentation in comments; the complete set some of the functions in the User subdirectory are version- and
of functions can be installed with system-specific.
There are also some miscellaneous functions with documentation in comments;
the complete set of functions can be installed with
FUNCTIONS_INSTALL='Core/* Base/* Builtins/* User/* Commands/* \ FUNCTIONS_INSTALL='Core/* Base/* Builtins/* User/* Commands/* \
Misc/* Zftp/* Zle/*' Misc/* Zftp/* Zle/*'
Note you should set this by hand to include `Zftp/*' if you have zftp Note you should set this by hand to include `Zftp/*' if you have zftp

View file

@ -29,3 +29,48 @@ while true; do sed -e 's/foo/bar/' Src/builtin.c >/dev/null; done
# ignoring the error messages from sed. # ignoring the error messages from sed.
# ^Z is more of a problem since you have to catch the sed. # ^Z is more of a problem since you have to catch the sed.
while true; do sed -e 's/foo/bar/' non-existent-file >/dev/null; done while true; do sed -e 's/foo/bar/' non-existent-file >/dev/null; done
# Try
# ^Z
# fg
# ^Z
# fg
fn() {
local a
while read a; do :; done
less "$@"
}
cat foo | fn bar
# Try
# ^Z
# fg
fn() {
cat builtin.c
}
fn | while read a; do :; done
# Try
# ^Z
# fg
# q
# ^Z
# fg
# q
fn() {
less builtin.c
echo done
}
x=2; while (( x-- )); do f; done
# Try
# ^C
# This won't work because zcat doesn't tell us that it received a signal.
# But
# ^Z
# fg
# ^C (probably a second ^C is needed: if the continued zcat is still running)
# works.
# (See also the file Etc/BUGS)
while true; do zcat foo.gz > /dev/null; done

View file

@ -2261,7 +2261,7 @@ zftp_type(char *name, char **args, int flags)
fflush(stdout); fflush(stdout);
return 0; return 0;
} else { } else {
nt = toupper(*str); nt = toupper(STOUC(*str));
/* /*
* RFC959 specifies other types, but these are the only * RFC959 specifies other types, but these are the only
* ones we know what to do with. * ones we know what to do with.
@ -2294,7 +2294,7 @@ zftp_mode(char *name, char **args, int flags)
fflush(stdout); fflush(stdout);
return 0; return 0;
} }
nt = str[0] = toupper(*str); nt = str[0] = toupper(STOUC(*str));
if (str[1] || (nt != 'S' && nt != 'B')) { if (str[1] || (nt != 'S' && nt != 'B')) {
zwarnnam(name, "transfer mode %s not recognised", str, 0); zwarnnam(name, "transfer mode %s not recognised", str, 0);
return 1; return 1;
@ -2651,7 +2651,7 @@ bin_zftp(char *name, char **args, char *ops, int func)
if ((prefs = getsparam("ZFTP_PREFS"))) { if ((prefs = getsparam("ZFTP_PREFS"))) {
zfprefs = 0; zfprefs = 0;
for (ptr = prefs; *ptr; ptr++) { for (ptr = prefs; *ptr; ptr++) {
switch (toupper(*ptr)) { switch (toupper(STOUC(*ptr))) {
case 'S': case 'S':
/* sendport */ /* sendport */
zfprefs |= ZFPF_SNDP; zfprefs |= ZFPF_SNDP;

View file

@ -218,6 +218,8 @@ struct cmatch {
int brsl; /* ...and the suffix */ int brsl; /* ...and the suffix */
char *rems; /* when to remove the suffix */ char *rems; /* when to remove the suffix */
char *remf; /* shell function to call for suffix-removal */ char *remf; /* shell function to call for suffix-removal */
int qipl; /* length of quote-prefix */
int qisl; /* length of quote-suffix */
int rnum; /* group relative number */ int rnum; /* group relative number */
int gnum; /* global number */ int gnum; /* global number */
}; };
@ -349,25 +351,25 @@ struct chdata {
#define CPN_NMATCHES 0 #define CPN_NMATCHES 0
#define CP_NMATCHES (1 << CPN_NMATCHES) #define CP_NMATCHES (1 << CPN_NMATCHES)
#define CPN_MATCHER 1 #define CPN_MATCHER 1
#define CP_MATCHER (1 << CPN_MATCHER) #define CP_MATCHER (1 << CPN_MATCHER)
#define CPN_MATCHERSTR 2 #define CPN_MATCHERSTR 2
#define CP_MATCHERSTR (1 << CPN_MATCHERSTR) #define CP_MATCHERSTR (1 << CPN_MATCHERSTR)
#define CPN_MATCHERTOT 3 #define CPN_MATCHERTOT 3
#define CP_MATCHERTOT (1 << CPN_MATCHERTOT) #define CP_MATCHERTOT (1 << CPN_MATCHERTOT)
#define CPN_CONTEXT 4 #define CPN_CONTEXT 4
#define CP_CONTEXT (1 << CPN_CONTEXT) #define CP_CONTEXT (1 << CPN_CONTEXT)
#define CPN_PARAMETER 5 #define CPN_PARAMETER 5
#define CP_PARAMETER (1 << CPN_PARAMETER) #define CP_PARAMETER (1 << CPN_PARAMETER)
#define CPN_REDIRECT 6 #define CPN_REDIRECT 6
#define CP_REDIRECT (1 << CPN_REDIRECT) #define CP_REDIRECT (1 << CPN_REDIRECT)
#define CPN_QUOTE 7 #define CPN_QUOTE 7
#define CP_QUOTE (1 << CPN_QUOTE) #define CP_QUOTE (1 << CPN_QUOTE)
#define CPN_QUOTING 8 #define CPN_QUOTING 8
#define CP_QUOTING (1 << CPN_QUOTING) #define CP_QUOTING (1 << CPN_QUOTING)
#define CPN_RESTORE 9 #define CPN_RESTORE 9
#define CP_RESTORE (1 << CPN_RESTORE) #define CP_RESTORE (1 << CPN_RESTORE)
#define CPN_LIST 10 #define CPN_LIST 10
#define CP_LIST (1 << CPN_LIST) #define CP_LIST (1 << CPN_LIST)
#define CPN_FORCELIST 11 #define CPN_FORCELIST 11
@ -398,6 +400,8 @@ struct chdata {
#define CP_OLDINS (1 << CPN_OLDINS) #define CP_OLDINS (1 << CPN_OLDINS)
#define CPN_VARED 24 #define CPN_VARED 24
#define CP_VARED (1 << CPN_VARED) #define CP_VARED (1 << CPN_VARED)
#define CPN_NNMATCHES 25
#define CP_NNMATCHES (1 << CPN_NNMATCHES)
#define CP_KEYPARAMS 25 #define CP_KEYPARAMS 26
#define CP_ALLKEYS ((unsigned int) 0xffffff) #define CP_ALLKEYS ((unsigned int) 0xffffff)

View file

@ -105,6 +105,7 @@ int incompfunc;
/**/ /**/
zlong compcurrent, zlong compcurrent,
compnmatches, compnmatches,
compnnmatches,
compmatcher, compmatcher,
compmatchertot, compmatchertot,
complistmax; complistmax;

View file

@ -27,6 +27,7 @@ compmatcher
compmatcherstr compmatcherstr
compmatchertot compmatchertot
compnmatches compnmatches
compnnmatches
compoldlist compoldlist
compoldins compoldins
compparameter compparameter

View file

@ -2210,6 +2210,7 @@ static struct compparam compkparams[] = {
{ "old_list", PM_SCALAR, VAL(compoldlist), NULL, NULL }, { "old_list", PM_SCALAR, VAL(compoldlist), NULL, NULL },
{ "old_insert", PM_SCALAR, VAL(compoldins), NULL, NULL }, { "old_insert", PM_SCALAR, VAL(compoldins), NULL, NULL },
{ "vared", PM_SCALAR, VAL(compvared), NULL, NULL }, { "vared", PM_SCALAR, VAL(compvared), NULL, NULL },
{ "normal_nmatches", PM_INTEGER, VAL(compnnmatches), NULL, NULL },
{ NULL, 0, NULL, NULL, NULL } { NULL, 0, NULL, NULL, NULL }
}; };

View file

@ -308,8 +308,8 @@ complistmatches(Hookdef dummy, Chdata dat)
Cmatch *p, m; Cmatch *p, m;
Cexpl *e; Cexpl *e;
int nlines = 0, ncols, nlist = 0, longest = 1, pnl = 0, opl = 0; int nlines = 0, ncols, nlist = 0, longest = 1, pnl = 0, opl = 0;
int of = isset(LISTTYPES); int of = isset(LISTTYPES), cf;
int mc, ml = 0, cc, hasm = 0, cl; int mc, ml = 0, cc, hasm = 0, cl = -1;
struct listcols col; struct listcols col;
if (minfo.asked == 2) { if (minfo.asked == 2) {
@ -318,15 +318,6 @@ complistmatches(Hookdef dummy, Chdata dat)
} }
getcols(&col); getcols(&col);
/* Set the cursor below the prompt. */
if (inselect)
clearflag = 0;
trashzle();
showinglist = listshown = 0;
clearflag = (isset(USEZLE) && !termflags &&
complastprompt && *complastprompt);
for (g = amatches; g; g = g->next) { for (g = amatches; g; g = g->next) {
char **pp = g->ylist; char **pp = g->ylist;
int nl = 0, l; int nl = 0, l;
@ -403,6 +394,19 @@ complistmatches(Hookdef dummy, Chdata dat)
nlines += 1 + ((1 + niceztrlen(m->str)) / columns); nlines += 1 + ((1 + niceztrlen(m->str)) / columns);
} }
} }
cf = (isset(USEZLE) && !termflags && complastprompt && *complastprompt);
if (!nlines || (mselect >= 0 && (!cf || (nlines + nlnct - 1) >= lines))) {
showinglist = listshown = 0;
noselect = 1;
return 1;
}
/* Set the cursor below the prompt. */
if (inselect)
clearflag = 0;
trashzle();
showinglist = listshown = 0;
clearflag = cf;
/* Maybe we have to ask if the user wants to see the list. */ /* Maybe we have to ask if the user wants to see the list. */
if ((!minfo.cur || !minfo.asked) && if ((!minfo.cur || !minfo.asked) &&
@ -654,20 +658,20 @@ complistmatches(Hookdef dummy, Chdata dat)
pnl = 1; pnl = 1;
g = g->next; g = g->next;
} }
if (clearflag) { if (clearflag) {
/* Move the cursor up to the prompt, if always_last_prompt * /* Move the cursor up to the prompt, if always_last_prompt *
* is set and all that... */ * is set and all that... */
if ((nlines += nlnct - 1) < lines) { if ((nlines += nlnct - 1) < lines) {
tcmultout(TCUP, TCMULTUP, nlines); tcmultout(TCUP, TCMULTUP, nlines);
showinglist = -1; showinglist = -1;
listshown = 1;
} else } else
clearflag = 0, putc('\n', shout); clearflag = 0, putc('\n', shout);
} else } else
putc('\n', shout); putc('\n', shout);
listshown = (clearflag ? 1 : -1);
if (!hasm || nlines >= lines) if (!hasm || nlines >= lines)
noselect = 1; noselect = 1;
return noselect; return noselect;
} }
@ -676,7 +680,7 @@ typedef struct menustack *Menustack;
struct menustack { struct menustack {
Menustack prev; Menustack prev;
char *line; char *line;
int cs; int cs, acc;
struct menuinfo info; struct menuinfo info;
Cmgroup amatches, pmatches, lmatches; Cmgroup amatches, pmatches, lmatches;
}; };
@ -742,19 +746,19 @@ domenuselect(Hookdef dummy, Chdata dat)
s->amatches = amatches; s->amatches = amatches;
s->pmatches = pmatches; s->pmatches = pmatches;
s->lmatches = lmatches; s->lmatches = lmatches;
menucmp = 0; s->acc = menuacc;
menucmp = menuacc = 0;
fixsuffix(); fixsuffix();
validlist = 0; validlist = 0;
pmatches = NULL; pmatches = NULL;
invalidatelist(); invalidatelist();
menucomplete(zlenoargs); menucomplete(zlenoargs);
if (dat->num < 2 || !minfo.cur || !*(minfo.cur)) { if (dat->num < 2 || !minfo.cur || !*(minfo.cur)) {
noselect = 1; noselect = clearlist = listshown = 1;
clearlist = 1;
zrefresh(); zrefresh();
break; break;
} }
clearlist = 1; clearlist = listshown = 1;
mselect = (*(minfo.cur))->gnum; mselect = (*(minfo.cur))->gnum;
continue; continue;
} else if (cmd == Th(z_acceptandhold) || } else if (cmd == Th(z_acceptandhold) ||
@ -767,6 +771,7 @@ domenuselect(Hookdef dummy, Chdata dat)
s->cs = cs; s->cs = cs;
memcpy(&(s->info), &minfo, sizeof(struct menuinfo)); memcpy(&(s->info), &minfo, sizeof(struct menuinfo));
s->amatches = s->pmatches = s->lmatches = NULL; s->amatches = s->pmatches = s->lmatches = NULL;
s->acc = menuacc;
acceptlast(); acceptlast();
do_menucmp(0); do_menucmp(0);
mselect = (*(minfo.cur))->gnum; mselect = (*(minfo.cur))->gnum;
@ -782,6 +787,7 @@ domenuselect(Hookdef dummy, Chdata dat)
spaceinline(l = strlen(u->line)); spaceinline(l = strlen(u->line));
strncpy((char *) line, u->line, l); strncpy((char *) line, u->line, l);
cs = u->cs; cs = u->cs;
menuacc = u->acc;
memcpy(&minfo, &(u->info), sizeof(struct menuinfo)); memcpy(&minfo, &(u->info), sizeof(struct menuinfo));
p = &(minfo.cur); p = &(minfo.cur);
if (u->pmatches && pmatches != u->pmatches) { if (u->pmatches && pmatches != u->pmatches) {

View file

@ -24,6 +24,7 @@ lastambig
linkkeymap linkkeymap
listshown listshown
lmatches lmatches
menuacc
menucmp menucmp
menucomplete menucomplete
menucur menucur

View file

@ -67,7 +67,7 @@ static struct zleparam {
zleunsetfn, NULL }, zleunsetfn, NULL },
{ "LASTWIDGET", PM_SCALAR | PM_READONLY, NULL, FN(get_lwidget), { "LASTWIDGET", PM_SCALAR | PM_READONLY, NULL, FN(get_lwidget),
zleunsetfn, NULL }, zleunsetfn, NULL },
{ "keys", PM_ARRAY | PM_READONLY, NULL, FN(get_keys), { "KEYS", PM_SCALAR | PM_READONLY, NULL, FN(get_keys),
zleunsetfn, NULL }, zleunsetfn, NULL },
{ "NUMERIC", PM_INTEGER | PM_UNSET, FN(set_numeric), FN(get_numeric), { "NUMERIC", PM_INTEGER | PM_UNSET, FN(set_numeric), FN(get_numeric),
unset_numeric, NULL }, unset_numeric, NULL },
@ -247,29 +247,10 @@ get_lwidget(Param pm)
} }
/**/ /**/
static char ** static char *
get_keys(Param pm) get_keys(Param pm)
{ {
char **r, **q, *p, *k, c; return keybuf;
r = (char **) zhalloc((strlen(keybuf) + 1) * sizeof(char *));
for (q = r, p = keybuf; (c = *p); q++, p++) {
k = *q = (char *) zhalloc(5);
if (c & 0x80) {
*k++ = 'M';
*k++ = '-';
c &= 0x7f;
}
if (c < 32 || c == 0x7f) {
*k++ = '^';
c ^= 64;
}
*k++ = c;
*k = '\0';
}
*q = NULL;
return r;
} }
/**/ /**/

View file

@ -53,7 +53,8 @@ int nlnct;
/**/ /**/
int showinglist; int showinglist;
/* Non-zero if a completion list was displayed. */ /* > 0 if a completion list is displayed below the prompt,
* < 0 if a list is displayed above the prompt. */
/**/ /**/
int listshown; int listshown;
@ -265,7 +266,7 @@ zrefresh(void)
if (inlist) if (inlist)
return; return;
if (clearlist && listshown) { if (clearlist && listshown > 0) {
if (tccan(TCCLEAREOD)) { if (tccan(TCCLEAREOD)) {
int ovln = vln, ovcs = vcs; int ovln = vln, ovcs = vcs;
char *nb = nbuf[vln]; char *nb = nbuf[vln];
@ -331,7 +332,8 @@ zrefresh(void)
tcout(TCCLEAREOD); tcout(TCCLEAREOD);
else else
cleareol = 1; /* request: clear to end of line */ cleareol = 1; /* request: clear to end of line */
listshown = 0; if (listshown > 0)
listshown = 0;
} }
if (t0 > -1) if (t0 > -1)
olnct = t0; olnct = t0;

View file

@ -106,10 +106,11 @@ static int insmnum, insgnum, insgroup, insspace;
static int movetoend; static int movetoend;
/* != 0 if we are in the middle of a menu completion */ /* != 0 if we are in the middle of a menu completion and number of matches
* accepted with accept-and-menu-complete */
/**/ /**/
int menucmp; int menucmp, menuacc;
/* Information about menucompletion. */ /* Information about menucompletion. */
@ -192,6 +193,10 @@ static char *qipre, *qisuf, autoq;
static int lpl, lsl, rpl, rsl, fpl, fsl, lppl, lpsl; static int lpl, lsl, rpl, rsl, fpl, fsl, lppl, lpsl;
static int noreal; static int noreal;
/* A parameter expansion prefix (like ${). */
static char *parpre;
/* This is either zero or equal to the special character the word we are * /* This is either zero or equal to the special character the word we are *
* trying to complete starts with (e.g. Tilde or Equals). */ * trying to complete starts with (e.g. Tilde or Equals). */
@ -209,9 +214,9 @@ static char *qword;
static Cmgroup mgroup; static Cmgroup mgroup;
/* A match counter. */ /* Match counters: all matches, normal matches (not alternate set). */
static int mnum; static int mnum, nmnum;
/* The match counter when unambig_data() was called. */ /* The match counter when unambig_data() was called. */
@ -540,6 +545,8 @@ reversemenucomplete(char **args)
void void
acceptlast(void) acceptlast(void)
{ {
menuacc++;
if (brbeg && *brbeg) { if (brbeg && *brbeg) {
int l; int l;
@ -553,10 +560,16 @@ acceptlast(void)
brbeg[l] = ','; brbeg[l] = ',';
brbeg[l + 1] = '\0'; brbeg[l + 1] = '\0';
} else { } else {
int l;
cs = minfo.pos + minfo.len + minfo.insc; cs = minfo.pos + minfo.len + minfo.insc;
iremovesuffix(' ', 1); iremovesuffix(' ', 1);
l = cs;
cs = minfo.pos + minfo.len - (*(minfo.cur))->qisl;
foredel(l - cs);
inststrlen(" ", 1, 1); inststrlen(" ", 1, 1);
if (parpre)
inststr(parpre);
minfo.insc = minfo.len = 0; minfo.insc = minfo.len = 0;
minfo.pos = cs; minfo.pos = cs;
minfo.we = 1; minfo.we = 1;
@ -694,6 +707,9 @@ check_param(char *s, int set, int test)
{ {
char *p; char *p;
zsfree(parpre);
parpre = NULL;
if (!test) if (!test)
ispar = parq = eparq = 0; ispar = parq = eparq = 0;
/* Try to find a `$'. */ /* Try to find a `$'. */
@ -755,6 +771,8 @@ check_param(char *s, int set, int test)
/* Now make sure that the cursor is inside the name. */ /* Now make sure that the cursor is inside the name. */
if (offs <= e - s && offs >= b - s && n <= 0) { if (offs <= e - s && offs >= b - s && n <= 0) {
char sav;
if (br) { if (br) {
p = e; p = e;
while (*p == (test ? Dnull : '"')) while (*p == (test ? Dnull : '"'))
@ -782,6 +800,12 @@ check_param(char *s, int set, int test)
else else
parq = eparq = 0; parq = eparq = 0;
/* Save the prefix. */
sav = *b;
*b = '\0';
untokenize(parpre = ztrdup(s));
*b = sav;
/* And adjust wb, we, and offs again. */ /* And adjust wb, we, and offs again. */
offs -= b - s; offs -= b - s;
wb = cs - offs; wb = cs - offs;
@ -1017,7 +1041,7 @@ docomplete(int lst)
int ocs = cs, ne = noerrs; int ocs = cs, ne = noerrs;
noerrs = 1; noerrs = 1;
doexpansion(s, lst, olst, lincmd); ret = doexpansion(s, lst, olst, lincmd);
lastambig = 0; lastambig = 0;
noerrs = ne; noerrs = ne;
@ -1043,8 +1067,8 @@ docomplete(int lst)
} }
} }
ret = docompletion(s, lst, lincmd); ret = docompletion(s, lst, lincmd);
} else } else if (ret)
ret = !strcmp(ol, (char *) line); clearlist = 1;
} else } else
/* Just do completion. */ /* Just do completion. */
ret = docompletion(s, lst, lincmd); ret = docompletion(s, lst, lincmd);
@ -1064,7 +1088,7 @@ docomplete(int lst)
dat.num = nmatches; dat.num = nmatches;
dat.cur = NULL; dat.cur = NULL;
if (runhookdef(MENUSTARTHOOK, (void *) &dat)) if (runhookdef(MENUSTARTHOOK, (void *) &dat))
menucmp = 0; menucmp = menuacc = 0;
} }
return ret; return ret;
} }
@ -1736,9 +1760,10 @@ get_comp_string(void)
/* Expand the current word. */ /* Expand the current word. */
/**/ /**/
static void static int
doexpansion(char *s, int lst, int olst, int explincmd) doexpansion(char *s, int lst, int olst, int explincmd)
{ {
int ret = 1;
LinkList vl; LinkList vl;
char *ss; char *ss;
@ -1775,7 +1800,7 @@ doexpansion(char *s, int lst, int olst, int explincmd)
} }
if (lst == COMP_LIST_EXPAND) { if (lst == COMP_LIST_EXPAND) {
/* Only the list of expansions was requested. */ /* Only the list of expansions was requested. */
listlist(vl); ret = listlist(vl);
showinglist = 0; showinglist = 0;
goto end; goto end;
} }
@ -1783,6 +1808,7 @@ doexpansion(char *s, int lst, int olst, int explincmd)
cs = wb; cs = wb;
foredel(we - wb); foredel(we - wb);
while ((ss = (char *)ugetnode(vl))) { while ((ss = (char *)ugetnode(vl))) {
ret = 0;
untokenize(ss); untokenize(ss);
ss = quotename(ss, NULL); ss = quotename(ss, NULL);
inststr(ss); inststr(ss);
@ -1801,6 +1827,8 @@ doexpansion(char *s, int lst, int olst, int explincmd)
end: end:
popheap(); popheap();
} LASTALLOC; } LASTALLOC;
return ret;
} }
/* This is called from the lexer to give us word positions. */ /* This is called from the lexer to give us word positions. */
@ -3547,6 +3575,8 @@ add_match_data(int alt, char *str, Cline line,
ai->line = join_clines(ai->line, line); ai->line = join_clines(ai->line, line);
mnum++; mnum++;
if (!alt)
nmnum++;
ai->count++; ai->count++;
/* Allocate and fill the match structure. */ /* Allocate and fill the match structure. */
@ -3569,6 +3599,8 @@ add_match_data(int alt, char *str, Cline line,
cm->flags = flags; cm->flags = flags;
cm->brpl = bpl; cm->brpl = bpl;
cm->brsl = bsl; cm->brsl = bsl;
cm->qipl = qipl;
cm->qisl = qisl;
cm->autoq = (autoq ? autoq : (inbackt ? '`' : '\0')); cm->autoq = (autoq ? autoq : (inbackt ? '`' : '\0'));
cm->rems = cm->remf = NULL; cm->rems = cm->remf = NULL;
addlinknode((alt ? fmatches : matches), cm); addlinknode((alt ? fmatches : matches), cm);
@ -3896,6 +3928,7 @@ addmatches(Cadata dat, char **argv)
} }
} }
compnmatches = mnum; compnmatches = mnum;
compnnmatches = nmnum;
if (dat->exp) if (dat->exp)
addexpl(); addexpl();
if (dat->apar) if (dat->apar)
@ -4380,10 +4413,14 @@ docompletion(char *s, int lst, int incmd)
} }
if (comppatmatch && *comppatmatch && comppatmatch != opm) if (comppatmatch && *comppatmatch && comppatmatch != opm)
haspattern = 1; haspattern = 1;
if (!useline && uselist) if (!useline && uselist) {
/* All this and the guy only wants to see the list, sigh. */ /* All this and the guy only wants to see the list, sigh. */
cs = 0;
foredel(ll);
inststr(origline);
cs = origcs;
showinglist = -2; showinglist = -2;
else if (useline) { } else if (useline) {
/* We have matches. */ /* We have matches. */
if (nmatches > 1) { if (nmatches > 1) {
/* There is more than one match. */ /* There is more than one match. */
@ -4399,9 +4436,13 @@ docompletion(char *s, int lst, int incmd)
do_single(m->matches[0]); do_single(m->matches[0]);
invalidatelist(); invalidatelist();
} }
} else } else {
invalidatelist(); invalidatelist();
cs = 0;
foredel(ll);
inststr(origline);
cs = origcs;
}
/* Print the explanation strings if needed. */ /* Print the explanation strings if needed. */
if (!showinglist && validlist && usemenu != 2 && nmatches != 1) { if (!showinglist && validlist && usemenu != 2 && nmatches != 1) {
Cmgroup g = amatches; Cmgroup g = amatches;
@ -4582,22 +4623,22 @@ callcompfunc(char *s, char *fn)
zsfree(compprefix); zsfree(compprefix);
zsfree(compsuffix); zsfree(compsuffix);
if (unset(COMPLETEINWORD)) { if (unset(COMPLETEINWORD)) {
/* Maybe we'll have to do quoting here some time. */ tmp = quotename(s, NULL);
tmp = dupstring(s);
untokenize(tmp); untokenize(tmp);
compprefix = ztrdup(tmp); compprefix = ztrdup(tmp);
compsuffix = ztrdup(""); compsuffix = ztrdup("");
} else { } else {
char *ss, sav; char *ss, sav;
tmp = dupstring(s); ss = s + offs;
ss = tmp + offs;
sav = *ss; sav = *ss;
*ss = '\0'; *ss = '\0';
tmp = quotename(s, NULL);
untokenize(tmp); untokenize(tmp);
compprefix = ztrdup(tmp); compprefix = ztrdup(tmp);
*ss = sav; *ss = sav;
ss = quotename(ss, NULL);
untokenize(ss); untokenize(ss);
compsuffix = ztrdup(ss); compsuffix = ztrdup(ss);
} }
@ -4611,6 +4652,7 @@ callcompfunc(char *s, char *fn)
compqisuffix = ztrdup(qisuf ? qisuf : ""); compqisuffix = ztrdup(qisuf ? qisuf : "");
compcurrent = (usea ? (clwpos + 1 - aadd) : 0); compcurrent = (usea ? (clwpos + 1 - aadd) : 0);
compnmatches = mnum; compnmatches = mnum;
compnnmatches = nmnum;
zsfree(complist); zsfree(complist);
switch (uselist) { switch (uselist) {
@ -4825,13 +4867,13 @@ makecomplist(char *s, int incmd, int lst)
if (!validlist) if (!validlist)
lastambig = 0; lastambig = 0;
amatches = NULL; amatches = NULL;
mnum = 0; mnum = nmnum = 0;
unambig_mnum = -1; unambig_mnum = -1;
isuf = NULL; isuf = NULL;
insmnum = insgnum = 1; insmnum = insgnum = 1;
insgroup = oldlist = oldins = 0; insgroup = oldlist = oldins = 0;
begcmgroup("default", 0); begcmgroup("default", 0);
menucmp = 0; menucmp = menuacc = 0;
ccused = newlinklist(); ccused = newlinklist();
ccstack = newlinklist(); ccstack = newlinklist();
@ -4984,6 +5026,8 @@ sep_comp_string(char *ss, char *s, int noffs, int rec)
memcpy(tmp + sl + 1, s, noffs); memcpy(tmp + sl + 1, s, noffs);
tmp[(scs = cs = sl + 1 + noffs)] = 'x'; tmp[(scs = cs = sl + 1 + noffs)] = 'x';
strcpy(tmp + sl + 2 + noffs, s + noffs); strcpy(tmp + sl + 2 + noffs, s + noffs);
if (incompfunc)
tmp = rembslash(tmp);
inpush(dupstrspace(tmp), 0, NULL); inpush(dupstrspace(tmp), 0, NULL);
line = (unsigned char *) tmp; line = (unsigned char *) tmp;
ll = tl - 1; ll = tl - 1;
@ -5013,6 +5057,7 @@ sep_comp_string(char *ss, char *s, int noffs, int rec)
p = NULL; p = NULL;
if (!got && !zleparse) { if (!got && !zleparse) {
DPUTS(!p, "no current word in substr"); DPUTS(!p, "no current word in substr");
got = 1;
cur = i; cur = i;
swb = wb - 1; swb = wb - 1;
swe = we - 1; swe = we - 1;
@ -5077,7 +5122,7 @@ sep_comp_string(char *ss, char *s, int noffs, int rec)
} }
sav = s[(i = swb - sl - 1)]; sav = s[(i = swb - sl - 1)];
s[i] = '\0'; s[i] = '\0';
qp = tricat(qipre, s, ""); qp = tricat(qipre, (incompfunc ? rembslash(s) : s), "");
s[i] = sav; s[i] = sav;
if (swe < swb) if (swe < swb)
swe = swb; swe = swb;
@ -5085,7 +5130,7 @@ sep_comp_string(char *ss, char *s, int noffs, int rec)
sl = strlen(s); sl = strlen(s);
if (swe > sl) if (swe > sl)
swe = sl, ns[swe - swb + 1] = '\0'; swe = sl, ns[swe - swb + 1] = '\0';
qs = tricat(s + swe, qisuf, ""); qs = tricat((incompfunc ? rembslash(s + swe) : s + swe), qisuf, "");
sl = strlen(ns); sl = strlen(ns);
if (soffs > sl) if (soffs > sl)
soffs = sl; soffs = sl;
@ -5172,7 +5217,7 @@ sep_comp_string(char *ss, char *s, int noffs, int rec)
compisuffix = ztrdup(""); compisuffix = ztrdup("");
zsfree(compqiprefix); zsfree(compqiprefix);
zsfree(compqisuffix); zsfree(compqisuffix);
if (instring) { if (ois) {
compqiprefix = qp; compqiprefix = qp;
compqisuffix = qs; compqisuffix = qs;
} else { } else {
@ -5188,6 +5233,7 @@ sep_comp_string(char *ss, char *s, int noffs, int rec)
p = compwords[i] = (char *) getdata(n); p = compwords[i] = (char *) getdata(n);
untokenize(p); untokenize(p);
} }
compcurrent = cur + 1;
compwords[i] = NULL; compwords[i] = NULL;
} }
autoq = oaq; autoq = oaq;
@ -5242,6 +5288,7 @@ makecomplistcall(Compctl cc)
inbackt = oib; inbackt = oib;
autoq = oaq; autoq = oaq;
compnmatches = mnum; compnmatches = mnum;
compnnmatches = nmnum;
} LASTALLOC; } LASTALLOC;
} SWITCHBACKHEAPS; } SWITCHBACKHEAPS;
@ -5317,6 +5364,7 @@ makecomplistctl(int flags)
autoq = oaq; autoq = oaq;
offs = ooffs; offs = ooffs;
compnmatches = mnum; compnmatches = mnum;
compnnmatches = nmnum;
zsfree(cmdstr); zsfree(cmdstr);
freearray(clwords); freearray(clwords);
cmdstr = os; cmdstr = os;
@ -5979,7 +6027,10 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
char save = line[cs]; char save = line[cs];
line[cs] = 0; line[cs] = 0;
lppre = dupstring((char *) (line + wb)); lppre = dupstring((char *) line + wb +
(qipre && *qipre ?
(strlen(qipre) -
(*qipre == '\'' || *qipre == '\"')) : 0));
line[cs] = save; line[cs] = save;
if (brbeg && *brbeg) if (brbeg && *brbeg)
strcpy(lppre + qbrpl, lppre + qbrpl + strlen(brbeg)); strcpy(lppre + qbrpl, lppre + qbrpl + strlen(brbeg));
@ -5998,11 +6049,17 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
lppl = 0; lppl = 0;
} }
if (cs != we) { if (cs != we) {
char save = line[we]; int end = we;
char save = line[end];
line[we] = 0; if (qisuf && *qisuf) {
int ql = strlen(qisuf);
end -= ql - (qisuf[ql-1] == '\'' || qisuf[ql-1] == '"');
}
line[end] = 0;
lpsuf = dupstring((char *) (line + cs)); lpsuf = dupstring((char *) (line + cs));
line[we] = save; line[end] = save;
if (brend && *brend) { if (brend && *brend) {
char *p = lpsuf + qbrsl - (cs - wb); char *p = lpsuf + qbrsl - (cs - wb);
@ -6640,7 +6697,8 @@ invalidatelist(void)
listmatches(); listmatches();
if (validlist) if (validlist)
freematches(); freematches();
lastambig = menucmp = validlist = showinglist = fromcomp = 0; lastambig = menucmp = menuacc = validlist = showinglist =
fromcomp = listshown = 0;
minfo.cur = NULL; minfo.cur = NULL;
minfo.asked = 0; minfo.asked = 0;
compwidget = NULL; compwidget = NULL;
@ -6917,6 +6975,8 @@ dupmatch(Cmatch m)
r->rems = ztrdup(m->rems); r->rems = ztrdup(m->rems);
r->remf = ztrdup(m->remf); r->remf = ztrdup(m->remf);
r->autoq = m->autoq; r->autoq = m->autoq;
r->qipl = m->qipl;
r->qisl = m->qisl;
return r; return r;
} }
@ -7346,7 +7406,9 @@ instmatch(Cmatch m, int *scs)
/* Ignored prefix. */ /* Ignored prefix. */
if (m->ipre) { if (m->ipre) {
inststrlen(m->ipre, 1, (l = strlen(m->ipre))); char *p = m->ipre + (menuacc ? m->qipl : 0);
inststrlen(p, 1, (l = strlen(p)));
r += l; r += l;
} }
/* -P prefix. */ /* -P prefix. */
@ -7413,7 +7475,8 @@ static int
do_ambiguous(void) do_ambiguous(void)
{ {
int ret = 0; int ret = 0;
menucmp = 0;
menucmp = menuacc = 0;
/* If we have to insert the first match, call do_single(). This is * /* If we have to insert the first match, call do_single(). This is *
* how REC_EXACT takes effect. We effectively turn the ambiguous * * how REC_EXACT takes effect. We effectively turn the ambiguous *
@ -7501,11 +7564,13 @@ do_ambiguous(void)
* if it is needed. */ * if it is needed. */
if (isset(LISTBEEP)) if (isset(LISTBEEP))
ret = 1; ret = 1;
if (uselist && (usemenu != 2 || (!showinglist && !oldlist)) &&
if (uselist && (usemenu != 2 || (!listshown && !oldlist)) &&
((!showinglist && (!listshown || !oldlist)) || ((!showinglist && (!listshown || !oldlist)) ||
(usemenu == 3 && !oldlist)) && (usemenu == 3 && !oldlist)) &&
(smatches >= 2 || (compforcelist && *compforcelist))) (smatches >= 2 || (compforcelist && *compforcelist)))
showinglist = -2; showinglist = -2;
return ret; return ret;
} }
@ -7649,7 +7714,7 @@ do_single(Cmatch m)
} }
} }
if (!minfo.insc) if (!minfo.insc)
cs = minfo.pos + minfo.len; cs = minfo.pos + minfo.len - m->qisl;
} }
/* If completing in a brace expansion... */ /* If completing in a brace expansion... */
if (brbeg) { if (brbeg) {
@ -7688,8 +7753,11 @@ do_single(Cmatch m)
if (minfo.we && m->ripre && isset(AUTOPARAMKEYS)) if (minfo.we && m->ripre && isset(AUTOPARAMKEYS))
makeparamsuffix(((m->flags & CMF_PARBR) ? 1 : 0), minfo.insc - parq); makeparamsuffix(((m->flags & CMF_PARBR) ? 1 : 0), minfo.insc - parq);
if ((menucmp && !minfo.we) || !movetoend) if ((menucmp && !minfo.we) || !movetoend) {
cs = minfo.end; cs = minfo.end;
if (cs + m->qisl == lastend)
cs += minfo.insc;
}
{ {
Cmatch *om = minfo.cur; Cmatch *om = minfo.cur;
struct chdata dat; struct chdata dat;
@ -7732,6 +7800,7 @@ do_ambig_menu(void)
if (usemenu != 3) { if (usemenu != 3) {
menucmp = 1; menucmp = 1;
menuacc = 0;
minfo.cur = NULL; minfo.cur = NULL;
} else { } else {
if (oldlist) { if (oldlist) {
@ -7931,13 +8000,6 @@ ilistmatches(Hookdef dummy, Chdata dat)
int nlines = 0, ncols, nlist = 0, longest = 1, pnl = 0; int nlines = 0, ncols, nlist = 0, longest = 1, pnl = 0;
int of = isset(LISTTYPES), opl = 0; int of = isset(LISTTYPES), opl = 0;
/* Set the cursor below the prompt. */
trashzle();
showinglist = listshown = 0;
clearflag = (isset(USEZLE) && !termflags &&
complastprompt && *complastprompt);
for (g = amatches; g; g = g->next) { for (g = amatches; g; g = g->next) {
char **pp = g->ylist; char **pp = g->ylist;
int nl = 0, l; int nl = 0, l;
@ -8013,6 +8075,16 @@ ilistmatches(Hookdef dummy, Chdata dat)
nlines += 1 + ((1 + niceztrlen(m->str)) / columns); nlines += 1 + ((1 + niceztrlen(m->str)) / columns);
} }
} }
if (!nlines) {
showinglist = listshown = 0;
return 1;
}
/* Set the cursor below the prompt. */
trashzle();
showinglist = listshown = 0;
clearflag = (isset(USEZLE) && !termflags &&
complastprompt && *complastprompt);
/* Maybe we have to ask if the user wants to see the list. */ /* Maybe we have to ask if the user wants to see the list. */
if ((!minfo.cur || !minfo.asked) && if ((!minfo.cur || !minfo.asked) &&
@ -8152,25 +8224,25 @@ ilistmatches(Hookdef dummy, Chdata dat)
pnl = 1; pnl = 1;
g = g->next; g = g->next;
} }
if (clearflag) { if (clearflag) {
/* Move the cursor up to the prompt, if always_last_prompt * /* Move the cursor up to the prompt, if always_last_prompt *
* is set and all that... */ * is set and all that... */
if ((nlines += nlnct - 1) < lines) { if ((nlines += nlnct - 1) < lines) {
tcmultout(TCUP, TCMULTUP, nlines); tcmultout(TCUP, TCMULTUP, nlines);
showinglist = -1; showinglist = -1;
listshown = 1;
} else } else
clearflag = 0, putc('\n', shout); clearflag = 0, putc('\n', shout);
} else } else
putc('\n', shout); putc('\n', shout);
listshown = (clearflag ? 1 : -1);
return 0; return 0;
} }
/* This is used to print expansions. */ /* This is used to print expansions. */
/**/ /**/
void int
listlist(LinkList l) listlist(LinkList l)
{ {
struct cmgroup dg; struct cmgroup dg;
@ -8193,6 +8265,8 @@ listlist(LinkList l)
validlist = vl; validlist = vl;
smatches = sm; smatches = sm;
complastprompt = oclp; complastprompt = oclp;
return !dg.lcount;
} }
/* Expand the history references. */ /* Expand the history references. */

View file

@ -658,6 +658,9 @@ set_pwd_env(void)
} }
} }
/* set if we are resolving links to their true paths */
static int chasinglinks;
/* The main pwd changing function. The real work is done by other * /* The main pwd changing function. The real work is done by other *
* functions. cd_get_dest() does the initial argument processing; * * functions. cd_get_dest() does the initial argument processing; *
* cd_do_chdir() actually changes directory, if possible; cd_new_pwd() * * cd_do_chdir() actually changes directory, if possible; cd_new_pwd() *
@ -670,7 +673,6 @@ bin_cd(char *nam, char **argv, char *ops, int func)
{ {
LinkNode dir; LinkNode dir;
struct stat st1, st2; struct stat st1, st2;
int chaselinks;
if (isset(RESTRICTED)) { if (isset(RESTRICTED)) {
zwarnnam(nam, "restricted", NULL, 0); zwarnnam(nam, "restricted", NULL, 0);
@ -694,7 +696,7 @@ bin_cd(char *nam, char **argv, char *ops, int func)
for (s = *argv; *++s; ops[STOUC(*s)] = 1); for (s = *argv; *++s; ops[STOUC(*s)] = 1);
} }
brk: brk:
chaselinks = ops['P'] || (isset(CHASELINKS) && !ops['L']); chasinglinks = ops['P'] || (isset(CHASELINKS) && !ops['L']);
PERMALLOC { PERMALLOC {
pushnode(dirstack, ztrdup(pwd)); pushnode(dirstack, ztrdup(pwd));
if (!(dir = cd_get_dest(nam, argv, ops, func))) { if (!(dir = cd_get_dest(nam, argv, ops, func))) {
@ -702,7 +704,7 @@ bin_cd(char *nam, char **argv, char *ops, int func)
LASTALLOC_RETURN 1; LASTALLOC_RETURN 1;
} }
} LASTALLOC; } LASTALLOC;
cd_new_pwd(func, dir, chaselinks); cd_new_pwd(func, dir);
if (stat(unmeta(pwd), &st1) < 0) { if (stat(unmeta(pwd), &st1) < 0) {
zsfree(pwd); zsfree(pwd);
@ -710,7 +712,7 @@ bin_cd(char *nam, char **argv, char *ops, int func)
} else if (stat(".", &st2) < 0) } else if (stat(".", &st2) < 0)
chdir(unmeta(pwd)); chdir(unmeta(pwd));
else if (st1.st_ino != st2.st_ino || st1.st_dev != st2.st_dev) { else if (st1.st_ino != st2.st_ino || st1.st_dev != st2.st_dev) {
if (chaselinks) { if (chasinglinks) {
zsfree(pwd); zsfree(pwd);
pwd = metafy(zgetcwd(), -1, META_DUP); pwd = metafy(zgetcwd(), -1, META_DUP);
} else { } else {
@ -915,40 +917,49 @@ static char *
cd_try_chdir(char *pfix, char *dest, int hard) cd_try_chdir(char *pfix, char *dest, int hard)
{ {
char *buf; char *buf;
int dlen, dochaselinks = 0;
/* handle directory prefix */ /* handle directory prefix */
if (pfix && *pfix) { if (pfix && *pfix) {
if (*pfix == '/') if (*pfix == '/')
buf = tricat(pfix, "/", dest); buf = tricat(pfix, "/", dest);
else { else {
int pwl = strlen(pwd);
int pfl = strlen(pfix); int pfl = strlen(pfix);
dlen = strlen(pwd);
buf = zalloc(pwl + pfl + strlen(dest) + 3); buf = zalloc(dlen + pfl + strlen(dest) + 3);
strcpy(buf, pwd); strcpy(buf, pwd);
buf[pwl] = '/'; buf[dlen] = '/';
strcpy(buf + pwl + 1, pfix); strcpy(buf + dlen + 1, pfix);
buf[pwl + 1 + pfl] = '/'; buf[dlen + 1 + pfl] = '/';
strcpy(buf + pwl + pfl + 2, dest); strcpy(buf + dlen + pfl + 2, dest);
} }
} else if (*dest == '/') } else if (*dest == '/')
buf = ztrdup(dest); buf = ztrdup(dest);
else { else {
int pwl = strlen(pwd); dlen = strlen(pwd);
buf = zalloc(pwl + strlen(dest) + 2); buf = zalloc(dlen + strlen(dest) + 2);
strcpy(buf, pwd); strcpy(buf, pwd);
buf[pwl] = '/'; buf[dlen] = '/';
strcpy(buf + pwl + 1, dest); strcpy(buf + dlen + 1, dest);
} }
/* Normalise path. See the definition of fixdir() for what this means. */ /* Normalise path. See the definition of fixdir() for what this means.
fixdir(buf); * We do not do this if we are chasing links.
*/
if (!chasinglinks)
dochaselinks = fixdir(buf);
else
unmetafy(buf, &dlen);
if (lchdir(buf, NULL, hard)) { if (lchdir(buf, NULL, hard)) {
zsfree(buf); free(buf);
return NULL; return NULL;
} }
/* the chdir succeeded, so decide if we should force links to be chased */
if (dochaselinks)
chasinglinks = 1;
return metafy(buf, -1, META_NOALLOC); return metafy(buf, -1, META_NOALLOC);
} }
@ -956,7 +967,7 @@ cd_try_chdir(char *pfix, char *dest, int hard)
/**/ /**/
static void static void
cd_new_pwd(int func, LinkNode dir, int chaselinks) cd_new_pwd(int func, LinkNode dir)
{ {
List l; List l;
char *new_pwd, *s; char *new_pwd, *s;
@ -972,7 +983,7 @@ cd_new_pwd(int func, LinkNode dir, int chaselinks)
} else if (func == BIN_CD && unset(AUTOPUSHD)) } else if (func == BIN_CD && unset(AUTOPUSHD))
zsfree(getlinknode(dirstack)); zsfree(getlinknode(dirstack));
if (chaselinks) { if (chasinglinks) {
s = new_pwd; s = new_pwd;
new_pwd = findpwd(s); new_pwd = findpwd(s);
zsfree(s); zsfree(s);
@ -1039,17 +1050,20 @@ printdirstack(void)
} }
/* Normalise a path. Segments consisting of ., and foo/.. * /* Normalise a path. Segments consisting of ., and foo/.. *
* combinations, are removed and the path is unmetafied. */ * combinations, are removed and the path is unmetafied.
* Returns 1 if we found a ../ path which should force links to
* be chased, 0 otherwise.
*/
/**/ /**/
static void int
fixdir(char *src) fixdir(char *src)
{ {
char *dest = src; char *dest = src, *d0 = dest;
char *d0 = dest; #ifdef __CYGWIN
#ifdef __CYGWIN__
char *s0 = src; char *s0 = src;
#endif #endif
int ret = 0;
/*** if have RFS superroot directory ***/ /*** if have RFS superroot directory ***/
#ifdef HAVE_SUPERROOT #ifdef HAVE_SUPERROOT
@ -1081,19 +1095,40 @@ fixdir(char *src)
while (dest > d0 + 1 && dest[-1] == '/') while (dest > d0 + 1 && dest[-1] == '/')
dest--; dest--;
*dest = '\0'; *dest = '\0';
return; return ret;
} }
if (src[0] == '.' && src[1] == '.' && if (src[0] == '.' && src[1] == '.' &&
(src[2] == '\0' || src[2] == '/')) { (src[2] == '\0' || src[2] == '/')) {
if (dest > d0 + 1) { if (isset(CHASEDOTS)) {
/* remove a foo/.. combination */ ret = 1;
for (dest--; dest > d0 + 1 && dest[-1] != '/'; dest--); /* and treat as normal path segment */
if (dest[-1] != '/') } else {
dest--; if (dest > d0 + 1) {
/*
* remove a foo/.. combination:
* first check foo exists, else return.
*/
struct stat st;
*dest = '\0';
if (stat(d0, &st) < 0 || !S_ISDIR(st.st_mode)) {
char *ptrd, *ptrs;
if (dest == src)
*dest = '.';
for (ptrs = src, ptrd = dest; *ptrs; ptrs++, ptrd++)
*ptrd = (*ptrs == Meta) ? (*++ptrs ^ 32) : *ptrs;
*ptrd = '\0';
return 1;
}
for (dest--; dest > d0 + 1 && dest[-1] != '/'; dest--);
if (dest[-1] != '/')
dest--;
}
src++;
while (*++src == '/');
continue;
} }
src++; }
while (*++src == '/'); if (src[0] == '.' && (src[1] == '/' || src[1] == '\0')) {
} else if (src[0] == '.' && (src[1] == '/' || src[1] == '\0')) {
/* skip a . section */ /* skip a . section */
while (*++src == '/'); while (*++src == '/');
} else { } else {
@ -3249,12 +3284,11 @@ bin_read(char *name, char **args, char *ops, int func)
nchars = 1; nchars = 1;
args++; args++;
} }
/* This `*args++ : *args' looks a bit weird, but it works around a bug
firstarg = *args; * in gcc-2.8.1 under DU 4.0. */
if (*args && **args == '?') firstarg = (*args && **args == '?' ? *args++ : *args);
args++;
/* default result parameter */
reply = *args ? *args++ : ops['A'] ? "reply" : "REPLY"; reply = *args ? *args++ : ops['A'] ? "reply" : "REPLY";
if (ops['A'] && *args) { if (ops['A'] && *args) {
zwarnnam(name, "only one array argument allowed", NULL, 0); zwarnnam(name, "only one array argument allowed", NULL, 0);
return 1; return 1;

View file

@ -3144,9 +3144,24 @@ static int
cancd2(char *s) cancd2(char *s)
{ {
struct stat buf; struct stat buf;
char *us = unmeta(s); char *us, *us2 = NULL;
/*
* If CHASEDOTS and CHASELINKS are not set, we want to rationalize the
* path by removing foo/.. combinations in the logical rather than
* the physical path. If either is set, we test the physical path.
*/
if (!isset(CHASEDOTS) && !isset(CHASELINKS)) {
if (*s != '/')
us = tricat(pwd[1] ? pwd : "", "/", s);
else
us = ztrdup(s);
fixdir(us2 = us);
} else
us = unmeta(s);
return !(access(us, X_OK) || stat(us, &buf) || !S_ISDIR(buf.st_mode)); return !(access(us, X_OK) || stat(us, &buf) || !S_ISDIR(buf.st_mode));
if (us2)
free(us2);
} }
/**/ /**/

View file

@ -2724,6 +2724,9 @@ charmatch(Comp c, char *x, char *y)
* Here we bypass tulower() and tuupper() for speed. * Here we bypass tulower() and tuupper() for speed.
*/ */
int xi = (STOUC(UNMETA(x)) & 0xff), yi = (STOUC(UNMETA(y)) & 0xff); int xi = (STOUC(UNMETA(x)) & 0xff), yi = (STOUC(UNMETA(y)) & 0xff);
/* A NULL is a real null, since a \000 would be metafied. */
if (!*x || !*y)
return 0;
return xi == yi || return xi == yi ||
(((c->stat & C_IGNCASE) ? (((c->stat & C_IGNCASE) ?
((isupper(xi) ? tolower(xi) : xi) == ((isupper(xi) ? tolower(xi) : xi) ==
@ -2926,7 +2929,10 @@ rangematch(char **patptr, int ch, int rchar)
* and optional ^ have already been skipped. */ * and optional ^ have already been skipped. */
char *pat = *patptr; char *pat = *patptr;
#ifdef HAVE_STRCOLL /* We don't use strcoll() for ranges, since it can have side
* effects. It's less necessary now we have [:posix:] ranges.
*/
#if 0
char l_buf[2], r_buf[2], ch_buf[2]; char l_buf[2], r_buf[2], ch_buf[2];
ch_buf[0] = ch; ch_buf[0] = ch;
@ -2944,7 +2950,7 @@ rangematch(char **patptr, int ch, int rchar)
break; break;
} else if (*pat == '-' && pat[-1] != rchar && } else if (*pat == '-' && pat[-1] != rchar &&
pat[1] != Outbrack) { pat[1] != Outbrack) {
#ifdef HAVE_STRCOLL #if 0
l_buf[0] = PPAT(-1); l_buf[0] = PPAT(-1);
r_buf[0] = PAT(1); r_buf[0] = PAT(1);
if (strcoll(l_buf, ch_buf) <= 0 && if (strcoll(l_buf, ch_buf) <= 0 &&

View file

@ -241,6 +241,7 @@ lexsave(void)
cmdsp = 0; cmdsp = 0;
inredir = 0; inredir = 0;
hdocs = NULL; hdocs = NULL;
histactive = 0;
ls->next = lstack; ls->next = lstack;
lstack = ls; lstack = ls;

View file

@ -91,6 +91,7 @@ static struct optname optns[] = {
{NULL, "braceccl", 0, BRACECCL}, {NULL, "braceccl", 0, BRACECCL},
{NULL, "bsdecho", OPT_EMULATE|OPT_SH, BSDECHO}, {NULL, "bsdecho", OPT_EMULATE|OPT_SH, BSDECHO},
{NULL, "cdablevars", 0, CDABLEVARS}, {NULL, "cdablevars", 0, CDABLEVARS},
{NULL, "chasedots", 0, CHASEDOTS},
{NULL, "chaselinks", 0, CHASELINKS}, {NULL, "chaselinks", 0, CHASELINKS},
{NULL, "clobber", OPT_ALL, CLOBBER}, {NULL, "clobber", OPT_ALL, CLOBBER},
{NULL, "completealiases", 0, COMPLETEALIASES}, {NULL, "completealiases", 0, COMPLETEALIASES},

View file

@ -72,7 +72,13 @@ struct list dummy_list;
#define YYERROR { tok = LEXERR; return NULL; } #define YYERROR { tok = LEXERR; return NULL; }
#define YYERRORV { tok = LEXERR; return; } #define YYERRORV { tok = LEXERR; return; }
#define COND_ERROR(X,Y) do{herrflush();zerr(X,Y,0);YYERROR}while(0) #define COND_ERROR(X,Y) do { \
zwarn(X,Y,0); \
herrflush(); \
if (noerrs != 2) \
errflag = 1; \
YYERROR \
} while(0)
#define make_list() allocnode(N_LIST) #define make_list() allocnode(N_LIST)
#define make_sublist() allocnode(N_SUBLIST) #define make_sublist() allocnode(N_SUBLIST)
@ -140,11 +146,13 @@ par_event(void)
} }
if (!l) { if (!l) {
if (errflag) { if (errflag) {
yyerror(); yyerror(0);
return NULL; return NULL;
} }
yyerror(1);
herrflush(); herrflush();
yyerror(); if (noerrs != 2)
errflag = 1;
return NULL; return NULL;
} else { } else {
l->right = par_event(); l->right = par_event();
@ -163,7 +171,7 @@ parse_list(void)
yylex(); yylex();
ret = par_list(); ret = par_list();
if (tok == LEXERR) { if (tok == LEXERR) {
yyerror(); yyerror(0);
return NULL; return NULL;
} }
return ret; return ret;
@ -1480,7 +1488,7 @@ par_cond_multi(char *a, LinkList l)
/**/ /**/
static void static void
yyerror(void) yyerror(int noerr)
{ {
int t0; int t0;
@ -1488,9 +1496,11 @@ yyerror(void)
if (!yytext || !yytext[t0] || yytext[t0] == '\n') if (!yytext || !yytext[t0] || yytext[t0] == '\n')
break; break;
if (t0 == 20) if (t0 == 20)
zerr("parse error near `%l...'", yytext, 20); zwarn("parse error near `%l...'", yytext, 20);
else if (t0) else if (t0)
zerr("parse error near `%l'", yytext, t0); zwarn("parse error near `%l'", yytext, t0);
else else
zerr("parse error", NULL, 0); zwarn("parse error", NULL, 0);
if (!noerr && noerrs != 2)
errflag = 1;
} }

View file

@ -30,23 +30,12 @@
#include "zsh.mdh" #include "zsh.mdh"
#include "utils.pro" #include "utils.pro"
/* Print an error */
/**/
void
zwarnnam(const char *cmd, const char *fmt, const char *str, int num)
{
int waserr;
waserr = errflag;
zerrnam(cmd, fmt, str, num);
errflag = waserr;
}
/* name of script being sourced */ /* name of script being sourced */
/**/ /**/
char *scriptname; char *scriptname;
/* Print an error */
/**/ /**/
void void
@ -57,7 +46,27 @@ zerr(const char *fmt, const char *str, int num)
errflag = 1; errflag = 1;
return; return;
} }
zwarn(fmt, str, num);
errflag = 1; errflag = 1;
}
/**/
void
zerrnam(const char *cmd, const char *fmt, const char *str, int num)
{
if (errflag || noerrs)
return;
zwarnnam(cmd, fmt, str, num);
errflag = 1;
}
/**/
void
zwarn(const char *fmt, const char *str, int num)
{
if (errflag || noerrs)
return;
trashzle(); trashzle();
/* /*
* scriptname is set when sourcing scripts, so that we get the * scriptname is set when sourcing scripts, so that we get the
@ -68,25 +77,29 @@ zerr(const char *fmt, const char *str, int num)
nicezputs((isset(SHINSTDIN) && !locallevel) ? "zsh" : nicezputs((isset(SHINSTDIN) && !locallevel) ? "zsh" :
scriptname ? scriptname : argzero, stderr); scriptname ? scriptname : argzero, stderr);
fputs(": ", stderr); fputs(": ", stderr);
zerrnam(NULL, fmt, str, num); zerrmsg(fmt, str, num);
} }
/**/ /**/
void void
zerrnam(const char *cmd, const char *fmt, const char *str, int num) zwarnnam(const char *cmd, const char *fmt, const char *str, int num)
{ {
if (cmd) { if (errflag || noerrs)
if (errflag || noerrs) return;
return; trashzle();
errflag = 1; if (unset(SHINSTDIN) || locallevel) {
trashzle(); nicezputs(scriptname ? scriptname : argzero, stderr);
if (unset(SHINSTDIN) || locallevel) {
nicezputs(scriptname ? scriptname : argzero, stderr);
fputs(": ", stderr);
}
nicezputs(cmd, stderr);
fputs(": ", stderr); fputs(": ", stderr);
} }
nicezputs(cmd, stderr);
fputs(": ", stderr);
zerrmsg(fmt, str, num);
}
/**/
void
zerrmsg(const char *fmt, const char *str, int num)
{
while (*fmt) while (*fmt)
if (*fmt == '%') { if (*fmt == '%') {
fmt++; fmt++;
@ -302,7 +315,7 @@ slashsplit(char *s)
/**/ /**/
static int static int
xsymlinks(char *s, int flag) xsymlinks(char *s)
{ {
char **pp, **opp; char **pp, **opp;
char xbuf2[PATH_MAX*2], xbuf3[PATH_MAX*2]; char xbuf2[PATH_MAX*2], xbuf3[PATH_MAX*2];
@ -325,15 +338,9 @@ xsymlinks(char *s, int flag)
*p = '\0'; *p = '\0';
continue; continue;
} }
if (unset(CHASELINKS)) {
strcat(xbuf, "/");
strcat(xbuf, *pp);
zsfree(*pp);
continue;
}
sprintf(xbuf2, "%s/%s", xbuf, *pp); sprintf(xbuf2, "%s/%s", xbuf, *pp);
t0 = readlink(unmeta(xbuf2), xbuf3, PATH_MAX); t0 = readlink(unmeta(xbuf2), xbuf3, PATH_MAX);
if (t0 == -1 || !flag) { if (t0 == -1) {
strcat(xbuf, "/"); strcat(xbuf, "/");
strcat(xbuf, *pp); strcat(xbuf, *pp);
zsfree(*pp); zsfree(*pp);
@ -342,9 +349,9 @@ xsymlinks(char *s, int flag)
metafy(xbuf3, t0, META_NOALLOC); metafy(xbuf3, t0, META_NOALLOC);
if (*xbuf3 == '/') { if (*xbuf3 == '/') {
strcpy(xbuf, ""); strcpy(xbuf, "");
xsymlinks(xbuf3 + 1, flag); xsymlinks(xbuf3 + 1);
} else } else
xsymlinks(xbuf3, flag); xsymlinks(xbuf3);
zsfree(*pp); zsfree(*pp);
} }
} }
@ -352,19 +359,19 @@ xsymlinks(char *s, int flag)
return ret; return ret;
} }
/* expand symlinks in s, and remove other weird things */ /*
* expand symlinks in s, and remove other weird things:
* note that this always expands symlinks.
*/
/**/ /**/
char * char *
xsymlink(char *s) xsymlink(char *s)
{ {
if (unset(CHASELINKS))
return ztrdup(s);
if (*s != '/') if (*s != '/')
return NULL; return NULL;
*xbuf = '\0'; *xbuf = '\0';
if (!xsymlinks(s + 1, 1)) xsymlinks(s + 1);
return ztrdup(s);
if (!*xbuf) if (!*xbuf)
return ztrdup("/"); return ztrdup("/");
return ztrdup(xbuf); return ztrdup(xbuf);
@ -374,15 +381,10 @@ xsymlink(char *s)
void void
print_if_link(char *s) print_if_link(char *s)
{ {
int chase;
if (*s == '/') { if (*s == '/') {
chase = opts[CHASELINKS];
opts[CHASELINKS] = 1;
*xbuf = '\0'; *xbuf = '\0';
if (xsymlinks(s + 1, 1)) if (xsymlinks(s + 1))
printf(" -> "), zputs(*xbuf ? xbuf : "/", stdout); printf(" -> "), zputs(*xbuf ? xbuf : "/", stdout);
opts[CHASELINKS] = chase;
} }
} }
@ -573,7 +575,8 @@ getnameddir(char *name)
/* Retrieve an entry from the password table/database for this user. */ /* Retrieve an entry from the password table/database for this user. */
struct passwd *pw; struct passwd *pw;
if ((pw = getpwnam(name))) { if ((pw = getpwnam(name))) {
char *dir = xsymlink(pw->pw_dir); char *dir = isset(CHASELINKS) ? xsymlink(pw->pw_dir)
: ztrdup(pw->pw_dir);
adduserdir(name, dir, ND_USERNAME, 1); adduserdir(name, dir, ND_USERNAME, 1);
str = dupstring(dir); str = dupstring(dir);
zsfree(dir); zsfree(dir);
@ -3202,7 +3205,7 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
int meta = 0, control = 0; int meta = 0, control = 0;
if (fromwhere == 6) if (fromwhere == 6)
t = tmp; t = buf = tmp;
else if (fromwhere != 4) else if (fromwhere != 4)
t = buf = zhalloc(strlen(s) + 1); t = buf = zhalloc(strlen(s) + 1);
else { else {

View file

@ -1171,6 +1171,7 @@ enum {
BRACECCL, BRACECCL,
BSDECHO, BSDECHO,
CDABLEVARS, CDABLEVARS,
CHASEDOTS,
CHASELINKS, CHASELINKS,
CLOBBER, CLOBBER,
COMPLETEALIASES, COMPLETEALIASES,

View file

@ -100,7 +100,7 @@ fi])
dnl Do you want large file support, if available? dnl Do you want large file support, if available?
undefine([lfs])dnl undefine([lfs])dnl
AC_ARG_ENABLE(lfs, AC_ARG_ENABLE(lfs,
[ --enable-lfs turn on support for large files], [ --disable-lfs turn off support for large files],
[lfs="$enableval"], [lfs=yes]) [lfs="$enableval"], [lfs=yes])
dnl Pathnames for global zsh scripts dnl Pathnames for global zsh scripts
@ -183,7 +183,7 @@ AC_SUBST(zlogout)dnl
dnl Do you want dynamically loaded binary modules. dnl Do you want dynamically loaded binary modules.
undefine([dynamic])dnl undefine([dynamic])dnl
AC_ARG_ENABLE(dynamic, AC_ARG_ENABLE(dynamic,
[ --enable-dynamic allow dynamically loaded binary modules], [ --disable-dynamic turn off dynamically loaded binary modules],
[dynamic="$enableval"], [dynamic=yes]) [dynamic="$enableval"], [dynamic=yes])
dnl Do you want to compile as K&R C. dnl Do you want to compile as K&R C.
@ -599,7 +599,7 @@ main() { return sizeof(ino_t) < 8; }
if test $lfs != no -o $zsh_cv_off_t_is_64_bit = yes \ if test $lfs != no -o $zsh_cv_off_t_is_64_bit = yes \
-o $zsh_cv_ino_t_is_64_bit = yes; then -o $zsh_cv_ino_t_is_64_bit = yes; then
AC_CACHE_CHECK(if compiler has a 64 bit type, zsh_cv_64_bit_type, AC_CACHE_CHECK(if compiler has a 64 bit type, zsh_cv_64_bit_type,
[if test $lfs != xyes -a $lfs != xno; then [if test $lfs != yes -a $lfs != no; then
zsh_64_BIT_TYPE(${lfs}, zsh_cv_64_bit_type, force) zsh_64_BIT_TYPE(${lfs}, zsh_cv_64_bit_type, force)
else else
zsh_64_BIT_TYPE(long long, zsh_cv_64_bit_type) zsh_64_BIT_TYPE(long long, zsh_cv_64_bit_type)