mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-06-14 08:08:10 +02:00
zsh-3.1.5-pws-6
This commit is contained in:
parent
20d67907c9
commit
7a40d6c258
30 changed files with 1793 additions and 844 deletions
Config
Doc
Functions
INSTALLMakefile.inMisc
Src
configure.inpatchlist.txt
|
@ -27,5 +27,5 @@
|
|||
# This must also serve as a shell script, so do not add spaces around the
|
||||
# `=' signs.
|
||||
|
||||
VERSION=3.1.5-pws-5
|
||||
VERSION_DATE='January 19, 1998'
|
||||
VERSION=3.1.5-pws-6
|
||||
VERSION_DATE='January 28, 1998'
|
||||
|
|
|
@ -112,11 +112,11 @@ version.yo: $(sdir_top)/Config/version.mk
|
|||
|
||||
# ========== DEPENDENCIES FOR INSTALLING ==========
|
||||
|
||||
# install all the documentation
|
||||
install: install.man install.info
|
||||
# install just installs the manual pages
|
||||
install: install.man
|
||||
|
||||
# uninstall all the documentation
|
||||
uninstall: uninstall.man uninstall.info
|
||||
# uninstall just unistalls the manual pages
|
||||
uninstall: uninstall.man
|
||||
|
||||
# install man pages, creating install directory if necessary
|
||||
install.man: $(MAN)
|
||||
|
@ -141,6 +141,9 @@ install.info: zsh.info
|
|||
else :; \
|
||||
fi || exit 1; \
|
||||
done
|
||||
if $(SHELL) -c 'install-info --version' >/dev/null 2>&1; then \
|
||||
install-info --dir-file=$(infodir)/dir $(infodir)/zsh.info; \
|
||||
else true; fi
|
||||
|
||||
install.html: zsh_toc.html
|
||||
$(sdir_top)/mkinstalldirs $(htmldir)
|
||||
|
|
|
@ -878,7 +878,10 @@ Equivalent to tt(whence -v).
|
|||
findex(typeset)
|
||||
cindex(parameters, setting)
|
||||
cindex(parameters, declaring)
|
||||
item(tt(typeset) [ {tt(PLUS())|tt(-)}tt(ALRUZafilrtuxm) [var(n)]] [ var(name)[tt(=)var(value)] ... ])(
|
||||
xitem(tt(typeset) [ {tt(PLUS())|tt(-)}tt(ALRUZafilrtuxm) [var(n)]] [ \
|
||||
var(name)[tt(=)var(value)] ... ])
|
||||
item(tt(typeset) -T [ {tt(PLUS()|tt(-))}tt(LRUZrux) ] \
|
||||
var(SCALAR)[tt(=)var(value)] var(array))(
|
||||
Set or display attributes and values for shell parameters.
|
||||
|
||||
A parameter is created for each var(name) that does not already refer
|
||||
|
@ -891,7 +894,7 @@ ifnzman(noderef(Local Parameters))\
|
|||
which case the parameter is exported em(only) when var(name) does not
|
||||
already appear in the environment.
|
||||
|
||||
For each nofill(var(name)tt(=)var(value)) assignment, the parameter
|
||||
For each var(name)tt(=)var(value) assignment, the parameter
|
||||
var(name) set to var(value). Note that arrays currently cannot be
|
||||
assigned in tt(typeset) expressions; scalars and integers only.
|
||||
|
||||
|
@ -899,6 +902,19 @@ For each remaining var(name) that refers to a parameter that is set,
|
|||
the name and value of the parameter are printed in the form of an
|
||||
assignment. Nothing is printed for newly-created parameters.
|
||||
|
||||
If the tt(-T) option is given, exactly two (or zero) var(name)
|
||||
arguments must be present. They represent a scalar and an array (in
|
||||
that order) that will be tied together in the manner of tt($PATH) and
|
||||
tt($path). In other words, an array present in the latter variable
|
||||
appears as a scalar with the elements of the array joined by colons in
|
||||
the former. Only the scalar may have an initial value. Both the
|
||||
scalar and the array may otherwise be manipulated as normal. If one
|
||||
is unset, the other will automatically be unset too. There is no way
|
||||
of untying the variables without unsetting them, or converting the
|
||||
type of one them with another tt(typeset) command; tt(+T) does not work,
|
||||
assigning an array to var(SCALAR) is an error, and assigning a scalar
|
||||
to var(array) sets it to be a single-element array.
|
||||
|
||||
If no var(name) is present, the names and values of all parameters are
|
||||
printed. In this case the attribute flags restrict the the display to
|
||||
only those parameters that have the specified attributes. Using
|
||||
|
|
108
Doc/Zsh/expn.yo
108
Doc/Zsh/expn.yo
|
@ -602,6 +602,46 @@ item(tt(f))(
|
|||
Split the result of the expansion to lines. This is a shorthand
|
||||
for `tt(ps:\n:)'.
|
||||
)
|
||||
item(tt(t))(
|
||||
Don't work on the value of the parameter, but on a string describing
|
||||
the type of the parameter. This string consists of keywords separated
|
||||
by hyphens (`tt(-)'). The first keyword in the string describes the
|
||||
main type, it can be one of `tt(scalar)', `tt(array)', `tt(integer)',
|
||||
or `tt(association)'. The other keywords describe the type in more
|
||||
detail:
|
||||
|
||||
startitem()
|
||||
item(`tt(left)')(
|
||||
for left justified parameters
|
||||
)
|
||||
item(`tt(right_blanks)')(
|
||||
for right justified parameters with leading blanks
|
||||
)
|
||||
item(`tt(right_zeros)')(
|
||||
for right justified parameters with leading zeros
|
||||
)
|
||||
item(`tt(lower)')(
|
||||
for parameters whose value is converted to all lower case when it is
|
||||
expanded
|
||||
)
|
||||
item(`tt(upper)')(
|
||||
for parameters whose value is converted to all upper case when it is
|
||||
expanded
|
||||
)
|
||||
item(`tt(readonly)')(
|
||||
for readonly parameters
|
||||
)
|
||||
item(`tt(tag)')(
|
||||
for tagged parameters
|
||||
)
|
||||
item(`tt(export)')(
|
||||
for exported parameters
|
||||
)
|
||||
item(`tt(unique)')(
|
||||
for arrays which keep only the first occurrence of duplicated values
|
||||
)
|
||||
enditem()
|
||||
)
|
||||
enditem()
|
||||
|
||||
The following flags are meaningful with the tt(${)...tt(#)...tt(}),
|
||||
|
@ -1048,6 +1088,49 @@ setgid files (02000)
|
|||
item(tt(t))(
|
||||
files with the sticky bit (01000)
|
||||
)
|
||||
item(tt(o)var(spec))(
|
||||
files with access rights matching var(spec). This var(spec) may be a
|
||||
octal number optionally preceded by a `tt(=)', a `tt(PLUS())', or a
|
||||
`tt(-)'. If none of these characters is given, the behavior is the
|
||||
same as for `tt(=)'. The octal number decribes the mode bits to be
|
||||
expected, if combined with a `tt(=)', the value given must match the
|
||||
file-modes exactly, with a `tt(PLUS())', at least the bits in the
|
||||
given number must be set in the file-modes, and with a `tt(-)', the
|
||||
bits in the number must not be set. Giving a `tt(?)' instead of a
|
||||
octal digit anywhere in the number ensures that the corresponding bits
|
||||
inthe file-modes are not checked, this is only useful in combination
|
||||
with `tt(=)'.
|
||||
|
||||
If the qualifier `tt(o)' is followed by any other character anything
|
||||
up to the next matching character (`tt([)', `tt({)', and `tt(<)' match
|
||||
`tt(])', `tt(})', and `tt(>)' respectively, any other character
|
||||
matches itself) is taken as a list of comma-separated
|
||||
var(sub-spec)s. Each var(sub-spec) may be either a octal number as
|
||||
described above or a list of any of the characters `tt(u)', `tt(g)',
|
||||
`tt(o)', and `tt(a)', followed by a `tt(=)', a `tt(PLUS())', or a
|
||||
`tt(-)', followed by a list of any of the characters `tt(r)', `tt(w)',
|
||||
`tt(x)', `tt(s)', and `tt(t)', or a octal digit. The first list of
|
||||
characters specify which acess rights are to be checked. If a `tt(u)'
|
||||
is given, those for the owner of the file are used, if a `tt(g)' is
|
||||
given, those of the group are checked, a `tt(o)' means to test those
|
||||
of other users, and the `tt(a)' says to test all three groups. The
|
||||
`tt(=)', `tt(PLUS())', and `tt(-)' again says how the modes are to be
|
||||
checked and have the same meaning as described for the first form
|
||||
above. The second list of characters finally says which access rights
|
||||
are to be expected: `tt(r)' for read access, `tt(w)' for write access,
|
||||
`tt(x)' for the right to execute the file (or to search a directory),
|
||||
`tt(s)' for the setuid and setgid bits, and `tt(t)' for the sticky
|
||||
bit.
|
||||
|
||||
Thus, `tt(*(o70?))' gives the files for which the owner has read,
|
||||
write, and execute permission, and for which other group members have
|
||||
no rights, independent of the permissions for other user. The pattern
|
||||
`tt(*(o-100))' gives all files for which the owner does not have
|
||||
execute permission, and `tt(*(o:gu+w,o-rx))' gives the files for which
|
||||
the owner and the other members of the group have at least write
|
||||
permission, and fo which other users don't have read or execute
|
||||
permission.
|
||||
)
|
||||
item(tt(d)var(dev))(
|
||||
files on the device var(dev)
|
||||
)
|
||||
|
@ -1065,8 +1148,8 @@ item(tt(u)var(id))(
|
|||
files owned by user ID var(id) if it is a number, if not, than the
|
||||
character after the `tt(u)' will be used as a separator and the string
|
||||
between it and the next matching separator
|
||||
(`tt(LPAR())', `tt([)', `tt({)', and `tt(<)'
|
||||
match `tt(RPAR())', `tt(])', `tt(})', and `tt(>)' respectively,
|
||||
(`tt([)', `tt({)', and `tt(<)'
|
||||
match `tt(])', `tt(})', and `tt(>)' respectively,
|
||||
any other character matches
|
||||
itself) will be taken as a user name, and the user ID of this user will
|
||||
be taken (e.g. `tt(u:foo:)' or `tt(u[foo])' for user `tt(foo)')
|
||||
|
@ -1122,6 +1205,27 @@ item(tt(D))(
|
|||
sets the tt(GLOB_DOTS) option for the current pattern
|
||||
pindex(GLOB_DOTS, setting in pattern)
|
||||
)
|
||||
item(tt(O)var(c))(
|
||||
specifies how the names of the files should be sorted. If var(c) is
|
||||
tt(n) they are sorted by name (the default), if var(c) is tt(L) they
|
||||
are sorted depending on the size (length) of the files, tt(l) makes
|
||||
them be sorted by the number of links, and tt(a), tt(m), and tt(c)
|
||||
make them be sorted by the time of the last access, modification, and
|
||||
inode change respectively. Note that tt(a), tt(m), and tt(c) compare
|
||||
the age to the current time, so the first name in the list is the
|
||||
one of the youngest file. Also note that the modifiers tt(^) and tt(-) are
|
||||
used, so `tt(*(^-OL))' gives a list of all files sorted by file size in
|
||||
descending order working not on symbolic links but on the files they
|
||||
point to.
|
||||
)
|
||||
item(tt([)var(beg)[tt(,)var(end)]tt(]))(
|
||||
specifies which of the matched filenames should be included in the
|
||||
returned list. The syntax is the same as for array
|
||||
subscripts. var(beg) and the optional var(end) may be mathematical
|
||||
expressions. As in parameter subscripting they may be negative to make
|
||||
them count from the last match backward. E.g.: `tt(*(^-OL[1,3]))'
|
||||
gives a list of the names of three biggest files.
|
||||
)
|
||||
enditem()
|
||||
|
||||
More than one of these lists can be combined, separated by commas. The
|
||||
|
|
|
@ -57,6 +57,12 @@ def(texinfo)(2)(\
|
|||
NOTRANS(@iftex)NL()\
|
||||
NOTRANS(@set dsq '{}')NL()\
|
||||
NOTRANS(@end iftex)NL()\
|
||||
NOTRANS(@ifinfo)NL()\
|
||||
NOTRANS(@dircategory Utilities)NL()\
|
||||
NOTRANS(@direntry)NL()\
|
||||
NOTRANS( * ZSH: (zsh). The Z Shell Guide.)NL()\
|
||||
NOTRANS(@end direntry)NL()\
|
||||
NOTRANS(@end ifinfo)NL()\
|
||||
)
|
||||
|
||||
def(texiifinfo)(1)(\
|
||||
|
|
37
Functions/zless
Normal file
37
Functions/zless
Normal file
|
@ -0,0 +1,37 @@
|
|||
#!/usr/bin/zsh -f
|
||||
#
|
||||
# zsh function script to run less on various inputs, decompressing as required.
|
||||
# Author: Phil Pennock. zsh-hacks@athenaeum.demon.co.uk
|
||||
# Modified by Bart Schaefer.
|
||||
# Thanks to zefram@fysh.org for a great deal of help in sorting this out,
|
||||
# ie wrt syntax for unsetting members of arrays and eval "$(...)" when I
|
||||
# asked for something better than . =(...)
|
||||
#
|
||||
# Use -zforce to pass through a display-formatting command
|
||||
# zless -zforce 'bzip2 -dc' foo-no-dotbz2
|
||||
# zless -zforce 'od -hc' foo-binfile
|
||||
#
|
||||
# If you can understand all of this without reference to zshexpn(1)
|
||||
# and zshparam(1) then you either have a photographic memory or you
|
||||
# need to get out more.
|
||||
#
|
||||
|
||||
emulate -R zsh
|
||||
setopt localoptions
|
||||
|
||||
[[ $# -ge 1 ]] || return
|
||||
local lessopts
|
||||
set -A lessopts
|
||||
integer i=1 loi=1
|
||||
while ((i <= $#))
|
||||
do
|
||||
case $argv[i] in
|
||||
-zforce) argv[i,i+2]=("=($argv[i+1] \"$argv[i+2]\")"); ((++i));;
|
||||
-*) lessopts[loi++]=\"$argv[i]\"; argv[i]=(); continue;;
|
||||
*.(gz|Z)) argv[i]="=(zcat \"$argv[i]\")";;
|
||||
*.bz2) argv[i]="=(bzip2 -dc \"$argv[i]\")";;
|
||||
*.bz) argv[i]="=(bzip -dc \"$argv[i]\")";;
|
||||
esac
|
||||
((++i))
|
||||
done
|
||||
eval command less $lessopts $*
|
|
@ -6,12 +6,13 @@ zmodload -i stat || return 1
|
|||
emulate -R zsh
|
||||
setopt localoptions
|
||||
|
||||
local f stat opts='' L=L mod=: dirs list
|
||||
local f opts='' L=L mod=: dirs list
|
||||
typeset -A stat
|
||||
|
||||
dirs=()
|
||||
list=()
|
||||
|
||||
while getopts ailLFd f
|
||||
while getopts ailLFdtuc f
|
||||
do
|
||||
opts=$opts$f
|
||||
if [[ $f == '?' ]] then
|
||||
|
@ -25,24 +26,40 @@ shift OPTIND-1
|
|||
[[ $opts == *F* ]] && mod=T$mod
|
||||
[[ $opts == *a* ]] && setopt globdots
|
||||
|
||||
local time=mtime tmod=m
|
||||
[[ $opts == *u* ]] && time=atime tmod=a
|
||||
[[ $opts == *c* ]] && time=ctime tmod=c
|
||||
|
||||
if ((! ARGC)) then
|
||||
set *
|
||||
if [[ $opts = *t* ]]; then
|
||||
set *(O$tmod)
|
||||
else
|
||||
set *
|
||||
fi
|
||||
opts=d$opts
|
||||
elif [[ $opts = *t* && $ARGC -gt 1 ]]; then
|
||||
# another glaringly obvious zsh trick: reorder the argv list
|
||||
# by time, without messing up metacharacters inside
|
||||
local n='$1'
|
||||
for (( f = 2; f <= $ARGC; f++ )); do
|
||||
n="$n|\$$f"
|
||||
done
|
||||
eval "argv=(($n)(O$tmod))"
|
||||
fi
|
||||
|
||||
for f in $*
|
||||
do
|
||||
stat -s$L -A stat -F "%b %e %H:%M" - $f || continue
|
||||
if [[ $opts != *d* && $stat[3] == d* ]] then
|
||||
stat -s$L -H stat -F "%b %e %H:%M" - $f || continue
|
||||
if [[ $opts != *d* && $stat[mode] == d* ]] then
|
||||
dirs=( $dirs $f )
|
||||
elif [[ $opts == *l* ]] then
|
||||
[[ $opts == *i* ]] && print -n "${(l:7:)stat[2]} "
|
||||
[[ -n $stat[14] ]] && f=( $f '->' $stat[14] ) || f=( $f($mod) )
|
||||
print -r -- "$stat[3] ${(l:3:)stat[4]} ${(r:8:)stat[5]} " \
|
||||
"${(r:8:)stat[6]} ${(l:8:)stat[8]} $stat[10] $f"
|
||||
[[ $opts == *i* ]] && print -n "${(l:7:)stat[inode]} "
|
||||
[[ -n $stat[link] ]] && f=( $f '->' $stat[link] ) || f=( $f($mod) )
|
||||
print -r -- "$stat[mode] ${(l:3:)stat[nlink]} ${(r:8:)stat[uid]} " \
|
||||
"${(r:8:)stat[gid]} ${(l:8:)stat[size]} $stat[$time] $f"
|
||||
else
|
||||
f=( $f($mod) )
|
||||
list=( "$list[@]" "${${(M)opts:%*i*}:+${(l:7:)stat[2]} }$f" )
|
||||
list=( "$list[@]" "${${(M)opts:%*i*}:+${(l:7:)stat[inode]} }$f" )
|
||||
fi
|
||||
done
|
||||
(($#list)) && print -cr -- "$list[@]"
|
||||
|
|
15
INSTALL
15
INSTALL
|
@ -114,15 +114,18 @@ To install the dynamically-loadable modules, do the command:
|
|||
To install the zsh man page, do the command:
|
||||
make install.man
|
||||
|
||||
To install the zsh info files, do the command:
|
||||
make install.info
|
||||
|
||||
Or alternatively, you can install all the above with the command:
|
||||
make install
|
||||
|
||||
"make install.info" will only move the info files into the info directory.
|
||||
You will have to edit the topmost node of the info tree "dir" manually
|
||||
in order to have the zsh info files available to your info reader.
|
||||
To install the zsh info files (this must be done separately), do the
|
||||
command:
|
||||
make install.info
|
||||
|
||||
If the programme install-info is available, "make install.info" will
|
||||
insert an entry in the file "dir" in the same directory as the info
|
||||
files. Otherwise you will have to edit the topmost node of the info
|
||||
tree "dir" manually in order to have the zsh info files available to
|
||||
your info reader.
|
||||
|
||||
Building Zsh On Additional Architectures
|
||||
----------------------------------------
|
||||
|
|
|
@ -55,9 +55,9 @@ META-FAQ: FORCE
|
|||
install-strip:
|
||||
$(MAKE) install STRIPFLAGS="-s"
|
||||
|
||||
# install/uninstall everything
|
||||
install: install.bin install.modules install.man install.info
|
||||
uninstall: uninstall.bin uninstall.modules uninstall.man uninstall.info
|
||||
# install/uninstall everything (except info)
|
||||
install: install.bin install.modules install.man
|
||||
uninstall: uninstall.bin uninstall.modules uninstall.man
|
||||
|
||||
# install/uninstall just the binary
|
||||
install.bin uninstall.bin:
|
||||
|
|
|
@ -19,21 +19,31 @@ typeset -A comps
|
|||
# With only one argument the function/variable-name __$1 is used.
|
||||
|
||||
defcomp() {
|
||||
local v
|
||||
local v a=''
|
||||
|
||||
if [[ "$1" = -a ]] then
|
||||
shift
|
||||
a=yes
|
||||
fi
|
||||
if [[ $# -eq 1 ]] then
|
||||
comps[$1]="__$1"
|
||||
[[ -z "$a" ]] || autoload "__$1"
|
||||
else
|
||||
v="$1"
|
||||
shift
|
||||
for i; do
|
||||
comps[$i]="$v"
|
||||
done
|
||||
[[ -z "$a" ]] || autoload "$v"
|
||||
fi
|
||||
}
|
||||
|
||||
defpatcomp() {
|
||||
if [[ ${+patcomps} == 1 ]] then
|
||||
if [[ "$1" = -a ]] then
|
||||
shift
|
||||
autoload "$1"
|
||||
fi
|
||||
if (( $+patcomps )) then
|
||||
patcomps=("$patcomps[@]" "$2 $1" )
|
||||
else
|
||||
patcomps=( "$2 $1" )
|
||||
|
@ -68,10 +78,10 @@ call-complete() {
|
|||
local var
|
||||
|
||||
eval var\=\$\{\+$1\}
|
||||
if [[ "$var" == 0 ]] then
|
||||
"$@"
|
||||
else
|
||||
if (( var )); then
|
||||
eval complist \$\{${1}\[\@\]\}
|
||||
else
|
||||
"$@"
|
||||
fi
|
||||
}
|
||||
|
||||
|
@ -80,11 +90,21 @@ call-complete() {
|
|||
# arguments from the command line are gives as positional parameters.
|
||||
|
||||
main-complete() {
|
||||
emulate -R zsh
|
||||
# emulate -R zsh
|
||||
local comp
|
||||
|
||||
setopt localoptions nullglob rcexpandparam globdots
|
||||
unsetopt markdirs globsubst shwordsplit nounset
|
||||
|
||||
# We first try the `compctl's. This is without first (-T) and default (-D)
|
||||
# completion. If you want them add `-T' and/or `-D' to this command.
|
||||
# If this produces any matches, we don't try new style completion. If you
|
||||
# want to have that tried anyway, remove the `[[ -nmatches ... ]] ...'
|
||||
# below.
|
||||
|
||||
compcall
|
||||
[[ -nmatches 0 ]] || return
|
||||
|
||||
# An entry for `--first--' is the replacement for `compctl -T'
|
||||
# The `|| return 1' is used throughout: if a function producing matches
|
||||
# returns non-zero this is interpreted as `do not try to produce more matches'
|
||||
|
@ -164,21 +184,6 @@ do-complete() {
|
|||
[[ -z "$comp" ]] || call-complete "$comp" "$@" || return 1
|
||||
}
|
||||
|
||||
# Do sub-completion for pre-command modifiers.
|
||||
|
||||
defcomp __precmd - noglob nocorrect exec command builtin
|
||||
__precmd() {
|
||||
COMMAND="$1"
|
||||
shift
|
||||
(( CURRENT-- ))
|
||||
if [[ CURRENT -eq 0 ]] then
|
||||
CONTEXT=command
|
||||
else
|
||||
CONTEXT=argument
|
||||
fi
|
||||
compsub
|
||||
}
|
||||
|
||||
# Utility function for in-path completion.
|
||||
# First argument should be an complist-option (e.g. -f, -/, -g). The other
|
||||
# arguments should be glob patterns, one per argument.
|
||||
|
@ -190,90 +195,123 @@ __precmd() {
|
|||
# so you may want to modify this.
|
||||
|
||||
pfiles() {
|
||||
local nm str pa pre epre a b c s rest
|
||||
local nm ostr opa pre epre a b c s rest ppres
|
||||
|
||||
setopt localoptions nullglob rcexpandparam globdots extendedglob
|
||||
unsetopt markdirs globsubst shwordsplit nounset
|
||||
|
||||
if [[ "$1" = -W ]] then
|
||||
a="$2"
|
||||
if [[ "$a[1]" = '(' ]] then
|
||||
ppres=( $a[2,-2]/ )
|
||||
else
|
||||
eval ppres\=\( \$$a/ \)
|
||||
[[ $#ppres -eq 0 ]] && ppres=( $a/ )
|
||||
fi
|
||||
[[ $#ppres -eq 0 ]] && ppres=( '' )
|
||||
shift 2
|
||||
else
|
||||
ppres=( '' )
|
||||
fi
|
||||
|
||||
str="$PREFIX*$SUFFIX"
|
||||
|
||||
if [[ -z "$a[1]" || "$str[1]" = [~/] || "$str" = (.|..)/* ]] then
|
||||
a=()
|
||||
else
|
||||
a=(-W "( $ppres )")
|
||||
fi
|
||||
nm=$NMATCHES
|
||||
if [[ $# -eq 0 ]] then
|
||||
complist -f
|
||||
complist "$a[@]" -f
|
||||
elif [[ "$1" = -g ]] then
|
||||
complist -g "$argv[2,-1]"
|
||||
complist "$a[@]" -g "$argv[2,-1]"
|
||||
shift
|
||||
else
|
||||
complist $1
|
||||
complist "$a[@]" $1
|
||||
shift
|
||||
fi
|
||||
[[ -nmatches nm ]] || return
|
||||
|
||||
str="$PREFIX*$SUFFIX"
|
||||
|
||||
[[ -z "$1" ]] && 1='*'
|
||||
if [[ $str[1] = \~ ]] then
|
||||
|
||||
if [[ "$str[1]" = \~ ]] then
|
||||
pre="${str%%/*}/"
|
||||
eval epre\=$pre
|
||||
str="${str#*/}"
|
||||
pa=''
|
||||
opa=''
|
||||
ppres=( '' )
|
||||
else
|
||||
pre=''
|
||||
epre=''
|
||||
if [[ $str[1] = / ]] then
|
||||
if [[ "$str[1]" = / ]] then
|
||||
str="$str[2,-1]"
|
||||
pa='/'
|
||||
opa='/'
|
||||
ppres=( '' )
|
||||
else
|
||||
pa=''
|
||||
[[ "$str" = (.|..)/* ]] && ppres=( '' )
|
||||
opa=''
|
||||
fi
|
||||
fi
|
||||
str="$str:gs/,/*,/:gs/_/*_/:gs./.*/.:gs/-/*[-_]/:gs/./*[.,]/:gs-*[.,]*[.,]*/-../-:gs.**.*."
|
||||
while [[ "$str" = */* ]] do
|
||||
rest="${str#*/}"
|
||||
a="${epre}${pa}(#l)${str%%/*}(-/)"
|
||||
a=( $~a )
|
||||
if [[ $#a -eq 0 ]] then
|
||||
return
|
||||
elif [[ $#a -gt 1 ]] then
|
||||
c=()
|
||||
s=( $rest$@ )
|
||||
s=( "${(@)s:gs.**.*.}" )
|
||||
for i in $a; do
|
||||
b=( $~i/(#l)$~s )
|
||||
eval b\=\( \$\{b:/\*\(${(j:|:)fignore}\)\} \)
|
||||
[[ $#b -ne 0 ]] && c=( $c $i )
|
||||
done
|
||||
if [[ $#c -eq 0 ]] then
|
||||
return
|
||||
elif [[ $#c -ne 1 ]] then
|
||||
a="$epre$pa"
|
||||
c=( $~c/(#l)$~s )
|
||||
eval c\=\( \$\{c:/\*\(${(j:|:)fignore}\)\} \)
|
||||
c=( ${c#$a} )
|
||||
for i in $c; do
|
||||
compadd -p "$pre$pa" -W "$a" -s "/${i#*/}" -f "${i%%/*}"
|
||||
done
|
||||
return
|
||||
fi
|
||||
a=( "$c[1]" )
|
||||
fi
|
||||
a="$a[1]"
|
||||
pa="$pa${a##*/}/"
|
||||
str="$rest"
|
||||
[[ -e "$epre$opa${str%%/*}" ]] || break
|
||||
opa="$opa${str%%/*}/"
|
||||
str="${str#*/}"
|
||||
done
|
||||
|
||||
ostr="$str:gs/,/*,/:gs/_/*_/:gs./.*/.:gs/-/*[-_]/:gs/./*[.,]/:gs-*[.,]*[.,]*/-../-:gs.**.*."
|
||||
|
||||
for ppre in "$ppres[@]"; do
|
||||
str="$ostr"
|
||||
pa="$opa"
|
||||
while [[ "$str" = */* ]] do
|
||||
rest="${str#*/}"
|
||||
a="${ppre}${epre}${pa}(#l)${str%%/*}(-/)"
|
||||
a=( $~a )
|
||||
if [[ $#a -eq 0 ]] then
|
||||
continue 2
|
||||
elif [[ $#a -gt 1 ]] then
|
||||
c=()
|
||||
s=( $rest$@ )
|
||||
s=( "${(@)s:gs.**.*.}" )
|
||||
for i in $a; do
|
||||
b=( $~i/(#l)$~s )
|
||||
eval b\=\( \$\{b:/\*\(${(j:|:)fignore}\)\} \)
|
||||
[[ $#b -ne 0 ]] && c=( $c $i )
|
||||
done
|
||||
if [[ $#c -eq 0 ]] then
|
||||
continue 2
|
||||
elif [[ $#c -ne 1 ]] then
|
||||
a="$ppre$epre$pa"
|
||||
c=( $~c/(#l)$~s )
|
||||
eval c\=\( \$\{c:/\*\(${(j:|:)fignore}\)\} \)
|
||||
c=( ${c#$a} )
|
||||
for i in $c; do
|
||||
compadd -p "$pre$pa" -W "$a" -s "/${i#*/}" -f "${i%%/*}"
|
||||
done
|
||||
continue 2
|
||||
fi
|
||||
a=( "$c[1]" )
|
||||
fi
|
||||
a="$a[1]"
|
||||
pa="$pa${a##*/}/"
|
||||
str="$rest"
|
||||
done
|
||||
a="$ppre$epre$pa"
|
||||
s=( $str$@ )
|
||||
s=( "${(@)s:gs.**.*.}" )
|
||||
b=( $~a(#l)$~s )
|
||||
eval b\=\( \$\{b:/\*\(${(j:|:)fignore}\)\} \)
|
||||
compadd -p "$pre$pa" -W "$ppre$epre$pa" -f ${b#$a}
|
||||
done
|
||||
a="$epre$pa"
|
||||
s=( $str$@ )
|
||||
s=( "${(@)s:gs.**.*.}" )
|
||||
b=( $~a(#l)$~s )
|
||||
eval b\=\( \$\{b:/\*\(${(j:|:)fignore}\)\} \)
|
||||
compadd -p "$pre$pa" -W "$epre$pa" -f ${b#$a}
|
||||
}
|
||||
|
||||
# Utility function for completing files of a given type or any file.
|
||||
# In many cases you will want to call this one instead of pfiles().
|
||||
|
||||
files() {
|
||||
local nm
|
||||
local nm=$NMATCHES
|
||||
|
||||
nm=$NMATCHES
|
||||
pfiles "$@"
|
||||
|
||||
[[ $# -ne 0 && -nmatches nm ]] && pfiles
|
||||
|
@ -289,23 +327,318 @@ __default() {
|
|||
defcomp __command --command--
|
||||
__command=( -c )
|
||||
|
||||
defcomp __math --math--
|
||||
__math=( -v )
|
||||
defcomp __vars --math--
|
||||
__vars=( -v )
|
||||
|
||||
defcomp __subscr --subscr--
|
||||
__subscr() {
|
||||
local t
|
||||
|
||||
eval t\=\$\{\(t\)$COMMAND\}
|
||||
compalso --math-- "$@"
|
||||
# ...probably other stuff
|
||||
[[ $t = assoc* ]] && eval complist -k \"\(\$\{\(k\)$COMMAND\}\)\"
|
||||
}
|
||||
|
||||
# A simple pattern completion, just as an example.
|
||||
# Do sub-completion for pre-command modifiers.
|
||||
|
||||
defpatcomp __x_options '*/X11/*'
|
||||
__x_options() {
|
||||
complist -J options -k '(-display -name -xrm)'
|
||||
defcomp __precmd - nohup nice eval time rusage noglob nocorrect exec
|
||||
__precmd() {
|
||||
COMMAND="$1"
|
||||
shift
|
||||
(( CURRENT-- ))
|
||||
if [[ CURRENT -eq 0 ]] then
|
||||
CONTEXT=command
|
||||
else
|
||||
CONTEXT=argument
|
||||
fi
|
||||
compsub
|
||||
}
|
||||
|
||||
# A better example: completion for `find'.
|
||||
defcomp builtin
|
||||
__builtin() {
|
||||
if [[ -position 2 -1 ]] then
|
||||
compsub
|
||||
else
|
||||
complist -eB
|
||||
fi
|
||||
}
|
||||
|
||||
defcomp command
|
||||
__command() {
|
||||
if [[ -position 2 -1 ]] then
|
||||
compsub
|
||||
else
|
||||
complist -em
|
||||
fi
|
||||
}
|
||||
|
||||
# Various completions...
|
||||
|
||||
defcomp __jobs fg jobs
|
||||
__jobs=(-j -P '%')
|
||||
|
||||
defcomp __bjobs bg
|
||||
__bjobs=(-z -P '%')
|
||||
|
||||
defcomp __arrays shift
|
||||
__arrays=(-A)
|
||||
|
||||
defcomp __which which whence where type
|
||||
__which=( -caF )
|
||||
|
||||
defcomp unhash
|
||||
__unhash() {
|
||||
[[ -mword 1 -*d* ]] && complist -n
|
||||
[[ -mword 1 -*a* ]] && complist -a
|
||||
[[ -mword 1 -*f* ]] && complist -F
|
||||
[[ ! -mword 1 -* ]] && complist -m
|
||||
}
|
||||
|
||||
defcomp hash
|
||||
__hash() {
|
||||
if [[ -mword 1 -*d* ]] then
|
||||
if [[ -string 1 '=' ]] then
|
||||
pfiles -g '*(-/)'
|
||||
else
|
||||
complist -n -q -S '='
|
||||
fi
|
||||
elif [[ -string 1 '=' ]] then
|
||||
files -g '*(*)' '*(-/)'
|
||||
else
|
||||
complist -m -q -S '='
|
||||
fi
|
||||
}
|
||||
|
||||
defcomp __funcs unfunction
|
||||
__funcs=(-F)
|
||||
|
||||
defcomp echotc
|
||||
__echotc=(-k '(al dc dl do le up al bl cd ce cl cr dc dl do ho is le ma nd nl se so up)')
|
||||
|
||||
defcomp __aliases unalias
|
||||
__aliases=(-a)
|
||||
|
||||
defcomp __vars getopts read unset vared
|
||||
|
||||
defcomp __varseq declare export integer local readonly typeset
|
||||
__varseq=(-v -S '=')
|
||||
|
||||
defcomp disable
|
||||
__disable() {
|
||||
[[ -mcurrent -1 -*a* ]] && complist -ea
|
||||
[[ -mcurrent -1 -*f* ]] && complist -eF
|
||||
[[ -mcurrent -1 -*r* ]] && complist -ew
|
||||
[[ ! -mcurrent -1 -* ]] && complist -eB
|
||||
}
|
||||
|
||||
defcomp enable
|
||||
__enable() {
|
||||
[[ -mcurrent -1 -*a* ]] && complist -da
|
||||
[[ -mcurrent -1 -*f* ]] && complist -dF
|
||||
[[ -mcurrent -1 -*r* ]] && complist -dw
|
||||
[[ ! -mcurrent -1 -* ]] && complist -dB
|
||||
}
|
||||
|
||||
defcomp __limits limit unlimit
|
||||
__limits=(-k "(${(j: :)${(f)$(limit)}%% *})")
|
||||
|
||||
defcomp source
|
||||
__source() {
|
||||
if [[ -position 2 -1 ]] then
|
||||
compsub
|
||||
else
|
||||
files
|
||||
fi
|
||||
}
|
||||
|
||||
defcomp setopt
|
||||
__setopt() {
|
||||
local nm=$NMATCHES
|
||||
|
||||
complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \
|
||||
-s '$({ unsetopt kshoptionprint; unsetopt } 2>/dev/null)'
|
||||
[[ -nmatches nm ]] && complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o
|
||||
}
|
||||
|
||||
defcomp unsetopt
|
||||
__unsetopt() {
|
||||
local nm=$NMATCHES
|
||||
|
||||
complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' \
|
||||
-s '$({ unsetopt kshoptionprint; setopt } 2>/dev/null)'
|
||||
[[ -nmatches nm ]] && complist -M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o
|
||||
}
|
||||
|
||||
defcomp autoload
|
||||
__autoload=(-s '${^fpath}/*(N:t)')
|
||||
|
||||
defcomp bindkey
|
||||
__bindkey() {
|
||||
if [[ -mword 1 -*[DAN]* || -mcurrent -1 -*M ]] then
|
||||
complist -s '$(bindkey -l)'
|
||||
else
|
||||
complist -b
|
||||
fi
|
||||
}
|
||||
|
||||
defcomp fc
|
||||
__fc() {
|
||||
if [[ -mcurrent -1 -*e ]] then
|
||||
complist -c
|
||||
elif [[ -mcurrent -1 -[ARWI]## ]] then
|
||||
files
|
||||
fi
|
||||
}
|
||||
|
||||
defcomp sched
|
||||
__sched() {
|
||||
[[ -position 2 -1 ]] && compsub
|
||||
}
|
||||
|
||||
defcomp set
|
||||
__set() {
|
||||
if [[ -mcurrent -1 [-+]o ]] then
|
||||
complist -o
|
||||
elif [[ -current -1 -A ]] then
|
||||
complist -A
|
||||
fi
|
||||
}
|
||||
|
||||
defcomp zle
|
||||
__zle() {
|
||||
if [[ -word 1 -N && -position 3 ]] then
|
||||
complist -F
|
||||
else
|
||||
complist -b
|
||||
fi
|
||||
}
|
||||
|
||||
defcomp zmodload
|
||||
__zmodload() {
|
||||
if [[ -mword 1 -*(a*u|u*a)* || -mword 1 -*a* && -position 3 -1 ]] then
|
||||
complist -B
|
||||
elif [[ -mword 1 -*u* ]] then
|
||||
complist -s '$(zmodload)'
|
||||
else
|
||||
complist -s '${^module_path}/*(N:t:r)'
|
||||
fi
|
||||
}
|
||||
|
||||
defcomp trap
|
||||
__trap() {
|
||||
if [[ -position 1 ]] then
|
||||
complist -c
|
||||
else
|
||||
complist -k signals
|
||||
fi
|
||||
}
|
||||
|
||||
killfunc() {
|
||||
reply=( "$(ps -x 2>/dev/null)" )
|
||||
}
|
||||
|
||||
defcomp kill
|
||||
__kill() {
|
||||
if [[ -iprefix '-' ]] then
|
||||
complist -k "($signals[1,-3])"
|
||||
else
|
||||
complist -P '%' -j
|
||||
complist -y killfunc -s '`ps -x 2>/dev/null | tail +2 | cut -c1-5`'
|
||||
fi
|
||||
}
|
||||
|
||||
defcomp wait
|
||||
__wait() {
|
||||
complist -P '%' -j
|
||||
complist -y killfunc -s '`ps -x 2>/dev/null | tail +2 | cut -c1-5`'
|
||||
}
|
||||
|
||||
defcomp cd
|
||||
__cd() {
|
||||
files -W cdpath -g '*(-/)'
|
||||
}
|
||||
|
||||
defcomp __rlogin rlogin rsh ssh
|
||||
__rlogin() {
|
||||
if [[ -position 1 ]] then
|
||||
complist -k hosts
|
||||
elif [[ -position 2 ]] then
|
||||
complist -k '(-l)'
|
||||
elif [[ -position 3 && -word 1 artus ]] then
|
||||
complist -k '(puck root)'
|
||||
fi
|
||||
}
|
||||
|
||||
defcomp __gunzip gunzip zcat
|
||||
__gunzip() {
|
||||
files -g '*.[gG][z]'
|
||||
}
|
||||
|
||||
defcomp gzip
|
||||
__gzip() {
|
||||
files -g '*~*.[gG][zZ]'
|
||||
}
|
||||
|
||||
defcomp xfig
|
||||
__xfig() {
|
||||
files -g '*.fig'
|
||||
}
|
||||
|
||||
defcomp __make make gmake pmake
|
||||
__make() {
|
||||
complist -s "\$(awk '/^[a-zA-Z0-9][^/ ]+:/ {print \$1}' FS=: [mM]akefile)"
|
||||
}
|
||||
|
||||
defcomp __ps gs ghostview gview psnup psselect pswrap pstops pstruct lpr
|
||||
__ps() {
|
||||
files -g '*([pP][sS]|eps)'
|
||||
}
|
||||
|
||||
defcomp __dvi xdvi dvips dvibook dviconcat dvicopy dvidvi dviselect dvitodvi dvitype
|
||||
__dvi() {
|
||||
files -g '*.(dvi|DVI)'
|
||||
}
|
||||
|
||||
defcomp __dirs rmdir df du dircmp
|
||||
__dirs() {
|
||||
files -/ '*(-/)'
|
||||
}
|
||||
|
||||
defcomp __uncompress uncompress zmore
|
||||
__uncompress() {
|
||||
files -g '*.Z'
|
||||
}
|
||||
|
||||
defcomp compress
|
||||
__compress() {
|
||||
files -g '*~*.Z'
|
||||
}
|
||||
|
||||
defcomp __tex tex latex slitex
|
||||
__tex() {
|
||||
files -g '*.(tex|TEX|texinfo|texi)'
|
||||
}
|
||||
|
||||
defcomp __pdf acroread
|
||||
__pdf() {
|
||||
files -g '*.(pdf|PDF)'
|
||||
}
|
||||
|
||||
defcomp tar
|
||||
__tar() {
|
||||
local nm=$NMATCHES tf="$2"
|
||||
compsave
|
||||
|
||||
if [[ ( -mword 1 *t*f* || -mword 1 *x*f* ) && -position 3 100000 ]] then
|
||||
complist -k "( $(tar tf $tf) )"
|
||||
compreset
|
||||
elif [[ -mword 1 *c*f* && -position 3 100000 ]] then
|
||||
files
|
||||
compreset
|
||||
elif [[ -mcurrent -1 *f* && -position 2 ]] then
|
||||
files -g '*.(tar|TAR)'
|
||||
fi
|
||||
}
|
||||
|
||||
defcomp find
|
||||
__find() {
|
||||
|
@ -333,121 +666,9 @@ __find() {
|
|||
fi
|
||||
}
|
||||
|
||||
# Various completions...
|
||||
# A simple pattern completion, just as an example.
|
||||
|
||||
defcomp __gunzip gunzip zcat
|
||||
__gunzip() {
|
||||
files -g '*.[gG][z]'
|
||||
}
|
||||
|
||||
defcomp gzip
|
||||
__gzip() {
|
||||
files -g '*~*.[gG][zZ]'
|
||||
}
|
||||
|
||||
defcomp xfig
|
||||
__xfig() {
|
||||
files -g '*.fig'
|
||||
}
|
||||
|
||||
defcomp __make make gmake
|
||||
__make() {
|
||||
complist -s "\$(awk '/^[a-zA-Z0-9][^/ ]+:/ {print \$1}' FS=: [mM]akefile)"
|
||||
}
|
||||
|
||||
defcomp __ps gs ghostview gview psnup psselect pswrap pstops pstruct lpr
|
||||
__ps() {
|
||||
files -g '*([pP][sS]|eps)'
|
||||
}
|
||||
|
||||
defcomp __which which whence
|
||||
__which=( -caF )
|
||||
|
||||
defcomp __rlogin rlogin rsh ssh
|
||||
__rlogin() {
|
||||
if [[ -position 1 ]] then
|
||||
complist -k hosts
|
||||
elif [[ -position 2 ]] then
|
||||
complist -k '(-l)'
|
||||
elif [[ -position 3 && -word 1 artus ]] then
|
||||
complist -k '(puck root)'
|
||||
fi
|
||||
}
|
||||
|
||||
defcomp __dvi xdvi dvips dvibook dviconcat dvicopy dvidvi dviselect dvitodvi dvitype
|
||||
__dvi() {
|
||||
files -g '*.(dvi|DVI)'
|
||||
}
|
||||
|
||||
defcomp __dirs rmdir df du dircmp cd
|
||||
__dirs() {
|
||||
files -/ '*(-/)'
|
||||
}
|
||||
|
||||
defcomp __jobs fg bg jobs
|
||||
__jobs=(-j -P '%?')
|
||||
|
||||
defcomp kill
|
||||
__kill() {
|
||||
if [[ -iprefix '-' ]] then
|
||||
complist -k signals
|
||||
else
|
||||
complist -P '%?' -j
|
||||
fi
|
||||
}
|
||||
|
||||
defcomp __uncompress uncompress zmore
|
||||
__uncompress() {
|
||||
files -g '*.Z'
|
||||
}
|
||||
|
||||
defcomp compress
|
||||
__compress() {
|
||||
files -g '*~*.Z'
|
||||
}
|
||||
|
||||
defcomp __tex tex latex glatex slitex gslitex
|
||||
__tex() {
|
||||
files -g '*.(tex|TEX|texinfo|texi)'
|
||||
}
|
||||
|
||||
defcomp __options setopt unsetopt
|
||||
__options=(-M 'L:|[nN][oO]= M:_= M:{A-Z}={a-z}' -o)
|
||||
|
||||
defcomp __funcs unfunction
|
||||
__funcs=(-F)
|
||||
|
||||
defcomp __aliases unalias
|
||||
__aliases=(-a)
|
||||
|
||||
defcomp __vars unset
|
||||
__vars=(-v)
|
||||
|
||||
defcomp __enabled disable
|
||||
__enabled=(-FBwa)
|
||||
|
||||
defcomp __disabled enable
|
||||
__disabled=(-dFBwa)
|
||||
|
||||
defcomp __pdf acroread
|
||||
__pdf() {
|
||||
files -g '*.(pdf|PDF)'
|
||||
}
|
||||
|
||||
defcomp tar
|
||||
__tar() {
|
||||
local nm tf
|
||||
compsave
|
||||
|
||||
tf="$2"
|
||||
nm=$NMATCHES
|
||||
if [[ ( -mword 1 *t*f* || -mword 1 *x*f* ) && -position 3 100000 ]] then
|
||||
complist -k "( $(tar tf $tf) )"
|
||||
compreset
|
||||
elif [[ -mword 1 *c*f* && -position 3 100000 ]] then
|
||||
files
|
||||
compreset
|
||||
elif [[ -mcurrent -1 *f* && -position 2 ]] then
|
||||
files -g '*.(tar|TAR)'
|
||||
fi
|
||||
defpatcomp __x_options '*/X11/*'
|
||||
__x_options() {
|
||||
complist -J options -k '(-display -name -xrm)'
|
||||
}
|
||||
|
|
|
@ -267,3 +267,8 @@ struct cline {
|
|||
#define CLF_MISS 4
|
||||
#define CLF_DIFF 8
|
||||
#define CLF_SUF 16
|
||||
|
||||
/* Flags for makecomplist*(). Things not to do. */
|
||||
|
||||
#define CFN_FIRST 1
|
||||
#define CFN_DEFAULT 2
|
||||
|
|
|
@ -43,12 +43,6 @@ Cmlist cmatcher;
|
|||
|
||||
/* pointers to functions required by zle and defined by compctl */
|
||||
|
||||
/**/
|
||||
void (*printcompctlptr) _((char *, Compctl, int, int));
|
||||
|
||||
/**/
|
||||
Compctl (*compctl_widgetptr) _((char *, char **));
|
||||
|
||||
/**/
|
||||
void (*makecompparamsptr) _((void));
|
||||
|
||||
|
@ -66,6 +60,8 @@ int (*getcpatptr) _((char *, int, char *, int));
|
|||
/**/
|
||||
void (*makecomplistcallptr) _((Compctl));
|
||||
|
||||
/**/
|
||||
void (*makecomplistctlptr) _((int));
|
||||
|
||||
/* Hash table for completion info for commands */
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ clwsize
|
|||
cmatcher
|
||||
compcommand
|
||||
compcontext
|
||||
compctl_widgetptr
|
||||
compctltab
|
||||
compcurrent
|
||||
compiprefix
|
||||
|
@ -28,8 +27,8 @@ incompctlfunc
|
|||
incompfunc
|
||||
instring
|
||||
makecomplistcallptr
|
||||
makecomplistctlptr
|
||||
makecompparamsptr
|
||||
patcomps
|
||||
printcompctlptr
|
||||
quotename
|
||||
rembslash
|
||||
|
|
|
@ -1638,38 +1638,6 @@ bin_compctl(char *name, char **argv, char *ops, int func)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Externally callable version of get_compctl. Used for completion widgets */
|
||||
|
||||
/**/
|
||||
static Compctl
|
||||
compctl_widget(char *name, char **argv)
|
||||
{
|
||||
Compctl cc = (Compctl) zcalloc(sizeof(*cc));
|
||||
cclist = 0;
|
||||
showmask = 0;
|
||||
|
||||
if (get_compctl(name, &argv, cc, 1, 0, 0)) {
|
||||
freecompctl(cc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cclist & COMP_REMOVE) {
|
||||
zwarnnam(name, "use -D to delete widget", NULL, 0);
|
||||
return NULL;
|
||||
} else if (cclist) {
|
||||
zwarnnam(name, "special options illegal in widget", NULL, 0);
|
||||
freecompctl(cc);
|
||||
return NULL;
|
||||
} else if (*argv) {
|
||||
zwarnnam(name, "command names illegal in widget", NULL, 0);
|
||||
freecompctl(cc);
|
||||
return NULL;
|
||||
}
|
||||
cc->refc++;
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
bin_complist(char *name, char **argv, char *ops, int func)
|
||||
|
@ -1677,7 +1645,7 @@ bin_complist(char *name, char **argv, char *ops, int func)
|
|||
Compctl cc;
|
||||
int ret = 0;
|
||||
|
||||
if (!incompfunc) {
|
||||
if (incompfunc != 1) {
|
||||
zerrnam(name, "can only be called from completion function", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
@ -1706,7 +1674,7 @@ bin_compadd(char *name, char **argv, char *ops, int func)
|
|||
char *pre = NULL, *suf = NULL, *group = NULL;
|
||||
int f = 0, q = 0, m = 0, ns = 0, a = 0;
|
||||
|
||||
if (!incompfunc) {
|
||||
if (incompfunc != 1) {
|
||||
zerrnam(name, "can only be called from completion function", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
@ -1792,15 +1760,27 @@ bin_compadd(char *name, char **argv, char *ops, int func)
|
|||
}
|
||||
}
|
||||
ca_args:
|
||||
if (!*argv) {
|
||||
zerrnam(name, "missing completions", NULL, 0);
|
||||
if (!*argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
addmatchesptr(ipre, ppre, psuf, prpre, pre, suf, group,
|
||||
f, q, m, ns, a, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
bin_compcall(char *name, char **argv, char *ops, int func)
|
||||
{
|
||||
if (incompfunc != 1) {
|
||||
zerrnam(name, "can only be called from completion function", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
makecomplistctlptr((ops['T'] ? 0 : CFN_FIRST) |
|
||||
(ops['D'] ? 0 : CFN_DEFAULT));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define VAR(X) ((void *) (&(X)))
|
||||
static struct compparam {
|
||||
char *name;
|
||||
|
@ -1823,7 +1803,7 @@ void makecompparams(void)
|
|||
struct compparam *cp;
|
||||
|
||||
for (cp = compparams; cp->name; cp++) {
|
||||
Param pm = createparam(cp->name, cp->type | PM_SPECIAL);
|
||||
Param pm = createparam(cp->name, cp->type | PM_SPECIAL|PM_REMOVABLE);
|
||||
if (!pm)
|
||||
pm = (Param) paramtab->getnode(paramtab, cp->name);
|
||||
DPUTS(!pm, "param not set in makecompparams");
|
||||
|
@ -1856,7 +1836,7 @@ compunsetfn(Param pm, int exp)
|
|||
static int
|
||||
comp_wrapper(List list, FuncWrap w, char *name)
|
||||
{
|
||||
if (!incompfunc)
|
||||
if (incompfunc != 1)
|
||||
return 1;
|
||||
else {
|
||||
char *octxt, *ocmd, *opre, *osuf, *oipre;
|
||||
|
@ -1907,7 +1887,7 @@ ignore_prefix(int l)
|
|||
static int
|
||||
comp_check(void)
|
||||
{
|
||||
if (!incompfunc) {
|
||||
if (incompfunc != 1) {
|
||||
zerr("condition can only be used in completion function", NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
@ -2119,7 +2099,8 @@ cond_nmatches(char **a, int id)
|
|||
static struct builtin bintab[] = {
|
||||
BUILTIN("compctl", 0, bin_compctl, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("complist", 0, bin_complist, 1, -1, 0, NULL, NULL),
|
||||
BUILTIN("compadd", 0, bin_compadd, 1, -1, 0, NULL, NULL),
|
||||
BUILTIN("compadd", 0, bin_compadd, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("compcall", 0, bin_compcall, 0, 0, 0, "TD", NULL),
|
||||
};
|
||||
|
||||
static struct conddef cotab[] = {
|
||||
|
@ -2149,8 +2130,6 @@ int
|
|||
setup_compctl(Module m)
|
||||
{
|
||||
compctltab->printnode = printcompctlp;
|
||||
printcompctlptr = printcompctl;
|
||||
compctl_widgetptr = compctl_widget;
|
||||
makecompparamsptr = makecompparams;
|
||||
return 0;
|
||||
}
|
||||
|
@ -2183,8 +2162,6 @@ int
|
|||
finish_compctl(Module m)
|
||||
{
|
||||
compctltab->printnode = NULL;
|
||||
printcompctlptr = NULL;
|
||||
compctl_widgetptr = NULL;
|
||||
makecompparamsptr = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
"capitalize-word", capitalizeword, 0
|
||||
"clear-screen", clearscreen, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_NOTCOMMAND
|
||||
"complete-word", completeword, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP
|
||||
"copy-prev-word", copyprevword, 0
|
||||
"copy-prev-word", copyprevword, ZLE_KEEPSUFFIX
|
||||
"copy-region-as-kill", copyregionaskill, ZLE_KEEPSUFFIX
|
||||
"delete-char", deletechar, ZLE_KEEPSUFFIX
|
||||
"delete-char-or-list", deletecharorlist, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP
|
||||
|
|
|
@ -46,7 +46,6 @@ struct widget {
|
|||
union {
|
||||
ZleIntFunc fn; /* pointer to internally implemented widget */
|
||||
char *fnnam; /* name of the shell function for user-defined widget */
|
||||
Compctl cc; /* for use with a WIDGET_COMP widget */
|
||||
struct {
|
||||
ZleIntFunc fn; /* internal widget function to call */
|
||||
char *wid; /* name of widget to call */
|
||||
|
@ -56,20 +55,15 @@ struct widget {
|
|||
};
|
||||
|
||||
#define WIDGET_INT (1<<0) /* widget is internally implemented */
|
||||
#define WIDGET_COMP (1<<1) /* Special completion widget */
|
||||
#define WIDGET_NCOMP (1<<2) /* new style completion widget */
|
||||
#define ZLE_MENUCMP (1<<3) /* DON'T invalidate completion list */
|
||||
#define ZLE_YANK (1<<4)
|
||||
#define ZLE_LINEMOVE (1<<5) /* command is a line-oriented movement */
|
||||
#define ZLE_LASTCOL (1<<6) /* command maintains lastcol correctly */
|
||||
#define ZLE_KILL (1<<7)
|
||||
#define ZLE_KEEPSUFFIX (1<<9) /* DON'T remove added suffix */
|
||||
#define ZLE_USEMENU (1<<10) /* Do ) use menu completion for */
|
||||
#define ZLE_NOMENU (1<<11) /* Don't ) widget, else use default */
|
||||
#define ZLE_USEGLOB (1<<12) /* Do ) use glob completion for */
|
||||
#define ZLE_NOGLOB (1<<13) /* Don't ) widget, else use default */
|
||||
#define ZLE_NOTCOMMAND (1<<14) /* widget should not alter lastcmd */
|
||||
#define ZLE_ISCOMP (1<<15) /* usable for new style completion */
|
||||
#define WIDGET_NCOMP (1<<1) /* new style completion widget */
|
||||
#define ZLE_MENUCMP (1<<2) /* DON'T invalidate completion list */
|
||||
#define ZLE_YANK (1<<3)
|
||||
#define ZLE_LINEMOVE (1<<4) /* command is a line-oriented movement */
|
||||
#define ZLE_LASTCOL (1<<5) /* command maintains lastcol correctly */
|
||||
#define ZLE_KILL (1<<6)
|
||||
#define ZLE_KEEPSUFFIX (1<<7) /* DON'T remove added suffix */
|
||||
#define ZLE_NOTCOMMAND (1<<8) /* widget should not alter lastcmd */
|
||||
#define ZLE_ISCOMP (1<<9) /* usable for new style completion */
|
||||
/* thingies */
|
||||
|
||||
struct thingy {
|
||||
|
|
|
@ -45,10 +45,10 @@ int mark;
|
|||
/**/
|
||||
int c;
|
||||
|
||||
/* the binding for this key */
|
||||
/* the bindings for the previous and for this key */
|
||||
|
||||
/**/
|
||||
Thingy bindk;
|
||||
Thingy lbindk, bindk;
|
||||
|
||||
/* insert mode/overwrite mode flag */
|
||||
|
||||
|
@ -554,6 +554,7 @@ zleread(char *lp, char *rp, int ha)
|
|||
void
|
||||
execzlefunc(Thingy func)
|
||||
{
|
||||
int r = 0;
|
||||
Widget w;
|
||||
|
||||
if(func->flags & DISABLED) {
|
||||
|
@ -565,14 +566,13 @@ execzlefunc(Thingy func)
|
|||
showmsg(msg);
|
||||
zsfree(msg);
|
||||
feep();
|
||||
} else if((w = func->widget)->flags &
|
||||
(WIDGET_INT|WIDGET_COMP | WIDGET_NCOMP)) {
|
||||
} else if((w = func->widget)->flags & (WIDGET_INT|WIDGET_NCOMP)) {
|
||||
int wflags = w->flags;
|
||||
|
||||
if(!(wflags & ZLE_KEEPSUFFIX))
|
||||
removesuffix();
|
||||
if(!(wflags & ZLE_MENUCMP) ||
|
||||
((wflags & (WIDGET_COMP|WIDGET_NCOMP)) && compwidget != w)) {
|
||||
((wflags & WIDGET_NCOMP) && compwidget != w)) {
|
||||
/* If we are doing a special completion, and the widget
|
||||
* is not the one currently in use for special completion,
|
||||
* we are starting a new completion.
|
||||
|
@ -584,16 +584,14 @@ execzlefunc(Thingy func)
|
|||
vilinerange = 1;
|
||||
if(!(wflags & ZLE_LASTCOL))
|
||||
lastcol = -1;
|
||||
if (wflags & WIDGET_COMP) {
|
||||
compwidget = w;
|
||||
completespecial();
|
||||
} else if (wflags & WIDGET_NCOMP) {
|
||||
if (wflags & WIDGET_NCOMP) {
|
||||
compwidget = w;
|
||||
completecall();
|
||||
} else
|
||||
w->u.fn();
|
||||
if (!(wflags & ZLE_NOTCOMMAND))
|
||||
lastcmd = wflags;
|
||||
r = 1;
|
||||
} else {
|
||||
List l = getshfunc(w->u.fnnam);
|
||||
|
||||
|
@ -610,14 +608,20 @@ execzlefunc(Thingy func)
|
|||
int osc = sfcontext;
|
||||
|
||||
startparamscope();
|
||||
makezleparams();
|
||||
makezleparams(0);
|
||||
sfcontext = SFC_WIDGET;
|
||||
doshfunc(w->u.fnnam, l, NULL, 0, 1);
|
||||
sfcontext = osc;
|
||||
endparamscope();
|
||||
lastcmd = 0;
|
||||
r = 1;
|
||||
}
|
||||
}
|
||||
if (r) {
|
||||
unrefthingy(lbindk);
|
||||
refthingy(func);
|
||||
lbindk = func;
|
||||
}
|
||||
}
|
||||
|
||||
/* initialise command modifiers */
|
||||
|
@ -877,9 +881,11 @@ setup_zle(Module m)
|
|||
comp_strptr = comp_str;
|
||||
getcpatptr = getcpat;
|
||||
makecomplistcallptr = makecomplistcall;
|
||||
makecomplistctlptr = makecomplistctl;
|
||||
|
||||
/* initialise the thingies */
|
||||
init_thingies();
|
||||
lbindk = NULL;
|
||||
|
||||
/* miscellaneous initialisations */
|
||||
stackhist = stackcs = -1;
|
||||
|
@ -920,6 +926,8 @@ finish_zle(Module m)
|
|||
{
|
||||
int i;
|
||||
|
||||
unrefthingy(lbindk);
|
||||
|
||||
cleanup_keymaps();
|
||||
deletehashtable(thingytab);
|
||||
|
||||
|
@ -944,6 +952,7 @@ finish_zle(Module m)
|
|||
comp_strptr = NULL;
|
||||
getcpatptr = NULL;
|
||||
makecomplistcallptr = NULL;
|
||||
makecomplistctlptr = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -61,17 +61,22 @@ static struct zleparam {
|
|||
zleunsetfn, NULL },
|
||||
{ "RBUFFER", PM_SCALAR, FN(set_rbuffer), FN(get_rbuffer),
|
||||
zleunsetfn, NULL },
|
||||
{ "WIDGET", PM_SCALAR | PM_READONLY, NULL, FN(get_widget),
|
||||
zleunsetfn, NULL },
|
||||
{ "LASTWIDGET", PM_SCALAR | PM_READONLY, NULL, FN(get_lwidget),
|
||||
zleunsetfn, NULL },
|
||||
{ NULL, 0, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
/**/
|
||||
void
|
||||
makezleparams(void)
|
||||
makezleparams(int ro)
|
||||
{
|
||||
struct zleparam *zp;
|
||||
|
||||
for(zp = zleparams; zp->name; zp++) {
|
||||
Param pm = createparam(zp->name, zp->type | PM_SPECIAL);
|
||||
Param pm = createparam(zp->name, (zp->type |PM_SPECIAL|PM_REMOVABLE|
|
||||
(ro ? PM_READONLY : 0)));
|
||||
if (!pm)
|
||||
pm = (Param) paramtab->getnode(paramtab, zp->name);
|
||||
DPUTS(!pm, "param not set in makezleparams");
|
||||
|
@ -197,3 +202,17 @@ get_rbuffer(Param pm)
|
|||
{
|
||||
return metafy((char *)line + cs, ll - cs, META_HEAPDUP);
|
||||
}
|
||||
|
||||
/**/
|
||||
static char *
|
||||
get_widget(Param pm)
|
||||
{
|
||||
return bindk->nam;
|
||||
}
|
||||
|
||||
/**/
|
||||
static char *
|
||||
get_lwidget(Param pm)
|
||||
{
|
||||
return (lbindk ? lbindk->nam : "");
|
||||
}
|
||||
|
|
|
@ -244,9 +244,7 @@ unbindwidget(Thingy t, int override)
|
|||
static void
|
||||
freewidget(Widget w)
|
||||
{
|
||||
if ((w->flags & WIDGET_COMP) && w->u.cc)
|
||||
freecompctl(w->u.cc);
|
||||
else if (w->flags & WIDGET_NCOMP) {
|
||||
if (w->flags & WIDGET_NCOMP) {
|
||||
zsfree(w->u.comp.wid);
|
||||
zsfree(w->u.comp.func);
|
||||
} else if(!(w->flags & WIDGET_INT))
|
||||
|
@ -339,7 +337,7 @@ bin_zle(char *name, char **args, char *ops, int func)
|
|||
{ 'D', bin_zle_del, 1, -1 },
|
||||
{ 'A', bin_zle_link, 2, 2 },
|
||||
{ 'N', bin_zle_new, 1, 2 },
|
||||
{ 'C', bin_zle_compctl, 1, -1},
|
||||
{ 'C', bin_zle_complete, 3, 3 },
|
||||
{ 'c', bin_zle_complete, 3, 3 },
|
||||
{ 0, bin_zle_call, 0, -1 },
|
||||
};
|
||||
|
@ -392,14 +390,11 @@ scanlistwidgets(HashNode hn, int list)
|
|||
if(w->flags & WIDGET_INT)
|
||||
return;
|
||||
if(list) {
|
||||
fputs((w->flags & WIDGET_COMP) ? "zle -C " : "zle -N ", stdout);
|
||||
fputs("zle -N ", stdout);
|
||||
if(t->nam[0] == '-')
|
||||
fputs("-- ", stdout);
|
||||
quotedzputs(t->nam, stdout);
|
||||
if (w->flags & WIDGET_COMP) {
|
||||
if (printcompctlptr && w->u.cc)
|
||||
printcompctlptr(NULL, w->u.cc, PRINT_LIST, 0);
|
||||
} else if (w->flags & WIDGET_NCOMP) {
|
||||
if (w->flags & WIDGET_NCOMP) {
|
||||
fputc(' ', stdout);
|
||||
quotedzputs(w->u.comp.wid, stdout);
|
||||
fputc(' ', stdout);
|
||||
|
@ -410,11 +405,7 @@ scanlistwidgets(HashNode hn, int list)
|
|||
}
|
||||
} else {
|
||||
nicezputs(t->nam, stdout);
|
||||
if (w->flags & WIDGET_COMP) {
|
||||
fputs(" -C", stdout);
|
||||
if (printcompctlptr && w->u.cc)
|
||||
printcompctlptr(NULL, w->u.cc, PRINT_TYPE, 0);
|
||||
} else if (w->flags & WIDGET_NCOMP) {
|
||||
if (w->flags & WIDGET_NCOMP) {
|
||||
fputs(" -c ", stdout);
|
||||
nicezputs(w->u.comp.wid, stdout);
|
||||
fputc(' ', stdout);
|
||||
|
@ -480,44 +471,6 @@ bin_zle_new(char *name, char **args, char *ops, char func)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
bin_zle_compctl(char *name, char **args, char *ops, char func)
|
||||
{
|
||||
Compctl cc = NULL;
|
||||
Widget w;
|
||||
char *wname = args[0];
|
||||
|
||||
if (!compctl_widgetptr) {
|
||||
zwarnnam(name, "compctl module is not loaded", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
args++;
|
||||
|
||||
if (*args && !(cc = compctl_widgetptr(name, args)))
|
||||
return 1;
|
||||
|
||||
w = zalloc(sizeof(*w));
|
||||
w->flags = WIDGET_COMP|ZLE_MENUCMP|ZLE_KEEPSUFFIX;
|
||||
w->first = NULL;
|
||||
w->u.cc = cc;
|
||||
if(bindwidget(w, rthingy(wname))) {
|
||||
freewidget(w);
|
||||
zerrnam(name, "widget name `%s' is protected", wname, 0);
|
||||
return 1;
|
||||
}
|
||||
if (ops['m'])
|
||||
w->flags |= ZLE_USEMENU;
|
||||
else if (ops['M'])
|
||||
w->flags |= ZLE_NOMENU;
|
||||
if (ops['g'])
|
||||
w->flags |= ZLE_USEGLOB;
|
||||
else if (ops['G'])
|
||||
w->flags |= ZLE_NOGLOB;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
bin_zle_complete(char *name, char **args, char *ops, char func)
|
||||
|
|
File diff suppressed because it is too large
Load diff
132
Src/builtin.c
132
Src/builtin.c
|
@ -50,7 +50,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("cd", 0, bin_cd, 0, 2, BIN_CD, NULL, NULL),
|
||||
BUILTIN("chdir", 0, bin_cd, 0, 2, BIN_CD, NULL, NULL),
|
||||
BUILTIN("continue", BINF_PSPECIAL, bin_break, 0, 1, BIN_CONTINUE, NULL, NULL),
|
||||
BUILTIN("declare", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRUZafilrtux", NULL),
|
||||
BUILTIN("declare", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafilrtux", NULL),
|
||||
BUILTIN("dirs", 0, bin_dirs, 0, -1, 0, "v", NULL),
|
||||
BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmr", NULL),
|
||||
BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL),
|
||||
|
@ -60,7 +60,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmr", NULL),
|
||||
BUILTIN("eval", BINF_PSPECIAL, bin_eval, 0, -1, BIN_EVAL, NULL, NULL),
|
||||
BUILTIN("exit", BINF_PSPECIAL, bin_break, 0, 1, BIN_EXIT, NULL, NULL),
|
||||
BUILTIN("export", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, BIN_EXPORT, "LRUZafilrtu", "x"),
|
||||
BUILTIN("export", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, BIN_EXPORT, "LRTUZafilrtu", "x"),
|
||||
BUILTIN("false", 0, bin_false, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("fc", BINF_FCOPTS, bin_fc, 0, -1, BIN_FC, "nlreIRWAdDfEim", NULL),
|
||||
BUILTIN("fg", 0, bin_fg, 0, -1, BIN_FG, NULL, NULL),
|
||||
|
@ -78,7 +78,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("jobs", 0, bin_fg, 0, -1, BIN_JOBS, "dlpZrs", NULL),
|
||||
BUILTIN("kill", 0, bin_kill, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("let", 0, bin_let, 1, -1, 0, NULL, NULL),
|
||||
BUILTIN("local", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRUZailrtu", NULL),
|
||||
BUILTIN("local", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZailrtu", NULL),
|
||||
BUILTIN("log", 0, bin_log, 0, 0, 0, NULL, NULL),
|
||||
BUILTIN("logout", 0, bin_break, 0, 1, BIN_LOGOUT, NULL, NULL),
|
||||
|
||||
|
@ -93,7 +93,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("pwd", 0, bin_pwd, 0, 0, 0, "rLP", NULL),
|
||||
BUILTIN("r", BINF_R, bin_fc, 0, -1, BIN_FC, "nrl", NULL),
|
||||
BUILTIN("read", 0, bin_read, 0, -1, 0, "rzu0123456789pkqecnAlE", NULL),
|
||||
BUILTIN("readonly", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRUZafiltux", "r"),
|
||||
BUILTIN("readonly", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafiltux", "r"),
|
||||
BUILTIN("rehash", 0, bin_hash, 0, 0, 0, "dfv", "r"),
|
||||
BUILTIN("return", BINF_PSPECIAL, bin_break, 0, 1, BIN_RETURN, NULL, NULL),
|
||||
BUILTIN("set", BINF_PSPECIAL, bin_set, 0, -1, 0, NULL, NULL),
|
||||
|
@ -107,7 +107,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("trap", BINF_PSPECIAL, bin_trap, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("true", 0, bin_true, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("type", 0, bin_whence, 0, -1, 0, "ampfsw", "v"),
|
||||
BUILTIN("typeset", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRUZafilrtuxm", NULL),
|
||||
BUILTIN("typeset", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "ALRTUZafilrtuxm", NULL),
|
||||
BUILTIN("umask", 0, bin_umask, 0, 1, 0, "S", NULL),
|
||||
BUILTIN("unalias", 0, bin_unhash, 1, -1, 0, "m", "a"),
|
||||
BUILTIN("unfunction", 0, bin_unhash, 1, -1, 0, "m", "f"),
|
||||
|
@ -1468,11 +1468,11 @@ getasg(char *s)
|
|||
/* function to set a single parameter */
|
||||
|
||||
/**/
|
||||
int
|
||||
Param
|
||||
typeset_single(char *cname, char *pname, Param pm, int func,
|
||||
int on, int off, int roff, char *value)
|
||||
int on, int off, int roff, char *value, Param altpm)
|
||||
{
|
||||
int usepm, tc;
|
||||
int usepm, tc, keeplocal = 0;
|
||||
|
||||
/* use the existing pm? */
|
||||
usepm = pm && !(pm->flags & PM_UNSET);
|
||||
|
@ -1490,24 +1490,24 @@ typeset_single(char *cname, char *pname, Param pm, int func,
|
|||
locallevel != pm->level && func != BIN_EXPORT)
|
||||
usepm = 0;
|
||||
|
||||
/* attempting a type conversion? */
|
||||
/* attempting a type conversion, or making a tied colonarray? */
|
||||
if ((tc = usepm && (((off & pm->flags) | (on & ~pm->flags)) &
|
||||
(PM_INTEGER|PM_HASHED|PM_ARRAY))))
|
||||
(PM_INTEGER|PM_HASHED|PM_ARRAY|PM_TIED))))
|
||||
usepm = 0;
|
||||
if (tc && (pm->flags & PM_SPECIAL)) {
|
||||
zerrnam(cname, "%s: can't change type of a special parameter",
|
||||
pname, 0);
|
||||
return 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (usepm) {
|
||||
if (!on && !roff && !value) {
|
||||
paramtab->printnode((HashNode)pm, 0);
|
||||
return 0;
|
||||
return pm;
|
||||
}
|
||||
if ((pm->flags & PM_RESTRICTED && isset(RESTRICTED))) {
|
||||
zerrnam(cname, "%s: restricted", pname, 0);
|
||||
return 1;
|
||||
return pm;
|
||||
}
|
||||
if (PM_TYPE(pm->flags) == PM_ARRAY && (on & PM_UNIQUE) &&
|
||||
!(pm->flags & PM_READONLY & ~off))
|
||||
|
@ -1530,9 +1530,9 @@ typeset_single(char *cname, char *pname, Param pm, int func,
|
|||
setsparam(pname, ztrdup(value));
|
||||
} else if (value) {
|
||||
zwarnnam(cname, "can't assign new value for array %s", pname, 0);
|
||||
return 1;
|
||||
return NULL;
|
||||
}
|
||||
return 0;
|
||||
return pm;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1542,10 +1542,15 @@ typeset_single(char *cname, char *pname, Param pm, int func,
|
|||
* last case only, we need to delete the old parameter.
|
||||
*/
|
||||
if (tc) {
|
||||
if (pm->flags & PM_READONLY) {
|
||||
on |= ~off & PM_READONLY;
|
||||
pm->flags &= ~PM_READONLY;
|
||||
}
|
||||
/* Maintain existing readonly/exported status... */
|
||||
on |= ~off & (PM_READONLY|PM_EXPORTED) & pm->flags;
|
||||
/* ...but turn off existing readonly so we can delete it */
|
||||
pm->flags &= ~PM_READONLY;
|
||||
/*
|
||||
* If we're just changing the type, we should keep the
|
||||
* variable at the current level of localness.
|
||||
*/
|
||||
keeplocal = pm->level;
|
||||
/*
|
||||
* Try to carry over a value, but not when changing from,
|
||||
* to, or between non-scalar types.
|
||||
|
@ -1563,17 +1568,33 @@ typeset_single(char *cname, char *pname, Param pm, int func,
|
|||
pm = createparam(pname, on & ~PM_READONLY);
|
||||
DPUTS(!pm, "BUG: parameter not created");
|
||||
pm->ct = auxlen;
|
||||
if (func != BIN_EXPORT)
|
||||
|
||||
if (altpm && PM_TYPE(pm->flags) == PM_SCALAR) {
|
||||
/*
|
||||
* It seems safer to set this here than in createparam(),
|
||||
* to make sure we only ever use the colonarr functions
|
||||
* when u.data is correctly set.
|
||||
*/
|
||||
pm->sets.cfn = colonarrsetfn;
|
||||
pm->gets.cfn = colonarrgetfn;
|
||||
pm->u.data = &altpm->u.arr;
|
||||
}
|
||||
|
||||
if (keeplocal)
|
||||
pm->level = keeplocal;
|
||||
else if (func != BIN_EXPORT)
|
||||
pm->level = locallevel;
|
||||
if (value && !(pm->flags & (PM_ARRAY|PM_HASHED)))
|
||||
setsparam(pname, ztrdup(value));
|
||||
pm->flags |= (on & PM_READONLY);
|
||||
if (value && (pm->flags & (PM_ARRAY|PM_HASHED))) {
|
||||
zerrnam(cname, "%s: can't assign initial value for array", pname, 0);
|
||||
return 1;
|
||||
/* the only safe thing to do here seems to be unset the param */
|
||||
unsetparam_pm(pm, 0, 1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return pm;
|
||||
}
|
||||
|
||||
/* declare, export, integer, local, readonly, typeset */
|
||||
|
@ -1585,7 +1606,7 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
Param pm;
|
||||
Asgment asg;
|
||||
Comp com;
|
||||
char *optstr = "aiALRZlurtxU";
|
||||
char *optstr = "aiALRZlurtxUT";
|
||||
int on = 0, off = 0, roff, bit = PM_ARRAY;
|
||||
int i;
|
||||
int returnval = 0, printflags = 0;
|
||||
|
@ -1619,6 +1640,9 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
off |= PM_UPPER;
|
||||
if (on & PM_HASHED)
|
||||
off |= PM_ARRAY;
|
||||
if (on & PM_TIED)
|
||||
off |= PM_INTEGER | PM_ARRAY | PM_HASHED;
|
||||
|
||||
on &= ~off;
|
||||
|
||||
/* Given no arguments, list whatever the options specify. */
|
||||
|
@ -1631,6 +1655,58 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (on & PM_TIED) {
|
||||
Param apm;
|
||||
char *name1;
|
||||
|
||||
if (ops['m']) {
|
||||
zwarnnam(name, "incompatible options for -T", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
on &= ~off;
|
||||
if (!argv[1] || argv[2]) {
|
||||
zwarnnam(name, "-T requires names of scalar and array", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the tied array; this is normal except that
|
||||
* it has the PM_TIED flag set. Do it first because
|
||||
* we need the address.
|
||||
*/
|
||||
if (!(asg = getasg(argv[1])))
|
||||
return 1;
|
||||
name1 = ztrdup(asg->name);
|
||||
if (!(apm=typeset_single(name, asg->name,
|
||||
(Param)paramtab->getnode(paramtab,
|
||||
asg->name),
|
||||
func, on | PM_ARRAY, off, roff,
|
||||
asg->value, NULL)))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Create the tied colonarray. We make it as a normal scalar
|
||||
* and fix up the oddities later.
|
||||
*/
|
||||
if (!(asg = getasg(argv[0])) ||
|
||||
!(pm=typeset_single(name, asg->name,
|
||||
(Param)paramtab->getnode(paramtab,
|
||||
asg->name),
|
||||
func, on, off, roff, asg->value, apm))) {
|
||||
unsetparam_pm(apm, 1, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pm->ename = name1;
|
||||
apm->ename = ztrdup(asg->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (off & PM_TIED) {
|
||||
zerrnam(name, "use unset to remove tied variables", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* With the -m option, treat arguments as glob patterns */
|
||||
if (ops['m']) {
|
||||
MUSTUSEHEAP("typeset -m");
|
||||
|
@ -1664,8 +1740,8 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
}
|
||||
for (pmnode = firstnode(pmlist); pmnode; incnode(pmnode)) {
|
||||
pm = (Param) getdata(pmnode);
|
||||
if (typeset_single(name, pm->nam, pm, func, on, off, roff,
|
||||
asg->value))
|
||||
if (!typeset_single(name, pm->nam, pm, func, on, off, roff,
|
||||
asg->value, NULL))
|
||||
returnval = 1;
|
||||
}
|
||||
}
|
||||
|
@ -1680,9 +1756,9 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
returnval = 1;
|
||||
continue;
|
||||
}
|
||||
if (typeset_single(name, asg->name,
|
||||
(Param)paramtab->getnode(paramtab, asg->name),
|
||||
func, on, off, roff, asg->value))
|
||||
if (!typeset_single(name, asg->name,
|
||||
(Param)paramtab->getnode(paramtab, asg->name),
|
||||
func, on, off, roff, asg->value, NULL))
|
||||
returnval = 1;
|
||||
}
|
||||
return returnval;
|
||||
|
|
319
Src/glob.c
319
Src/glob.c
|
@ -31,7 +31,42 @@
|
|||
#include "glob.pro"
|
||||
|
||||
/* flag for CSHNULLGLOB */
|
||||
|
||||
|
||||
typedef struct gmatch *Gmatch;
|
||||
|
||||
struct gmatch {
|
||||
char *name;
|
||||
long size;
|
||||
long atime;
|
||||
long mtime;
|
||||
long ctime;
|
||||
long links;
|
||||
long _size;
|
||||
long _atime;
|
||||
long _mtime;
|
||||
long _ctime;
|
||||
long _links;
|
||||
};
|
||||
|
||||
#define GS_NAME 1
|
||||
#define GS_SIZE 2
|
||||
#define GS_ATIME 4
|
||||
#define GS_MTIME 8
|
||||
#define GS_CTIME 16
|
||||
#define GS_LINKS 32
|
||||
|
||||
#define GS_SHIFT 5
|
||||
#define GS__SIZE (GS_SIZE << GS_SHIFT)
|
||||
#define GS__ATIME (GS_ATIME << GS_SHIFT)
|
||||
#define GS__MTIME (GS_MTIME << GS_SHIFT)
|
||||
#define GS__CTIME (GS_CTIME << GS_SHIFT)
|
||||
#define GS__LINKS (GS_LINKS << GS_SHIFT)
|
||||
|
||||
#define GS_DESC 2048
|
||||
|
||||
#define GS_NORMAL (GS_SIZE | GS_ATIME | GS_MTIME | GS_CTIME | GS_LINKS)
|
||||
#define GS_LINKED (GS_NORMAL << GS_SHIFT)
|
||||
|
||||
/**/
|
||||
int badcshglob;
|
||||
|
||||
|
@ -42,8 +77,8 @@ static int matchct; /* number of matches found */
|
|||
static char *pathbuf; /* pathname buffer */
|
||||
static int pathbufsz; /* size of pathbuf */
|
||||
static int pathbufcwd; /* where did we chdir()'ed */
|
||||
static char **matchbuf; /* array of matches */
|
||||
static char **matchptr; /* &matchbuf[matchct] */
|
||||
static Gmatch matchbuf; /* array of matches */
|
||||
static Gmatch matchptr; /* &matchbuf[matchct] */
|
||||
static char *colonmod; /* colon modifiers in qualifier list */
|
||||
|
||||
typedef struct stat *Statptr; /* This makes the Ultrix compiler happy. Go figure. */
|
||||
|
@ -81,6 +116,7 @@ static struct qual *quals;
|
|||
static int qualct, qualorct;
|
||||
static int range, amc, units;
|
||||
static int gf_nullglob, gf_markdirs, gf_noglobdots, gf_listtypes, gf_follow;
|
||||
static int gf_sorts, gf_nsorts, gf_sortlist[11];
|
||||
|
||||
/* Prefix, suffix for doing zle trickery */
|
||||
|
||||
|
@ -213,6 +249,7 @@ insert(char *s, int checked)
|
|||
|
||||
if (!statted && statfullpath(s, &buf, 1))
|
||||
return;
|
||||
statted = 1;
|
||||
qo = quals;
|
||||
for (qn = qo; qn && qn->func;) {
|
||||
range = qn->range;
|
||||
|
@ -237,19 +274,44 @@ insert(char *s, int checked)
|
|||
}
|
||||
qn = qn->next;
|
||||
}
|
||||
} else if (!checked && statfullpath(s, NULL, 1))
|
||||
return;
|
||||
|
||||
} else if (!checked) {
|
||||
if (statfullpath(s, NULL, 1))
|
||||
return;
|
||||
statted = 1;
|
||||
}
|
||||
news = dyncat(pathbuf, news);
|
||||
if (colonmod) {
|
||||
/* Handle the remainder of the qualifer: e.g. (:r:s/foo/bar/). */
|
||||
s = colonmod;
|
||||
modify(&news, &s);
|
||||
}
|
||||
*matchptr++ = news;
|
||||
if (!statted && (gf_sorts & GS_NORMAL)) {
|
||||
statfullpath(s, &buf, 1);
|
||||
statted = 1;
|
||||
}
|
||||
if (statted != 2 && (gf_sorts & GS_LINKED)) {
|
||||
if (statted) {
|
||||
if (!S_ISLNK(buf.st_mode) || statfullpath(s, &buf2, 0))
|
||||
memcpy(&buf2, &buf, sizeof(buf));
|
||||
} else if (statfullpath(s, &buf2, 0))
|
||||
statfullpath(s, &buf2, 1);
|
||||
}
|
||||
matchptr->name = news;
|
||||
matchptr->size = buf.st_size;
|
||||
matchptr->atime = buf.st_atime;
|
||||
matchptr->mtime = buf.st_mtime;
|
||||
matchptr->ctime = buf.st_ctime;
|
||||
matchptr->links = buf.st_nlink;
|
||||
matchptr->_size = buf2.st_size;
|
||||
matchptr->_atime = buf2.st_atime;
|
||||
matchptr->_mtime = buf2.st_mtime;
|
||||
matchptr->_ctime = buf2.st_ctime;
|
||||
matchptr->_links = buf2.st_nlink;
|
||||
matchptr++;
|
||||
|
||||
if (++matchct == matchsz) {
|
||||
matchbuf = (char **)realloc((char *)matchbuf,
|
||||
sizeof(char **) * (matchsz *= 2));
|
||||
matchbuf = (Gmatch )realloc((char *)matchbuf,
|
||||
sizeof(struct gmatch) * (matchsz *= 2));
|
||||
|
||||
matchptr = matchbuf + matchct;
|
||||
}
|
||||
|
@ -944,21 +1006,144 @@ qgetnum(char **s)
|
|||
return v;
|
||||
}
|
||||
|
||||
/* get octal number after qualifier */
|
||||
/* get mode spec after qualifier */
|
||||
|
||||
/**/
|
||||
static long
|
||||
qgetoctnum(char **s)
|
||||
qgetmodespec(char **s)
|
||||
{
|
||||
long v = 0;
|
||||
long yes = 0, no = 0, val, mask, t;
|
||||
char *p = *s, c, how, end;
|
||||
|
||||
if (!idigit(**s)) {
|
||||
zerr("octal number expected", NULL, 0);
|
||||
return 0;
|
||||
if ((c = *p) == '=' || c == Equals || c == '+' || c == '-' ||
|
||||
c == '?' || c == Quest || (c >= '0' && c <= '7')) {
|
||||
end = 0;
|
||||
c = 0;
|
||||
} else {
|
||||
end = (c == '<' ? '>' :
|
||||
(c == '[' ? ']' :
|
||||
(c == '{' ? '}' :
|
||||
(c == Inang ? Outang :
|
||||
(c == Inbrack ? Outbrack :
|
||||
(c == Inbrace ? Outbrace : c))))));
|
||||
p++;
|
||||
}
|
||||
while (**s >= '0' && **s <= '7')
|
||||
v = v * 010 + *(*s)++ - '0';
|
||||
return v;
|
||||
do {
|
||||
mask = 0;
|
||||
while (((c = *p) == 'u' || c == 'g' || c == 'o' || c == 'a') && end) {
|
||||
switch (c) {
|
||||
case 'o': mask |= 01007; break;
|
||||
case 'g': mask |= 02070; break;
|
||||
case 'u': mask |= 04700; break;
|
||||
case 'a': mask |= 07777; break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
how = ((c == '+' || c == '-') ? c : '=');
|
||||
if (c == '+' || c == '-' || c == '=' || c == Equals)
|
||||
p++;
|
||||
val = 0;
|
||||
if (mask) {
|
||||
while ((c = *p++) != ',' && c != end) {
|
||||
switch (c) {
|
||||
case 'x': val |= 00111; break;
|
||||
case 'w': val |= 00222; break;
|
||||
case 'r': val |= 00444; break;
|
||||
case 's': val |= 06000; break;
|
||||
case 't': val |= 01000; break;
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
t = ((long) c - '0');
|
||||
val |= t | (t << 3) | (t << 6);
|
||||
break;
|
||||
default:
|
||||
zerr("invalid mode specification", NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (how == '=' || how == '+') {
|
||||
yes |= val & mask;
|
||||
val = ~val;
|
||||
}
|
||||
if (how == '=' || how == '-')
|
||||
no |= val & mask;
|
||||
} else {
|
||||
t = 07777;
|
||||
while ((c = *p) == '?' || c == Quest ||
|
||||
(c >= '0' && c <= '7')) {
|
||||
if (c == '?' || c == Quest) {
|
||||
t = (t << 3) | 7;
|
||||
val <<= 3;
|
||||
} else {
|
||||
t <<= 3;
|
||||
val = (val << 3) | ((long) c - '0');
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if (end && c != end && c != ',') {
|
||||
zerr("invalid mode specification", NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
if (how == '=') {
|
||||
yes = (yes & ~t) | val;
|
||||
no = (no & ~t) | (~val & ~t);
|
||||
} else if (how == '+')
|
||||
yes |= val;
|
||||
else
|
||||
no |= val;
|
||||
}
|
||||
} while (end && c != end);
|
||||
|
||||
*s = p;
|
||||
return ((yes & 07777) | ((no & 07777) << 12));
|
||||
}
|
||||
|
||||
static int
|
||||
gmatchcmp(Gmatch a, Gmatch b)
|
||||
{
|
||||
int i, *s;
|
||||
long r;
|
||||
|
||||
for (i = gf_nsorts, s = gf_sortlist; i; i--, s++) {
|
||||
switch (*s & ~GS_DESC) {
|
||||
case GS_NAME:
|
||||
r = notstrcmp(&a->name, &b->name);
|
||||
break;
|
||||
case GS_SIZE:
|
||||
r = b->size - a->size;
|
||||
break;
|
||||
case GS_ATIME:
|
||||
r = a->atime - b->atime;
|
||||
break;
|
||||
case GS_MTIME:
|
||||
r = a->mtime - b->mtime;
|
||||
break;
|
||||
case GS_CTIME:
|
||||
r = a->ctime - b->ctime;
|
||||
break;
|
||||
case GS_LINKS:
|
||||
r = b->links - a->links;
|
||||
break;
|
||||
case GS__SIZE:
|
||||
r = b->_size - a->_size;
|
||||
break;
|
||||
case GS__ATIME:
|
||||
r = a->_atime - b->_atime;
|
||||
break;
|
||||
case GS__MTIME:
|
||||
r = a->_mtime - b->_mtime;
|
||||
break;
|
||||
case GS__CTIME:
|
||||
r = a->_ctime - b->_ctime;
|
||||
break;
|
||||
case GS__LINKS:
|
||||
r = b->_links - a->_links;
|
||||
break;
|
||||
}
|
||||
if (r)
|
||||
return (int) ((*s & GS_DESC) ? -r : r);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Main entry point to the globbing code for filename globbing. *
|
||||
|
@ -976,7 +1161,8 @@ glob(LinkList list, LinkNode np)
|
|||
Complist q; /* pattern after parsing */
|
||||
char *ostr = (char *)getdata(np); /* the pattern before the parser */
|
||||
/* chops it up */
|
||||
|
||||
int first = 0, last = -1; /* index of first/last match to */
|
||||
/* return */
|
||||
MUSTUSEHEAP("glob");
|
||||
if (unset(GLOBOPT) || !haswilds(ostr)) {
|
||||
untokenize(ostr);
|
||||
|
@ -994,6 +1180,7 @@ glob(LinkList list, LinkNode np)
|
|||
gf_markdirs = isset(MARKDIRS);
|
||||
gf_listtypes = gf_follow = 0;
|
||||
gf_noglobdots = unset(GLOBDOTS);
|
||||
gf_sorts = gf_nsorts = 0;
|
||||
|
||||
/* Check for qualifiers */
|
||||
if (isset(BAREGLOBQUAL) && str[sl - 1] == Outpar) {
|
||||
|
@ -1246,10 +1433,9 @@ glob(LinkList list, LinkNode np)
|
|||
}
|
||||
break;
|
||||
case 'o':
|
||||
/* Match octal mode of file exactly. *
|
||||
* Currently undocumented. */
|
||||
func = qualeqflags;
|
||||
data = qgetoctnum(&s);
|
||||
/* Match modes with chmod-spec. */
|
||||
func = qualmodeflags;
|
||||
data = qgetmodespec(&s);
|
||||
break;
|
||||
case 'M':
|
||||
/* Mark directories with a / */
|
||||
|
@ -1315,6 +1501,51 @@ glob(LinkList list, LinkNode np)
|
|||
data = qgetnum(&s);
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
{
|
||||
int t;
|
||||
|
||||
switch (*s) {
|
||||
case 'n': t = GS_NAME; break;
|
||||
case 'L': t = GS_SIZE; break;
|
||||
case 'l': t = GS_LINKS; break;
|
||||
case 'a': t = GS_ATIME; break;
|
||||
case 'm': t = GS_MTIME; break;
|
||||
case 'c': t = GS_CTIME; break;
|
||||
default:
|
||||
zerr("unknown sort specifier", NULL, 0);
|
||||
return;
|
||||
}
|
||||
if ((sense & 2) && t != GS_NAME)
|
||||
t <<= GS_SHIFT;
|
||||
if (gf_sorts & t) {
|
||||
zerr("doubled sort specifier", NULL, 0);
|
||||
return;
|
||||
}
|
||||
gf_sorts |= t;
|
||||
gf_sortlist[gf_nsorts++] = t |
|
||||
((sense & 1) ? GS_DESC : 0);
|
||||
s++;
|
||||
break;
|
||||
}
|
||||
case '[':
|
||||
case Inbrack:
|
||||
{
|
||||
char *os = --s;
|
||||
struct value v;
|
||||
|
||||
v.isarr = SCANPM_WANTVALS;
|
||||
v.pm = NULL;
|
||||
v.b = -1;
|
||||
v.inv = 0;
|
||||
if (getindex(&s, &v) || s == os) {
|
||||
zerr("invalid subscript", NULL, 0);
|
||||
return;
|
||||
}
|
||||
first = v.a;
|
||||
last = v.b;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
zerr("unknown file attribute", NULL, 0);
|
||||
return;
|
||||
|
@ -1353,10 +1584,14 @@ glob(LinkList list, LinkNode np)
|
|||
zerr("bad pattern: %s", ostr, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gf_nsorts) {
|
||||
gf_sortlist[0] = gf_sorts = GS_NAME;
|
||||
gf_nsorts = 1;
|
||||
}
|
||||
/* Initialise receptacle for matched files, *
|
||||
* expanded by insert() where necessary. */
|
||||
matchptr = matchbuf = (char **)zalloc((matchsz = 16) * sizeof(char *));
|
||||
matchptr = matchbuf = (Gmatch)zalloc((matchsz = 16) *
|
||||
sizeof(struct gmatch));
|
||||
matchct = 0;
|
||||
|
||||
/* The actual processing takes place here: matches go into *
|
||||
|
@ -1375,18 +1610,32 @@ glob(LinkList list, LinkNode np)
|
|||
return;
|
||||
} else {
|
||||
/* treat as an ordinary string */
|
||||
untokenize(*matchptr++ = dupstring(ostr));
|
||||
untokenize(matchptr->name = dupstring(ostr));
|
||||
matchptr++;
|
||||
matchct = 1;
|
||||
}
|
||||
}
|
||||
/* Sort arguments in to lexical (and possibly numeric) order. *
|
||||
* This is reversed to facilitate insertion into the list. */
|
||||
qsort((void *) & matchbuf[0], matchct, sizeof(char *),
|
||||
(int (*) _((const void *, const void *)))notstrcmp);
|
||||
qsort((void *) & matchbuf[0], matchct, sizeof(struct gmatch),
|
||||
(int (*) _((const void *, const void *)))gmatchcmp);
|
||||
|
||||
matchptr = matchbuf;
|
||||
while (matchct--) /* insert matches in the arg list */
|
||||
insertlinknode(list, node, *matchptr++);
|
||||
if (first < 0)
|
||||
first += matchct;
|
||||
if (last < 0)
|
||||
last += matchct;
|
||||
if (first < 0)
|
||||
first = 0;
|
||||
if (last >= matchct)
|
||||
last = matchct - 1;
|
||||
if (first <= last) {
|
||||
matchptr = matchbuf + matchct - 1 - last;
|
||||
last -= first;
|
||||
while (last-- >= 0) { /* insert matches in the arg list */
|
||||
insertlinknode(list, node, matchptr->name);
|
||||
matchptr++;
|
||||
}
|
||||
}
|
||||
free(matchbuf);
|
||||
}
|
||||
|
||||
|
@ -2918,13 +3167,15 @@ qualflags(struct stat *buf, long mod)
|
|||
return mode_to_octal(buf->st_mode) & mod;
|
||||
}
|
||||
|
||||
/* mode matches number supplied exactly */
|
||||
/* mode matches specification */
|
||||
|
||||
/**/
|
||||
static int
|
||||
qualeqflags(struct stat *buf, long mod)
|
||||
qualmodeflags(struct stat *buf, long mod)
|
||||
{
|
||||
return mode_to_octal(buf->st_mode) == mod;
|
||||
long v = mode_to_octal(buf->st_mode), y = mod & 07777, n = mod >> 12;
|
||||
|
||||
return ((v & y) == y && !(v & n));
|
||||
}
|
||||
|
||||
/* regular executable file? */
|
||||
|
|
45
Src/init.c
45
Src/init.c
|
@ -300,18 +300,61 @@ init_io(void)
|
|||
|
||||
/* Make sure the tty is opened read/write. */
|
||||
if (isatty(0)) {
|
||||
#ifdef TIOCNXCL
|
||||
/*
|
||||
* See if the terminal claims to be busy. If so, and fd 0
|
||||
* is a terminal, try and set non-exclusive use for that.
|
||||
* This is something to do with Solaris over-cleverness.
|
||||
*/
|
||||
int tmpfd;
|
||||
if ((tmpfd = open("/dev/tty", O_RDWR | O_NOCTTY)) < 0) {
|
||||
if (errno == EBUSY)
|
||||
ioctl(0, TIOCNXCL, 0);
|
||||
} else
|
||||
close(tmpfd);
|
||||
#endif
|
||||
zsfree(ttystrname);
|
||||
if ((ttystrname = ztrdup(ttyname(0))))
|
||||
SHTTY = movefd(open(ttystrname, O_RDWR | O_NOCTTY));
|
||||
/*
|
||||
* xterm, rxvt and probably all terminal emulators except
|
||||
* dtterm on Solaris 2.6 & 7 have a bug. Applications are
|
||||
* unable to open /dev/tty or /dev/pts/<terminal number here>
|
||||
* because something in Sun's STREAMS modules doesn't like
|
||||
* it. The open() call fails with EBUSY which is not even
|
||||
* listed as a possibility in the open(2) man page. So we'll
|
||||
* try to outsmart The Company. -- <dave@srce.hr>
|
||||
*
|
||||
* Presumably there's no harm trying this on any OS, given that
|
||||
* isatty(0) worked but opening the tty didn't. Possibly we won't
|
||||
* get the tty read/write, but it's the best we can do -- pws
|
||||
*
|
||||
* Try both stdin and stdout before trying /dev/tty. -- Bart
|
||||
*/
|
||||
#if defined(HAVE_FCNTL_H) && defined(F_GETFL)
|
||||
#define rdwrtty(fd) ((fcntl(fd, F_GETFL) & O_RDWR) == O_RDWR)
|
||||
#else
|
||||
#define rdwrtty(fd) 1
|
||||
#endif
|
||||
if (SHTTY == -1 && rdwrtty(0)) {
|
||||
SHTTY = movefd(dup(0));
|
||||
}
|
||||
}
|
||||
if (SHTTY == -1 && isatty(1) && rdwrtty(1) &&
|
||||
(SHTTY = movefd(dup(1))) != -1) {
|
||||
zsfree(ttystrname);
|
||||
ttystrname = ztrdup(ttyname(1));
|
||||
}
|
||||
if (SHTTY == -1 &&
|
||||
(SHTTY = movefd(open("/dev/tty", O_RDWR | O_NOCTTY))) != -1) {
|
||||
zsfree(ttystrname);
|
||||
ttystrname = ztrdup("/dev/tty");
|
||||
ttystrname = ztrdup(ttyname(SHTTY));
|
||||
}
|
||||
if (SHTTY == -1) {
|
||||
zsfree(ttystrname);
|
||||
ttystrname = ztrdup("");
|
||||
} else if (!ttystrname) {
|
||||
ttystrname = ztrdup("/dev/tty");
|
||||
}
|
||||
|
||||
/* We will only use zle if shell is interactive, *
|
||||
|
|
|
@ -109,7 +109,8 @@ int parend;
|
|||
|
||||
/* text of puctuation tokens */
|
||||
|
||||
static char *tokstrings[WHILE + 1] = {
|
||||
/**/
|
||||
char *tokstrings[WHILE + 1] = {
|
||||
NULL, /* NULLTOK 0 */
|
||||
";", /* SEPER */
|
||||
"\\n", /* NEWLIN */
|
||||
|
@ -120,7 +121,7 @@ static char *tokstrings[WHILE + 1] = {
|
|||
")", /* OUTPAR */
|
||||
"||", /* DBAR */
|
||||
"&&", /* DAMPER */
|
||||
")", /* OUTANG 10 */
|
||||
">", /* OUTANG 10 */
|
||||
">|", /* OUTANGBANG */
|
||||
">>", /* DOUTANG */
|
||||
">>|", /* DOUTANGBANG */
|
||||
|
|
66
Src/params.c
66
Src/params.c
|
@ -679,7 +679,7 @@ getarg(char **str, int *inv, Value v, int a2, long *w)
|
|||
Comp c;
|
||||
|
||||
/* first parse any subscription flags */
|
||||
if (*s == '(' || *s == Inpar) {
|
||||
if (v->pm && (*s == '(' || *s == Inpar)) {
|
||||
int escapes = 0;
|
||||
int waste;
|
||||
for (s++; *s != ')' && *s != Outpar && s != *str; s++) {
|
||||
|
@ -765,7 +765,7 @@ getarg(char **str, int *inv, Value v, int a2, long *w)
|
|||
} else if (rev) {
|
||||
v->isarr |= SCANPM_WANTVALS;
|
||||
}
|
||||
if (!down && PM_TYPE(v->pm->flags) == PM_HASHED)
|
||||
if (!down && v->pm && PM_TYPE(v->pm->flags) == PM_HASHED)
|
||||
v->isarr &= ~SCANPM_MATCHMANY;
|
||||
*inv = ind;
|
||||
}
|
||||
|
@ -785,7 +785,7 @@ getarg(char **str, int *inv, Value v, int a2, long *w)
|
|||
singsub(&s);
|
||||
|
||||
if (!rev) {
|
||||
if (PM_TYPE(v->pm->flags) == PM_HASHED) {
|
||||
if (v->pm && PM_TYPE(v->pm->flags) == PM_HASHED) {
|
||||
HashTable ht = v->pm->gets.hfn(v->pm);
|
||||
if (!ht) {
|
||||
ht = newparamtable(17, v->pm->nam);
|
||||
|
@ -1371,7 +1371,7 @@ setarrvalue(Value v, char **val)
|
|||
freearray(val);
|
||||
return;
|
||||
}
|
||||
if (PM_TYPE(v->pm->flags) & ~(PM_ARRAY|PM_HASHED)) {
|
||||
if (!(PM_TYPE(v->pm->flags) & (PM_ARRAY|PM_HASHED))) {
|
||||
freearray(val);
|
||||
zerr("attempt to assign array value to non-array", NULL, 0);
|
||||
return;
|
||||
|
@ -1501,7 +1501,7 @@ setsparam(char *s, char *val)
|
|||
if (!(v = getvalue(&s, 1)))
|
||||
createparam(t, PM_SCALAR);
|
||||
else if (PM_TYPE(v->pm->flags) == PM_ARRAY &&
|
||||
!(v->pm->flags & PM_SPECIAL) && unset(KSHARRAYS)) {
|
||||
!(v->pm->flags & (PM_SPECIAL|PM_TIED)) && unset(KSHARRAYS)) {
|
||||
unsetparam(t);
|
||||
createparam(t, PM_SCALAR);
|
||||
v = NULL;
|
||||
|
@ -1545,7 +1545,7 @@ setaparam(char *s, char **val)
|
|||
if (!(v = getvalue(&s, 1)))
|
||||
createparam(t, PM_ARRAY);
|
||||
else if (!(PM_TYPE(v->pm->flags) & (PM_ARRAY|PM_HASHED)) &&
|
||||
!(v->pm->flags & PM_SPECIAL)) {
|
||||
!(v->pm->flags & (PM_SPECIAL|PM_TIED))) {
|
||||
int uniq = v->pm->flags & PM_UNIQUE;
|
||||
unsetparam(t);
|
||||
createparam(t, PM_ARRAY | uniq);
|
||||
|
@ -1662,26 +1662,36 @@ unsetparam_pm(Param pm, int altflag, int exp)
|
|||
unsetparam_pm(altpm, 1, exp);
|
||||
}
|
||||
|
||||
/* If this was a local variable, we need to keep the old *
|
||||
* struct so that it is resurrected at the right level. *
|
||||
* This is partly because when an array/scalar value is set *
|
||||
* and the parameter used to be the other sort, unsetparam() *
|
||||
* is called. Beyond that, there is an ambiguity: should *
|
||||
* foo() { local bar; unset bar; } make the global bar *
|
||||
* available or not? The following makes the answer "no". */
|
||||
if ((locallevel && locallevel >= pm->level) || (pm->flags & PM_SPECIAL))
|
||||
/*
|
||||
* If this was a local variable, we need to keep the old
|
||||
* struct so that it is resurrected at the right level.
|
||||
* This is partly because when an array/scalar value is set
|
||||
* and the parameter used to be the other sort, unsetparam()
|
||||
* is called. Beyond that, there is an ambiguity: should
|
||||
* foo() { local bar; unset bar; } make the global bar
|
||||
* available or not? The following makes the answer "no".
|
||||
*
|
||||
* Some specials, such as those used in zle, still need removing
|
||||
* from the parameter table; they have the PM_REMOVABLE flag.
|
||||
*/
|
||||
if ((locallevel && locallevel >= pm->level) ||
|
||||
(pm->flags & (PM_SPECIAL|PM_REMOVABLE)) == PM_SPECIAL)
|
||||
return;
|
||||
|
||||
paramtab->removenode(paramtab, pm->nam); /* remove parameter node from table */
|
||||
/* remove parameter node from table */
|
||||
paramtab->removenode(paramtab, pm->nam);
|
||||
|
||||
if (pm->old) {
|
||||
oldpm = pm->old;
|
||||
paramtab->addnode(paramtab, oldpm->nam, oldpm);
|
||||
if ((PM_TYPE(oldpm->flags) == PM_SCALAR) && oldpm->sets.cfn == strsetfn)
|
||||
if ((PM_TYPE(oldpm->flags) == PM_SCALAR) &&
|
||||
oldpm->sets.cfn == strsetfn)
|
||||
adduserdir(oldpm->nam, oldpm->u.str, 0, 0);
|
||||
}
|
||||
|
||||
paramtab->freenode((HashNode) pm); /* free parameter node */
|
||||
/* Even removable specials shouldn't be deleted. */
|
||||
if (!(pm->flags & PM_SPECIAL))
|
||||
paramtab->freenode((HashNode) pm); /* free parameter node */
|
||||
}
|
||||
|
||||
/* Standard function to unset a parameter. This is mostly delegated to *
|
||||
|
@ -1759,6 +1769,9 @@ arrsetfn(Param pm, char **x)
|
|||
if (pm->flags & PM_UNIQUE)
|
||||
uniqarray(x);
|
||||
pm->u.arr = x;
|
||||
/* Arrays tied to colon-arrays may need to fix the environment */
|
||||
if (pm->ename && x)
|
||||
arrfixenv(pm->ename, x);
|
||||
}
|
||||
|
||||
/* Function to get value of an association parameter */
|
||||
|
@ -1950,7 +1963,8 @@ arrvarsetfn(Param pm, char **x)
|
|||
char *
|
||||
colonarrgetfn(Param pm)
|
||||
{
|
||||
return zjoin(*(char ***)pm->u.data, ':');
|
||||
char ***dptr = (char ***)pm->u.data;
|
||||
return *dptr ? zjoin(*dptr, ':') : "";
|
||||
}
|
||||
|
||||
/**/
|
||||
|
@ -1959,8 +1973,15 @@ colonarrsetfn(Param pm, char *x)
|
|||
{
|
||||
char ***dptr = (char ***)pm->u.data;
|
||||
|
||||
freearray(*dptr);
|
||||
*dptr = x ? colonsplit(x, pm->flags & PM_UNIQUE) : mkarray(NULL);
|
||||
/*
|
||||
* If this is tied to a parameter (rather than internal) array,
|
||||
* the array itself may be NULL. Otherwise, we have to make
|
||||
* sure it doesn't ever get null.
|
||||
*/
|
||||
if (*dptr)
|
||||
freearray(*dptr);
|
||||
*dptr = x ? colonsplit(x, pm->flags & PM_UNIQUE) :
|
||||
(pm->flags & PM_TIED) ? NULL : mkarray(NULL);
|
||||
if (pm->ename)
|
||||
arrfixenv(pm->nam, *dptr);
|
||||
zsfree(x);
|
||||
|
@ -2399,7 +2420,7 @@ arrfixenv(char *s, char **t)
|
|||
MUSTUSEHEAP("arrfixenv");
|
||||
if (t == path)
|
||||
cmdnamtab->emptytable(cmdnamtab);
|
||||
u = zjoin(t, ':');
|
||||
u = t ? zjoin(t, ':') : "";
|
||||
len_s = strlen(s);
|
||||
pm = (Param) paramtab->getnode(paramtab, s);
|
||||
for (ep = environ; *ep; ep++)
|
||||
|
@ -2602,6 +2623,9 @@ freeparamnode(HashNode hn)
|
|||
if (delunset)
|
||||
pm->unsetfn(pm, 1);
|
||||
zsfree(pm->nam);
|
||||
/* If this variable was tied by the user, ename was ztrdup'd */
|
||||
if (pm->flags & PM_TIED)
|
||||
zsfree(pm->ename);
|
||||
zfree(pm, sizeof(struct param));
|
||||
}
|
||||
|
||||
|
|
45
Src/subst.c
45
Src/subst.c
|
@ -702,6 +702,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
int whichlen = 0;
|
||||
int chkset = 0;
|
||||
int vunset = 0;
|
||||
int wantt = 0;
|
||||
int spbreak = isset(SHWORDSPLIT) && !ssub && !qt;
|
||||
char *val = NULL, **aval = NULL;
|
||||
unsigned int fwidth = 0;
|
||||
|
@ -902,6 +903,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
hvals = SCANPM_WANTVALS;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
wantt = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
flagerr:
|
||||
zerr("error in flags", NULL, 0);
|
||||
|
@ -978,9 +983,47 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
*s = sav;
|
||||
v = (Value) NULL;
|
||||
} else {
|
||||
if (!(v = fetchvalue(&s, (unset(KSHARRAYS) || inbrace) ? 1 : -1,
|
||||
if (!(v = fetchvalue(&s, (wantt ? -1 :
|
||||
((unset(KSHARRAYS) || inbrace) ? 1 : -1)),
|
||||
hkeys|hvals)))
|
||||
vunset = 1;
|
||||
|
||||
if (wantt) {
|
||||
if (v) {
|
||||
int f = v->pm->flags;
|
||||
|
||||
switch (PM_TYPE(f)) {
|
||||
case PM_SCALAR: val = "scalar"; break;
|
||||
case PM_ARRAY: val = "array"; break;
|
||||
case PM_INTEGER: val = "integer"; break;
|
||||
case PM_HASHED: val = "association"; break;
|
||||
}
|
||||
val = dupstring(val);
|
||||
if (f & PM_LEFT)
|
||||
val = dyncat(val, "-left");
|
||||
if (f & PM_RIGHT_B)
|
||||
val = dyncat(val, "-right_blanks");
|
||||
if (f & PM_RIGHT_Z)
|
||||
val = dyncat(val, "-right_zeros");
|
||||
if (f & PM_LOWER)
|
||||
val = dyncat(val, "-lower");
|
||||
if (f & PM_UPPER)
|
||||
val = dyncat(val, "-upper");
|
||||
if (f & PM_READONLY)
|
||||
val = dyncat(val, "-readonly");
|
||||
if (f & PM_TAGGED)
|
||||
val = dyncat(val, "-tag");
|
||||
if (f & PM_EXPORTED)
|
||||
val = dyncat(val, "-export");
|
||||
if (f & PM_UNIQUE)
|
||||
val = dyncat(val, "-unique");
|
||||
vunset = 0;
|
||||
} else
|
||||
val = dupstring("");
|
||||
|
||||
v = NULL;
|
||||
isarr = 0;
|
||||
}
|
||||
}
|
||||
while (v || ((inbrace || (unset(KSHARRAYS) && vunset)) && isbrack(*s))) {
|
||||
if (!v) {
|
||||
|
|
|
@ -214,6 +214,7 @@ tgoto
|
|||
tok
|
||||
tokenize
|
||||
tokstr
|
||||
tokstrings
|
||||
tputs
|
||||
trashzleptr
|
||||
tricat
|
||||
|
|
11
Src/zsh.h
11
Src/zsh.h
|
@ -780,6 +780,7 @@ struct shfunc {
|
|||
#define SFC_HOOK 2 /* one of the special functions */
|
||||
#define SFC_WIDGET 3 /* user defined widget */
|
||||
#define SFC_COMPLETE 4 /* called from completion code */
|
||||
#define SFC_CWIDGET 5 /* new style completion widget */
|
||||
|
||||
/* node in list of function call wrappers */
|
||||
|
||||
|
@ -916,10 +917,12 @@ struct param {
|
|||
#define PM_TAGGED (1<<9) /* tagged */
|
||||
#define PM_EXPORTED (1<<10) /* exported */
|
||||
#define PM_UNIQUE (1<<11) /* remove duplicates */
|
||||
#define PM_SPECIAL (1<<12) /* special builtin parameter */
|
||||
#define PM_DONTIMPORT (1<<13) /* do not import this variable */
|
||||
#define PM_RESTRICTED (1<<14) /* cannot be changed in restricted mode */
|
||||
#define PM_UNSET (1<<15) /* has null value */
|
||||
#define PM_TIED (1<<12) /* array tied to colon-path or v.v. */
|
||||
#define PM_SPECIAL (1<<13) /* special builtin parameter */
|
||||
#define PM_DONTIMPORT (1<<14) /* do not import this variable */
|
||||
#define PM_RESTRICTED (1<<15) /* cannot be changed in restricted mode */
|
||||
#define PM_UNSET (1<<16) /* has null value */
|
||||
#define PM_REMOVABLE (1<<17) /* special can be removed from paramtab */
|
||||
|
||||
/* Flags for extracting elements of arrays and associative arrays */
|
||||
#define SCANPM_WANTVALS (1<<0)
|
||||
|
|
21
configure.in
21
configure.in
|
@ -1008,9 +1008,24 @@ char *argv[];
|
|||
aix*) DLLDFLAGS="${DLLDFLAGS=-G -bexpall -lc}" ;;
|
||||
solaris*|sysv4*|esix*) DLLDFLAGS="${DLLDFLAGS=-G}" ;;
|
||||
esac
|
||||
case "$host_os" in
|
||||
hpux*) EXTRA_LDFLAGS="${EXTRA_LDFLAGS=-Wl,-E}" ;;
|
||||
linux*) EXTRA_LDFLAGS="${EXTRA_LDFLAGS=-rdynamic}" ;;
|
||||
case "$host" in
|
||||
*-hpux*) EXTRA_LDFLAGS="${EXTRA_LDFLAGS=-Wl,-E}" ;;
|
||||
*-linux*) EXTRA_LDFLAGS="${EXTRA_LDFLAGS=-rdynamic}" ;;
|
||||
mips-sni-sysv4)
|
||||
#
|
||||
# unfortunately, we have different compilers
|
||||
# that need different flags
|
||||
#
|
||||
sni_cc_version=`$CC -V 2>&1 | head -1`
|
||||
case "$sni_cc_version" in
|
||||
CDS* )
|
||||
EXTRA_LDFLAGS="${EXTRA_LDFLAGS=-Wl,-Blargedynsym}"
|
||||
;;
|
||||
* )
|
||||
EXTRA_LDFLAGS="${EXTRA_LDFLAGS=-LD-Blargedynsym}"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
AC_CACHE_CHECK(if your dlsym() needs a leading underscore,
|
||||
zsh_cv_func_dlsym_needs_underscore,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
This version of zsh is based on 3.1.5 and includes the following
|
||||
patches. (The version number built into the shell has not been changed.)
|
||||
patches.
|
||||
|
||||
Old stuff:
|
||||
|
||||
|
@ -111,7 +111,7 @@ My special parameter unset fix, 4662
|
|||
Third edition
|
||||
|
||||
I've taken the plunge and changed $ZSH_VERSION, the current one is now
|
||||
3.1.5.pws-1 . It seemed rational to have something incremental at the
|
||||
3.1.5.pws-3 . It seemed rational to have something incremental at the
|
||||
end for testing, so I abandoned using the date.
|
||||
|
||||
4482 (cdmatch2)and 4641 (${assoc[0]}) now applied; 4641 was supposed
|
||||
|
@ -261,8 +261,70 @@ need '-tc' with -T. However, you now do need '-tn' in cases where you
|
|||
don't want normal completion tried after a -T matches.
|
||||
|
||||
Sven's new completion functions, 4850, 4881, 4941, 4942, 4943, 4944,
|
||||
4946, 4949, plus my addition of function pointers, 4945. The example
|
||||
file is now in Misc/new-completion-examples.
|
||||
4946, 4949, 4950, plus my addition of function pointers, 4945. The
|
||||
example file is now in Misc/new-completion-examples.
|
||||
|
||||
(Effect of) fix from Helmut Jarausch in 4947 partly due to change
|
||||
missed in patch.
|
||||
|
||||
pws-6
|
||||
|
||||
Sven: fix for completion after redirection, 4957
|
||||
|
||||
Bart: add-on, 4965
|
||||
|
||||
Andrej: configure patch for Reliant UNIX et al., 5021 (as resubmitted)
|
||||
|
||||
Sven: compctl list with a single string, 4974
|
||||
|
||||
Sven: compctl -M matches with *'s, 4975, 5007
|
||||
|
||||
Sven: compadd and new-completion-examples, 4976
|
||||
|
||||
Sven: funky new glob modifiers: change sort order, select
|
||||
item from list, 4979; make time order work like ls -t, 4987
|
||||
|
||||
Sven: fix completion whitespace for copy-previous-word, 4981
|
||||
|
||||
Sven: fix for new-style completion after redirection, 4986, 4988
|
||||
|
||||
New mirror site ftp://ftp.win.ne.jp/pub/shell/zsh/ in META-FAQ (not
|
||||
posted)
|
||||
|
||||
Andrej: when installing info files, insert zsh.info into dir, 5016
|
||||
|
||||
Sven: ${(t)param} flag, 5022, 5045; no unset behaviour, 5078
|
||||
|
||||
Phil: zless, 5032, simplified by Bart, 5037, also added a `setopt
|
||||
localoptions' after spending an hour wondering why nothing worked any
|
||||
more.
|
||||
|
||||
Me: `make install' does not do `make install.info', 5047
|
||||
|
||||
Sven: compcall tries old-style completion from new-style function,
|
||||
compctl -K ' func' handles newstyle completion, 5059; avoid recursion,
|
||||
5065; my dynamic fix-up, 5085
|
||||
|
||||
Sven: inserting completion inside brace expansion, 5060
|
||||
|
||||
Sven: extra completion context, 5092
|
||||
|
||||
Me: typeset -T MYPATH mypath, 5094, plus fix for MYPATH=(foo),
|
||||
mypath=foo (and also existing PATH=(foo) bug), 5120
|
||||
|
||||
Sven: doc fix for glob qualifiers, 5102
|
||||
|
||||
Drazen Kacar, modified by me: workaround for terminal bug on Solaris,
|
||||
5103; modified by Bart, 5113
|
||||
|
||||
Sven: zle and widget information via variables in new completion
|
||||
functions, 5104
|
||||
|
||||
Me: remove old zle -C, zle -C now does new completion, 5105
|
||||
|
||||
Sven: glob qualifier o for modes, 5107
|
||||
|
||||
Me: fix for unsetting special zle variables, 5111
|
||||
|
||||
Drazen Kacar, modified by me: unlock terminal device on Solaris, 5118
|
||||
(5117 was wrong)
|
||||
|
|
Loading…
Reference in a new issue