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

zsh-3.1.5-pws-17

This commit is contained in:
Tanaka Akira 1999-05-02 15:19:50 +00:00
parent 206237c8ec
commit 53d36e795b
39 changed files with 1103 additions and 221 deletions

10
Completion/Builtins/_stat Normal file
View file

@ -0,0 +1,10 @@
#compdef stat
if [[ "$words[CURRENT-1]" = -[AH] ]]; then
compgen -A
else
[[ "$PREFIX[1]" = + ]] &&
compadd - +device +inode +mode +nlink +uid +gid +rdev +size \
+atime +mtime +ctime +blksize +block +link
_files
fi

View file

@ -1,6 +1,7 @@
DISTFILES_SRC='
.distfiles
_approximate _compalso _complete _correct _expand _files _list
_main_complete _match _multi_parts _normal _options _parameters
_path_files _sep_parts _set_options _unset_options compdump compinit
_approximate _closequotes _compalso _complete _correct _expand _files
_list _main_complete _match _menu _multi_parts _normal _oldlist _options
_parameters _path_files _sep_parts _set_options _unset_options
compdump compinit compinstall
'

View file

@ -0,0 +1,11 @@
#autoload
# If the current completion is in quotes, add the closing quote.
# This can clash with some of the more sophisticated forms of completion
if [[ -n $compstate[quote] && $RBUFFER != *${compstate[quote]}* ]]; then
compstate[restore]=''
ISUFFIX="$ISUFFIX$compstate[quote]"
fi
return 1

21
Completion/Core/_menu Normal file
View file

@ -0,0 +1,21 @@
#autoload
# This completer is an example showing how menucompletion can be
# implemented with the new completion system.
# Use this one before the normal _complete completer, as in:
#
# compconf completer=_menu:_complete
if [[ -n "$compstate[old_list]" ]]; then
# We have an old list, keep it and insert the next match.
compstate[old_list]=keep
compstate[insert]=$((compstate[old_insert]+1))
else
# No old list, make completion insert the first match.
compstate[insert]=1
fi
return 1

View file

@ -83,8 +83,7 @@ while true; do
else
# No exact match, see how many strings match what's on the line.
tmp2=( "${(@)matches%%${sep}*}" )
compadd -O tmp1 - "$tmp2[@]"
compadd -O tmp1 - "${(@)matches%%${sep}*}"
if [[ $#tmp1 -eq 1 ]]; then

29
Completion/Core/_oldlist Normal file
View file

@ -0,0 +1,29 @@
#autoload
# If this is a listing widget and there is already an old list,
# and either the compconfig key oldlist_list is `always', or it is not `never'
# and the list is not already shown, then use the existing list for listing
# (even if it was generated by another widget).
if [[ -n $compstate[old_list] && $compconfig[oldlist_list] != never &&
$WIDGET = *list* &&
( $compconfig[oldlist_list] = always || $compstate[old_list] != shown ) ]]
then
compstate[old_list]=keep
return 0
fi
# If this is a completion widget, and we have a completion inserted already,
# and the compconfig key oldlist_menu is not never, then we cycle through the
# existing list (even if it was generated by another widget).
if [[ -n $compstate[old_insert] && $WIDGET = *complete(|-prefix|-word) &&
$compconfig[oldlist_menu] != never ]]; then
compstate[old_list]=keep
if [[ $WIDGET = *reverse* ]]; then
compstate[insert]=$(( compstate[old_insert] - 1 ))
else
compstate[insert]=$(( compstate[old_insert] + 1 ))
fi
return 0
fi
return 1

View file

@ -230,14 +230,15 @@ for prepath in "$prepaths[@]"; do
if [[ -n "$PREFIX$SUFFIX" ]]; then
# See which of them match what's on the line.
compadd -O tmp2 "$ignore[@]" - "${(@)tmp1##*/}"
tmp2=("$tmp1[@]")
compadd -D tmp1 "$ignore[@]" - "${(@)tmp1##*/}"
# If no file matches, save the expanded path and continue with
# the outer loop.
if [[ $#tmp2 -eq 0 ]]; then
if [[ "$tmp1[1]" = */* ]]; then
tmp2=( "${(@)tmp1#${prepath}${realpath}}" )
if [[ $#tmp1 -eq 0 ]]; then
if [[ "$tmp2[1]" = */* ]]; then
tmp2=( "${(@)tmp2#${prepath}${realpath}}" )
if [[ "$tmp2[1]" = */* ]]; then
exppaths=( "$exppaths[@]" ${^tmp2%/*}/${tpre}${tsuf} )
else
@ -246,14 +247,6 @@ for prepath in "$prepaths[@]"; do
fi
continue 2
fi
# Remove all files that weren't matched.
if [[ "$tmp1[1]" = */* ]]; then
tmp1=( "${(@M)tmp1:#*/(${(j:|:)~${(@)tmp2:q}})}" )
else
tmp1=( "${(@M)tmp1:#(${(j:|:)~${(@)tmp2:q}})}" )
fi
elif (( ! $#tmp1 )); then
continue 2
fi

216
Completion/Core/compinstall Normal file
View file

@ -0,0 +1,216 @@
# This script is to be run by a user to setup the new function based
# completion system. The functions themselves are assumed to be already
# available in some directory; they should have been installed with the
# the shell (except we haven't written that yet).
#
# Run it as a script under zsh and answer the questions.
# You can run it as `zsh compinstall $FPATH' and it will be able to check
# your function path for the completion functions.
#
# Normally, this will alter ~/.zshrc (or wherever ZDOTDIR puts it),
# but you can make that unwritable and it will leave the lines in a
# temporary file instead.
#
# You can use this script to modify what compinstall previously
# added to ~/.zshrc.
#
# It is safe to abort with ^C any time you are being prompted for
# information; your .zshrc will not be altered.
#
# To do:
# - Maybe this should be sourced, then it can check the user's current
# setup better. But then there is a potentially horrendous option
# setting/resetting problem. (Maybe we need another way of doing that.)
# - Should probably offer to set different options for _approximate than
# for _complete if both are used.
# - Could add code for setting other completers and options.
# - Could add keys for context-sensitive help.
# - Probably should allow a set of directories to be added to $fpath,
# like Core, Base, etc.
# In case a startup script changed options
emulate zsh
[[ -n $1 ]] && FPATH=$1
for f in $fpath; do
if [[ $f != . && -f $f/compinit && -f $f/compdump ]]; then
fdir=$f
break
fi
done
if [[ -z $fdir ]]; then
print "Trying to find where the completion functions are..."
if [[ $0 = */* && -f $0:h/compinit && -f $0:h/compdump ]]; then
fdir=$0:h
else
# more guesses?
print \
"Please edit the name of the directory where the completion functions are
installed. If they are not installed, you will need to find them in the
Completion/* directories of the zsh distribution and install them yourself,
or insult your system manager for incompetence."
vared -c fdir
while [[ ! -d ${~fdir} || ! -f ${~fdir}/compinit ||
! -f ${~fdir}/compdump ]]; do
print "I can't find them in that directory. Try again or abort."
vared fdir
done
fi
eval "fpath=($fdir \$fpath)"
fdir=${fdir/#$HOME/\~}
lines="fpath=($fdir \$fpath)\n"
else
print "Found completion functions in your fpath, will not alter it."
fi
files=( ${^~fpath:/.}/_(|*[^~])(N:t) )
if [[ $#files -lt 20 ]]; then
print "
Hmmm, completion functions seem a bit thin on the ground. There should
be lots of files with names beginning with an underscore (_). You should
look and see what's happened to these.
[Hit return to continue]"
read
fi
if [[ -w ${~fdir} && ( ! -f ${~fdir}/compinit.dump ||
-w ${~fdir}/compinit.dump ) ]]
then
print "
Using standard dumpfile
${~fdir}/compinit.dump
to speed up initialisation.
[Hit return to continue]"
read
else
print "
I will force completion to dump its status, which will speed up the shell's
start-up considerably. However, I can't write the file I'd like to, namely
$fdir/compinit.dump. Please edit a replacement."
dumpfile='~/.compinit.dump'
vared dumpfile
while ! touch ${~dumpfile} >& /dev/null; do
print "Sorry, I can't write that either. Try again."
vared dumpfile
done
[[ -s $dumpfile ]] || rm -f $dumpfile
dumpfile=" $dumpfile"
fi
fdir=${fdir/#$HOME/\~}
lines="${lines}. $fdir/compinit -d$dumpfile\n"
print "
In addition to completion, zsh can also perform correction of the
current word, or approximate completion, i.e. completion where the part of
the word typed so far can be corrected; or it can try correction, then
approximate completion if that fails. Would you like:
0: Just ordinary completion
C: Correction
A: Approximate completion
B: Both?
Please type one of the keys above:"
while read -k type; do
print
case $type in
0*) completer=_complete
break
;;
[cC]*) completer=_complete:_correct
break
;;
[aA]*) completer=_complete:_approximate
break;
;;
[bB]*) completer=_complete:_correct:_approximate
break
;;
*) print Try again
;;
esac
done
lines="${lines}compconf completer=$completer"
if [[ $completer = *(correct|approx)* ]]; then
print "
Correction and approximation will normally allow up to two errors,
and you will be able to use a numeric prefix (e.g. <Esc>4) to allow
more. The standard prompt is \`correct to:'. Do you want to change
any of this? [n]"
if read -q; then
print "Number of errors to accept normally (0 is OK):"
read accept
while [[ $accept != <-> ]]; do
read accept"?Please enter a number: "
done
print \
"How would you like the numeric prefix to be treated:
0: Not used by correction
U: Used to given the number of errors
I: If present, and not 1, do not perform correction?
Please type one of the keys above:"
while read -k type; do
print
case $type in
0*) break
;;
[uU]*) accept="${accept}n"
break
;;
[Ii]*) accept="${accept}!n"
break
;;
*) print Try again
;;
esac
done
lines="$lines \\\\
correct_accept='$accept'"
print "
Instead of the prompt \`correct to:', you can have no prompt, or a
prompt of your choosing which can display the number of errors found by
containing the string \`%e'. Do you wish to change the correction
prompt? [n]"
if read -q; then
cprompt=''
print "Edit a new prompt (may be empty):"
vared cprompt
lines="$lines \\\\
correct_prompt='${cprompt//\'/\'\\\'\'}'"
fi
fi
fi
lines="$lines\n"
startline='# The following lines were added by compinstall'
endline='# End of lines added by compinstall'
ifile=${ZDOTDIR:-~}/.zshrc
[[ -f $ifile ]] || touch $ifile
tmpf=${TMPPPREFIX:-/tmp/zsh}compinstall$$
if [[ ! -w $ifile ]]; then
print "\nI can't write to $ifile. I will leave the lines to add in
\`$tmpf' and you must add them by hand."
print "\n$startline\n$lines\n$endline" >$tmpf
return 0
fi
if grep $endline $ifile >& /dev/null; then
print -- "$startline\n$lines$endline" >$tmpf
sed -e "/^$endline/r $tmpf
/^$startline/,/^$endline/d" $ifile >${tmpf}2 && mv ${tmpf}2 $ifile &&
print "\nSuccesfully modified old compinstall lines in $ifile."
rm -f $tmpf ${tmpf}2
else
print "\n$startline\n$lines\n$endline" >>$ifile &&
print "\nSuccessfully appended lines to $ifile."
fi

View file

@ -1,3 +1,3 @@
#compdef make gmake pmake
compgen -s "\$(awk '/^[a-zA-Z0-9][^\/ ]+:/ {print \$1}' FS=: [mM]akefile /dev/null)"
compgen -s "\$(awk '/^[a-zA-Z0-9][^\/ ]+:/ {print \$1}' FS=: [mM]akefile /dev/null)"

View file

@ -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-16
VERSION_DATE='April 25, 1999'
VERSION=3.1.5-pws-17
VERSION_DATE='April 30, 1999'

View file

@ -1175,9 +1175,12 @@ xitem(tt(zmodload) tt(-d) [ tt(-L) ] [ var(name) [ var(dep) ... ] ])
xitem(tt(zmodload) tt(-du) var(name) [ var(dep) ... ])
xitem(tt(zmodload) tt(-a) [ tt(-iL) ] [ var(name) [ var(builtin) ... ] ])
xitem(tt(zmodload) tt(-au) [ tt(-i) ] var(builtin) ...)
xitem(tt(zmodload) tt(-c) [ tt(-iI) ] [ var(name) [ var(cond) ... ] ])
xitem(tt(zmodload) tt(-c) [ tt(-iI) ] var(name) [ var(cond) ... ])
xitem(tt(zmodload) tt(-cu) [ tt(-iI) ] var(cond) ...)
item(tt(zmodload) tt(-c) [ tt(-IL) ])(
xitem(tt(zmodload) tt(-c) [ tt(-IL) ])
xitem(tt(zmodload) tt(-p) [ tt(-i) ] var(name) [ var(parameter) ... ])
xitem(tt(zmodload) tt(-pu) [ tt(-i) ] var(parameter) ... ])
item(tt(zmodload) tt(-p) [ tt(-L) ])(
tt(zmodload) performs operations relating to zsh's loadable modules.
This feature is not available on all operating systems,
or on all installations on a particular operating system.
@ -1253,5 +1256,8 @@ names. Without this option prefix condition names are defined.
Together with the tt(-u) option definitions for autoloaded conditions
are removed. If given no condition names all defined names are listed
(as a series of tt(zmodload) commands if the tt(-L) option is given).
The tt(-p) option is like the tt(-c) option, but makes tt(zmodload)
work on autoloaded parameters instead of condition codes.
)
enditem()

View file

@ -528,6 +528,53 @@ tt(MENU_COMPLETE) option and does not work with the other
menucompletion widgets such as tt(reverse-menu-complete), or
tt(accept-and-menu-complete).
)
item(tt(_oldlist))(
This completer controls how the standard completion widgets behave when
there is an existing list of completions which may have been generated by a
special completion (i.e. a separately-bound completion command). It should
appear in the list of completers before any of the widgets which generate
matches. It understands two configuration keys:
startitem()
item(tt(oldlist_list))(
If this is set to tt(always), then standard widgets which perform listing
will retain the current list of matches, however they were generated. If
it is set to tt(never), this will not be done (the behaviour without the
tt(_oldlist) completer). If it is unset, or any other value, then the
existing list of completions will be displayed if it is not already;
otherwise, the standard completion list will be generated: this is the
default behaviour of tt(_oldlist).
For example, suppose you type tt(^Xc) to use the tt(_correct_word)
widget, which generates a list of corrections for the word under the
cursor. Usually, typing tt(^D) would generate a standard list of
completions for the word on the command line, and show that. With
tt(_oldlist), it will instead show the list of corrections already
generated.
)
item(tt(oldlist_menu))(
Controls how menu completion behaves when a completion has already been
inserted and the user types a standard completion key type as tt(TAB).
The default behaviour of tt(_oldlist) is that menu completion always
continues with the existing list of completions. If this key is set to
tt(never), however, a new completion is started if the old list was
generated by a different completion command (the behaviour without the
tt(_oldlist) completer).
For example, suppose you type tt(^Xc) to generate a list of corrections,
and menu completion is started in one of the usual ways. Usually, typing
tt(TAB) at this point would start trying to complete the line as it now
appears. With tt(_oldlist), it will instead continue to cycle through the
list of completions.
)
enditem()
)
item(tt(_closequotes))(
When a completion starts in quotes, this completer will recognise the fact
and insert a matching closing quote if there is not already one later on
the line. It should come earlier in the list of completers than any of the
completers which generate matches. It can be confused by some of the more
sophisticated forms of completion.
)
enditem()
texinode(Completion Functions)()(Control Functions)(Completion System)

View file

@ -140,6 +140,12 @@ with tt(${).
)
enditem()
)
item(tt(vared))(
If completion is called while editing a line using the tt(vared)
builtin, the value of this key is set to the name of the parameter
given as argument to tt(vared). If tt(vared) is not currently used,
this key is unset.
)
item(tt(parameter))(
The name of the parameter when completing in a subscript or in the
value of a parameter assignment.
@ -340,7 +346,7 @@ xitem([ tt(-W) var(file-prefix) ])
xitem([ tt(-J) var(name) ] [ tt(-V) var(name) ] [ tt(-X) var(explanation) ])
xitem([ tt(-r) var(remove-chars) ] [ tt(-R) var(remove-func) ])
xitem([ tt(-M) var(match-spec) ] [ tt(-O) var(array) ] [ tt(-A) var(array) ])
item([ tt(--) ] [ var(words) ... ])(
item([ tt(-D) var(array) ] [ tt(--) ] [ var(words) ... ])(
This builtin command can be used to add matches directly and control
all the information the completion code stores with each possible
@ -518,6 +524,13 @@ on the command line and the string `tt(foo)' as one of the var(words), this
option stores the string `tt(nofoo)' in the array, whereas the tt(-O)
option stores the `tt(foo)' originally given.
)
item(tt(-D) var(array))(
As with tt(-O), the var(words) are not added to the set of possible
completions. Instead, the completion code tests every var(word) if
it matches what is on the line. If the var(n)'th var(word) does not
match, the var(n)'th element of the var(array) is removed. Elements
for which the corresponding var(word) is matched are retained.
)
item(tt(-), tt(--))(
This flag ends the list of flags and options. All arguments after it
will be taken as the words to use as matches even if they begin with

View file

@ -361,6 +361,7 @@ the parameter is then substituted.
item(tt(${)var(name)tt(:?)var(word)tt(}))(
If var(name) is set and is non-null, then substitute
its value; otherwise, print var(word) and exit from the shell.
Interactive shells do not exit.
If var(word) is omitted, then a standard message is printed.
)
item(tt(${)var(name)tt(:PLUS())var(word)tt(}))(
@ -596,11 +597,12 @@ Pad the resulting words on the left. Each word will be truncated if
required and placed in a field var(expr) characters wide. The space
to the left will be filled with var(string1) (concatenated as often
as needed) or spaces if var(string1) is not given. If both
var(string1) and var(string2) are given, this string will be placed
exactly once directly to the left of the resulting word.
var(string1) and var(string2) are given, this string is inserted
once directly to the left of each word, before padding.
)
item(tt(r:)var(expr)tt(::)var(string1)tt(::)var(string2)tt(:))(
As tt(l), but pad the words on the right.
As tt(l), but pad the words on the right and insert var(string2)
on the right.
)
item(tt(j:)var(string)tt(:))(
Join the words of arrays together using var(string) as a separator.

View file

@ -670,7 +670,7 @@ tt(trap) and
tt(unset).
)
pindex(PRINT_EIGHT_BIT)
cindex(exit status, printing)
cindex(eight bit characters, printing)
item(tt(PRINT_EIGHT_BIT))(
Print eight bit characters literally in completion lists, etc.
This option is not necessary if your system correctly returns the

View file

@ -180,4 +180,4 @@ the command named in the shell variable tt(READNULLCMD) is assumed.
nofill(tt(< file))
prints the contents of tt(file).
copies the contents of tt(file) to the standard output.

View file

@ -30,22 +30,45 @@
#include "example.mdh"
#include "example.pro"
/* parameters */
static long intparam;
static char *strparam;
static char **arrparam;
/**/
static int
bin_example(char *nam, char **args, char *ops, int func)
{
unsigned char c;
char **oargs = args, **p = arrparam;
long i = 0;
printf("Options: ");
for (c = 32; ++c < 128;)
if (ops[c])
putchar(c);
printf("\nArguments:");
for (; *args; args++) {
for (; *args; i++, args++) {
putchar(' ');
fputs(*args, stdout);
}
printf("\nName: %s\n", nam);
printf("\nInteger Parameter: %ld\n", intparam);
printf("String Parameter: %s\n", strparam ? strparam : "");
printf("Array Parameter:");
if (p)
while (*p) printf(" %s", *p++);
printf("\n");
intparam = i;
zsfree(strparam);
strparam = ztrdup(*oargs ? *oargs : "");
freearray(arrparam);
PERMALLOC {
arrparam = arrdup(oargs);
} LASTALLOC;
return 0;
}
@ -103,6 +126,12 @@ static struct conddef cotab[] = {
CONDDEF("ex", CONDF_INFIX, cond_i_ex, 0, 0, 0),
};
static struct paramdef patab[] = {
INTPARAMDEF("exint", &intparam),
STRPARAMDEF("exstr", &strparam),
ARRPARAMDEF("exarr", &arrparam),
};
static struct funcwrap wrapper[] = {
WRAPDEF(ex_wrapper),
};
@ -120,8 +149,15 @@ setup_example(Module m)
int
boot_example(Module m)
{
intparam = 42;
strparam = ztrdup("example");
arrparam = (char **) zalloc(3 * sizeof(char *));
arrparam[0] = ztrdup("example");
arrparam[1] = ztrdup("array");
arrparam[2] = NULL;
return !(addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)) |
addconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab)) |
addparamdefs(m->nam, patab, sizeof(patab)/sizeof(*patab)) |
!addwrapper(m, wrapper));
}
@ -133,6 +169,7 @@ cleanup_example(Module m)
{
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
deleteconddefs(m->nam, cotab, sizeof(cotab)/sizeof(*cotab));
deleteparamdefs(m->nam, patab, sizeof(patab)/sizeof(*patab));
deletewrapper(m, wrapper);
return 0;
}

View file

@ -2,5 +2,6 @@ autobins="example"
autoinfixconds="ex"
autoprefixconds="len"
autoparams="exint exstr exarr"
objects="example.o"

View file

@ -71,6 +71,9 @@
#ifdef HAVE_POLL_H
# include <poll.h>
#endif
#if defined(HAVE_POLL) && !defined(POLLIN) && !defined(POLLNORM)
# undef HAVE_POLL
#endif
/* pinch the definition from <netinet/in.h> for deficient headers */
#ifndef INADDR_NONE

View file

@ -270,6 +270,31 @@ struct cpattern {
#define CAF_ALT 4
#define CAF_MATCH 8
/* Data for compadd and addmatches() */
typedef struct cadata *Cadata;
struct cadata {
char *ipre; /* ignored prefix (-i) */
char *isuf; /* ignored suffix (-I) */
char *ppre; /* `path' prefix (-p) */
char *psuf; /* `path' suffix (-s) */
char *prpre; /* expanded `path' prefix (-W) */
char *pre; /* prefix to insert (-P) */
char *suf; /* suffix to insert (-S) */
char *group; /* name of the group (-[JV]) */
char *rems; /* remove suffix on chars... (-r) */
char *remf; /* function to remove suffix (-R) */
char *ign; /* ignored suffixes (-F) */
int flags; /* CMF_* flags (-[fqn]) */
int aflags; /* CAF_* flags (-[QUa]) */
Cmatcher match; /* match spec (parsed from -M) */
char *exp; /* explanation (-X) */
char *apar; /* array to store matches in (-A) */
char *opar; /* array to store originals in (-O) */
char *dpar; /* array to delete non-matches in (-D) */
};
/* Flags for special parameters. */
#define CP_WORDS (1 << 0)
@ -306,7 +331,8 @@ struct cpattern {
#define CP_TOEND (1 << 28)
#define CP_OLDLIST (1 << 29)
#define CP_OLDINS (1 << 30)
#define CP_VARED (1 << 31)
#define CP_NUM 31
#define CP_NUM 32
#define CP_ALLMASK ((int) ((((unsigned int) 1) << CP_NUM) - 1))
#define CP_ALLMASK ((unsigned int) 0xffffffff)

View file

@ -52,7 +52,7 @@ void (*comp_setunsetptr) _((int, int));
/* pointers to functions required by compctl and defined by zle */
/**/
int (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, char *, char *, char *, char *, int, int, Cmatcher, char *, char *, char *, char **));
int (*addmatchesptr) _((Cadata, char **));
/**/
char *(*comp_strptr) _((int *, int *, int));
@ -129,7 +129,8 @@ char **compwords,
*complastprompt,
*comptoend,
*compoldlist,
*compoldins;
*compoldins,
*compvared;
/**/
Param *comppms;
@ -445,7 +446,7 @@ setup_comp1(Module m)
compquoting = comprestore = complist = compinsert =
compexact = compexactstr = comppatmatch = comppatinsert =
compforcelist = complastprompt = comptoend =
compoldlist = compoldins = NULL;
compoldlist = compoldins = compvared = NULL;
makecompparamsptr = NULL;
comp_setunsetptr = NULL;
return 0;
@ -497,6 +498,7 @@ finish_comp1(Module m)
zsfree(comptoend);
zsfree(compoldlist);
zsfree(compoldins);
zsfree(compvared);
return 0;
}

View file

@ -41,6 +41,7 @@ comp_setunsetptr
comp_strptr
compsuffix
comptoend
compvared
compwords
freecmatcher
freecmlist

View file

@ -1691,17 +1691,22 @@ bin_compgen(char *name, char **argv, char *ops, int func)
static int
bin_compadd(char *name, char **argv, char *ops, int func)
{
char *p, **sp, *e;
char *ipre = NULL, *isuf = NULL, *ppre = NULL, *psuf = NULL, *prpre = NULL;
char *pre = NULL, *suf = NULL, *group = NULL, *m = NULL, *rs = NULL;
char *ign = NULL, *rf = NULL, *expl = NULL, *apar = NULL, *opar = NULL;
int f = 0, a = CAF_MATCH, dm;
struct cadata dat;
char *p, **sp, *e, *m = NULL;
int dm;
Cmatcher match = NULL;
if (incompfunc != 1) {
zerrnam(name, "can only be called from completion function", NULL, 0);
return 1;
}
dat.ipre = dat.isuf = dat.ppre = dat.psuf = dat.prpre =
dat.pre = dat.suf = dat.group = dat.rems = dat.remf =
dat.ign = dat.exp = dat.apar = dat.opar = dat.dpar = NULL;
dat.match = NULL;
dat.flags = 0;
dat.aflags = CAF_MATCH;
for (; *argv && **argv == '-'; argv++) {
if (!(*argv)[1]) {
argv++;
@ -1713,64 +1718,64 @@ bin_compadd(char *name, char **argv, char *ops, int func)
dm = 0;
switch (*p) {
case 'q':
f |= CMF_REMOVE;
dat.flags |= CMF_REMOVE;
break;
case 'Q':
a |= CAF_QUOTE;
dat.aflags |= CAF_QUOTE;
break;
case 'f':
f |= CMF_FILE;
dat.flags |= CMF_FILE;
break;
case 'F':
sp = &ign;
sp = &(dat.ign);
e = "string expected after -%c";
break;
case 'n':
f |= CMF_NOLIST;
dat.flags |= CMF_NOLIST;
break;
case 'U':
a &= ~CAF_MATCH;
dat.aflags &= ~CAF_MATCH;
break;
case 'P':
sp = &pre;
sp = &(dat.pre);
e = "string expected after -%c";
break;
case 'S':
sp = &suf;
sp = &(dat.suf);
e = "string expected after -%c";
break;
case 'J':
sp = &group;
sp = &(dat.group);
e = "group name expected after -%c";
break;
case 'V':
if (!group)
a |= CAF_NOSORT;
sp = &group;
if (!dat.group)
dat.aflags |= CAF_NOSORT;
sp = &(dat.group);
e = "group name expected after -%c";
break;
case 'i':
sp = &ipre;
sp = &(dat.ipre);
e = "string expected after -%c";
break;
case 'I':
sp = &isuf;
sp = &(dat.isuf);
e = "string expected after -%c";
break;
case 'p':
sp = &ppre;
sp = &(dat.ppre);
e = "string expected after -%c";
break;
case 's':
sp = &psuf;
sp = &(dat.psuf);
e = "string expected after -%c";
break;
case 'W':
sp = &prpre;
sp = &(dat.prpre);
e = "string expected after -%c";
break;
case 'a':
a |= CAF_ALT;
dat.aflags |= CAF_ALT;
break;
case 'M':
sp = &m;
@ -1778,25 +1783,29 @@ bin_compadd(char *name, char **argv, char *ops, int func)
dm = 1;
break;
case 'X':
sp = &expl;
sp = &(dat.exp);
e = "string expected after -%c";
break;
case 'r':
f |= CMF_REMOVE;
sp = &rs;
dat.flags |= CMF_REMOVE;
sp = &(dat.rems);
e = "string expected after -%c";
break;
case 'R':
f |= CMF_REMOVE;
sp = &rf;
dat.flags |= CMF_REMOVE;
sp = &(dat.remf);
e = "function name expected after -%c";
break;
case 'A':
sp = &apar;
sp = &(dat.apar);
e = "parameter name expected after -%c";
break;
case 'O':
sp = &opar;
sp = &(dat.opar);
e = "parameter name expected after -%c";
break;
case 'D':
sp = &(dat.dpar);
e = "parameter name expected after -%c";
break;
case '-':
@ -1830,12 +1839,11 @@ bin_compadd(char *name, char **argv, char *ops, int func)
if (!*argv)
return 1;
match = cpcmatcher(match);
a = addmatchesptr(ipre, isuf, ppre, psuf, prpre, pre, suf, group,
rs, rf, ign, f, a, match, expl, apar, opar, argv);
dat.match = match = cpcmatcher(match);
dm = addmatchesptr(&dat, argv);
freecmatcher(match);
return a;
return dm;
}
#define CVT_RANGENUM 0
@ -2165,6 +2173,7 @@ static struct compparam {
{ "to_end", PM_SCALAR, VAL(comptoend), NULL, NULL },
{ "old_list", PM_SCALAR, VAL(compoldlist), NULL, NULL },
{ "old_insert", PM_SCALAR, VAL(compoldins), NULL, NULL },
{ "vared", PM_SCALAR, VAL(compvared), NULL, NULL },
{ NULL, 0, NULL, NULL, NULL }
};
@ -2308,7 +2317,7 @@ compunsetfn(Param pm, int exp)
/**/
void
comp_setunset(int set, int unset)
comp_setunset(unsigned int set, unsigned int unset)
{
Param *p;
@ -2334,11 +2343,11 @@ comp_wrapper(List list, FuncWrap w, char *name)
else {
char *orest, *opre, *osuf, *oipre, *oisuf, **owords;
long ocur;
int unset = 0, m, sm;
unsigned int unset = 0, m, sm;
Param *pp;
m = CP_WORDS | CP_CURRENT | CP_PREFIX | CP_SUFFIX |
CP_IPREFIX | CP_RESTORE;
CP_IPREFIX | CP_ISUFFIX | CP_RESTORE;
for (pp = comppms, sm = 1; m; pp++, m >>= 1, sm <<= 1) {
if ((m & 1) && ((*pp)->flags & PM_UNSET))
unset |= sm;
@ -2373,7 +2382,8 @@ comp_wrapper(List list, FuncWrap w, char *name)
} LASTALLOC;
comp_setunset(CP_COMPSTATE |
(~unset & (CP_WORDS | CP_CURRENT | CP_PREFIX |
CP_SUFFIX | CP_IPREFIX | CP_RESTORE)),
CP_SUFFIX | CP_IPREFIX | CP_ISUFFIX |
CP_RESTORE)),
unset);
} else
comp_setunset(CP_COMPSTATE | (~unset & CP_RESTORE),

View file

@ -1,6 +1,6 @@
moddeps="comp1"
autobins="compctl complist compadd compset"
autobins="compctl compgen compadd compset"
autoprefixconds="prefix suffix between after"

View file

@ -413,7 +413,6 @@ zleread(char *lp, char *rp, int flags)
baud = getiparam("BAUD");
costmult = (baud) ? 3840000L / baud : 0;
tv.tv_sec = 0;
#endif
/* ZLE doesn't currently work recursively. This is needed in case a *
@ -523,6 +522,7 @@ zleread(char *lp, char *rp, int flags)
#ifdef HAVE_SELECT
if (baud && !(lastcmd & ZLE_MENUCMP)) {
FD_SET(SHTTY, &foofd);
tv.tv_sec = 0;
if ((tv.tv_usec = cost * costmult) > 500000)
tv.tv_usec = 500000;
if (!kungetct && select(SHTTY+1, (SELECT_ARG_2_T) & foofd,
@ -656,14 +656,18 @@ handleprefixes(void)
initmodifier(&zmod);
}
/* this exports the argument we are currently vared'iting if != NULL */
/**/
char *varedarg;
/* vared: edit (literally) a parameter value */
/**/
static int
bin_vared(char *name, char **args, char *ops, int func)
{
char *s;
char *t;
char *s, *t, *ova = varedarg;
Value v;
Param pm = 0;
int create = 0;
@ -753,7 +757,9 @@ bin_vared(char *name, char **args, char *ops, int func)
PERMALLOC {
pushnode(bufstack, ztrdup(s));
} LASTALLOC;
varedarg = *args;
t = (char *) zleread(p1, p2, ops['h'] ? ZLRF_HISTORY : 0);
varedarg = ova;
if (!t || errflag) {
/* error in editing */
errflag = 0;
@ -927,6 +933,8 @@ setup_zle(Module m)
/* initialise the keymap system */
init_keymaps();
varedarg = NULL;
return 0;
}

View file

@ -611,7 +611,7 @@ Thingy
executenamedcommand(char *prmt)
{
Thingy cmd;
int len, l = strlen(prmt);
int len, l = strlen(prmt), ols = listshown;
char *ptr;
char *okeymap = curkeymapname;
@ -629,6 +629,10 @@ executenamedcommand(char *prmt)
if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) {
statusline = NULL;
selectkeymap(okeymap, 1);
if ((listshown = ols))
showinglist = -2;
else
clearlist = 1;
return NULL;
}
if(cmd == Th(z_clearscreen)) {
@ -669,6 +673,10 @@ executenamedcommand(char *prmt)
unrefthingy(r);
statusline = NULL;
selectkeymap(okeymap, 1);
if ((listshown = ols))
showinglist = -2;
else
clearlist = 1;
return r;
}
unrefthingy(r);

View file

@ -96,6 +96,7 @@ static int more_start, /* more text before start of screen? */
olnct, /* previous number of lines */
ovln, /* previous video cursor position line */
lpromptw, rpromptw, /* prompt widths on screen */
lpromptwof, /* left prompt width with real end position */
lprompth, /* lines taken up by the prompt */
rprompth, /* right prompt height */
vcs, vln, /* video cursor position column & line */
@ -141,8 +142,14 @@ resetvideo(void)
*obuf[ln] = '\0';
}
countprompt(lpromptbuf, &lpromptw, &lprompth);
countprompt(rpromptbuf, &rpromptw, &rprompth);
countprompt(lpromptbuf, &lpromptwof, &lprompth, 1);
countprompt(rpromptbuf, &rpromptw, &rprompth, 0);
if (lpromptwof != winw)
lpromptw = lpromptwof;
else {
lpromptw = 0;
lprompth++;
}
if (lpromptw) {
memset(nbuf[0], ' ', lpromptw);
@ -271,7 +278,7 @@ zrefresh(void)
clearflag = 0;
resetneeded = 1;
}
listshown = 0;
listshown = showinglist = 0;
}
clearlist = 0;
@ -327,7 +334,7 @@ zrefresh(void)
vcs = 0;
else if (!clearflag && lpromptbuf[0]) {
zputs(lpromptbuf, shout);
if (lpromptw == 0 && lprompth == 1)
if (lpromptwof == winw)
zputs("\n", shout); /* works with both hasam and !hasam */
}
if (clearflag) {
@ -947,7 +954,7 @@ tc_rightcurs(int cl)
zputc('\r', shout);
tc_upcurs(lprompth - 1);
zputs(lpromptbuf, shout);
if (lpromptw == 0 && lprompth == 1)
if (lpromptwof == winw)
zputs("\n", shout); /* works with both hasam and !hasam */
}
i = lpromptw;

View file

@ -87,6 +87,10 @@ static int usemenu, useglob, useexact, useline, uselist;
static int oldlist, oldins;
/* Non-zero if we have to redisplay the list of matches. */
static int showagain = 0;
/* The match and group number to insert when starting menucompletion. */
static int insmnum, insgnum, insgroup;
@ -555,7 +559,7 @@ acceptandmenucomplete(void)
/* These are flags saying if we are completing in the command *
* position, in a redirection, or in a parameter expansion. */
static int lincmd, linredir, ispar, linwhat;
static int lincmd, linredir, ispar, linwhat, linarr;
/* The string for the redirection operator. */
@ -758,10 +762,14 @@ docomplete(int lst)
char *s, *ol;
int olst = lst, chl = 0, ne = noerrs, ocs;
if (showagain && validlist)
showinglist = -2;
showagain = 0;
/* If we are doing a menu-completion... */
if (menucmp && lst != COMP_LIST_EXPAND && compwidget &&
compwidget == lastcompwidget) {
if (menucmp && lst != COMP_LIST_EXPAND &&
(!compwidget || compwidget == lastcompwidget)) {
do_menucmp(lst);
return;
}
@ -872,7 +880,7 @@ docomplete(int lst)
}
if (lst == COMP_EXPAND_COMPLETE)
do {
/* check if there is a parameter expresiion. */
/* Check if there is a parameter expression. */
for (; *q && *q != String; q++);
if (*q == String && q[1] != Inpar && q[1] != Inbrack) {
if (*++q == Inbrace) {
@ -1128,7 +1136,7 @@ unmetafy_line(void)
static char *
get_comp_string(void)
{
int t0, tt0, i, j, k, cp, rd, sl, ocs, ins, oins, inarr, ia, parct;
int t0, tt0, i, j, k, cp, rd, sl, ocs, ins, oins, ia, parct;
char *s = NULL, *linptr, *tmp, *p, *tt = NULL;
zsfree(brbeg);
@ -1192,7 +1200,7 @@ get_comp_string(void)
inpush(dupstrspace((char *) linptr), 0, NULL);
strinbeg();
stophist = 2;
i = tt0 = cp = rd = ins = oins = inarr = parct = ia = 0;
i = tt0 = cp = rd = ins = oins = linarr = parct = ia = 0;
/* This loop is possibly the wrong way to do this. It goes through *
* the previously massaged command line using the lexer. It stores *
@ -1211,11 +1219,11 @@ get_comp_string(void)
linredir = (inredir && !ins);
oins = ins;
/* Get the next token. */
if (inarr)
if (linarr)
incmdpos = 0;
ctxtlex();
if (tok == ENVARRAY) {
inarr = 1;
linarr = 1;
zsfree(varname);
varname = ztrdup(tokstr);
} else if (tok == INPAR)
@ -1224,7 +1232,7 @@ get_comp_string(void)
if (parct)
parct--;
else
inarr = 0;
linarr = 0;
}
if (inredir)
rdstr = tokstrings[tok];
@ -1267,7 +1275,7 @@ get_comp_string(void)
clwpos = i;
cp = lincmd;
rd = linredir;
ia = inarr;
ia = linarr;
if (inwhat == IN_NOTHING && incond)
inwhat = IN_COND;
} else if (linredir)
@ -1515,12 +1523,53 @@ get_comp_string(void)
*/
for (i = 0, p = s; *p; p++, i++) {
/* careful, ${... is not a brace expansion...
* in fact, if it's got a substitution in it's too
* hard for us anyway. sorry.
* we try to get braces after a parameter expansion right,
* but this may fail sometimes. sorry.
*/
if (*p == String || *p == Qstring) {
tt = NULL;
break;
if (p[1] == Inbrace || p[1] == Inpar || p[1] == Inbrack) {
char *tp = p + 1;
if (skipparens(*tp, (*tp == Inbrace ? Outbrace :
(*tp == Inpar ? Outpar : Outbrack)),
&tp)) {
tt = NULL;
break;
}
i += tp - p;
p = tp;
} else {
char *tp = p + 1;
for (; *tp == '^' || *tp == Hat ||
*tp == '=' || *tp == Equals ||
*tp == '~' || *tp == Tilde ||
*tp == '#' || *tp == Pound || *tp == '+';
tp++);
if (*tp == Quest || *tp == Star || *tp == String ||
*tp == Qstring || *tp == '?' || *tp == '*' ||
*tp == '$' || *tp == '-' || *tp == '!' ||
*tp == '@')
p++, i++;
else {
if (idigit(*tp))
while (idigit(*tp))
tp++;
else if (iident(*tp))
while (iident(*tp))
tp++;
else {
tt = NULL;
break;
}
if (*tp == Inbrace) {
tt = NULL;
break;
}
tp--;
i += tp - p;
p = tp;
}
}
} else if (*p == Inbrace) {
if (tt) {
/* too many inbraces */
@ -3472,14 +3521,10 @@ set_param(char *name, LinkList l)
/**/
int
addmatches(char *ipre, char *isuf,
char *ppre, char *psuf, char *prpre, char *pre,
char *suf, char *group, char *rems, char *remf, char *ign,
int flags, int aflags, Cmatcher match, char *exp,
char *apar, char *opar, char **argv)
addmatches(Cadata dat, char **argv)
{
char *s, *ms, *lipre = NULL, *lisuf = NULL, *lpre = NULL, *lsuf = NULL;
char **aign = NULL;
char **aign = NULL, **dparr;
int lpl, lsl, pl, sl, bpl, bsl, llpl = 0, llsl = 0, nm = mnum;
int oisalt = 0, isalt, isexact, doadd;
Cline lc = NULL;
@ -3487,45 +3532,52 @@ addmatches(char *ipre, char *isuf,
struct cmlist mst;
Cmlist oms = mstack;
Comp cp = NULL;
LinkList aparl = NULL, oparl = NULL;
LinkList aparl = NULL, oparl = NULL, dparl = NULL;
/* Switch back to the heap that was used when the completion widget
* was invoked. */
SWITCHHEAPS(compheap) {
HEAPALLOC {
doadd = (!apar && !opar);
if (apar)
doadd = (!dat->apar && !dat->opar && !dat->dpar);
if (dat->apar)
aparl = newlinklist();
if (opar)
if (dat->opar)
oparl = newlinklist();
if (exp) {
if (dat->dpar) {
if (*(dat->dpar) == '(')
dparr = NULL;
else if ((dparr = get_user_var(dat->dpar)) && !*dparr)
dparr = NULL;
dparl = newlinklist();
}
if (dat->exp) {
expl = (Cexpl) zhalloc(sizeof(struct cexpl));
expl->count = expl->fcount = 0;
expl->str = dupstring(exp);
expl->str = dupstring(dat->exp);
} else
expl = NULL;
/* Store the matcher in our stack of matchers. */
if (match) {
if (dat->match) {
mst.next = mstack;
mst.matcher = match;
mst.matcher = dat->match;
mstack = &mst;
if (!mnum)
add_bmatchers(match);
add_bmatchers(dat->match);
addlinknode(matchers, match);
match->refc++;
addlinknode(matchers, dat->match);
dat->match->refc++;
}
if (mnum && (mstack || bmatchers))
update_bmatchers();
/* Get the suffixes to ignore. */
if (ign)
aign = get_user_var(ign);
if (dat->ign)
aign = get_user_var(dat->ign);
/* Get the contents of the completion variables if we have
* to perform matching. */
if (aflags & CAF_MATCH) {
if (dat->aflags & CAF_MATCH) {
lipre = dupstring(compiprefix);
lisuf = dupstring(compisuffix);
lpre = dupstring(compprefix);
@ -3533,8 +3585,8 @@ addmatches(char *ipre, char *isuf,
llpl = strlen(lpre);
llsl = strlen(lsuf);
/* Test if there is an existing -P prefix. */
if (pre && *pre) {
pl = pfxlen(pre, lpre);
if (dat->pre && *dat->pre) {
pl = pfxlen(dat->pre, lpre);
llpl -= pl;
lpre += pl;
}
@ -3557,79 +3609,76 @@ addmatches(char *ipre, char *isuf,
}
}
/* Now duplicate the strings we have from the command line. */
if (ipre)
ipre = (lipre ? dyncat(lipre, ipre) : dupstring(ipre));
if (dat->ipre)
dat->ipre = (lipre ? dyncat(lipre, dat->ipre) :
dupstring(dat->ipre));
else if (lipre)
ipre = lipre;
if (isuf)
isuf = (lisuf ? dyncat(lisuf, isuf) : dupstring(isuf));
dat->ipre = lipre;
if (dat->isuf)
dat->isuf = (lisuf ? dyncat(lisuf, dat->isuf) :
dupstring(dat->isuf));
else if (lisuf)
isuf = lisuf;
if (ppre) {
ppre = dupstring(ppre);
lpl = strlen(ppre);
dat->isuf = lisuf;
if (dat->ppre) {
dat->ppre = dupstring(dat->ppre);
lpl = strlen(dat->ppre);
} else
lpl = 0;
if (psuf) {
psuf = dupstring(psuf);
lsl = strlen(psuf);
if (dat->psuf) {
dat->psuf = dupstring(dat->psuf);
lsl = strlen(dat->psuf);
} else
lsl = 0;
if (aflags & CAF_MATCH) {
s = ppre ? ppre : "";
if (llpl <= lpl && strpfx(lpre, s)) {
llpl = 0;
if (dat->aflags & CAF_MATCH) {
s = dat->ppre ? dat->ppre : "";
if (llpl <= lpl && strpfx(lpre, s))
lpre = "";
} else if (llpl > lpl && strpfx(s, lpre)) {
llpl -= lpl;
else if (llpl > lpl && strpfx(s, lpre))
lpre += lpl;
} else
else
*argv = NULL;
s = psuf ? psuf : "";
if (llsl <= lsl && strsfx(lsuf, s)) {
llsl = 0;
s = dat->psuf ? dat->psuf : "";
if (llsl <= lsl && strsfx(lsuf, s))
lsuf = "";
} else if (llsl > lsl && strsfx(s, lsuf)) {
else if (llsl > lsl && strsfx(s, lsuf))
lsuf[llsl - lsl] = '\0';
llsl -= lsl;
} else
else
*argv = NULL;
}
if (*argv) {
if (pre)
pre = dupstring(pre);
if (suf)
suf = dupstring(suf);
if (!prpre && (prpre = ppre)) {
singsub(&prpre);
untokenize(prpre);
if (dat->pre)
dat->pre = dupstring(dat->pre);
if (dat->suf)
dat->suf = dupstring(dat->suf);
if (!dat->prpre && (dat->prpre = dat->ppre)) {
singsub(&(dat->prpre));
untokenize(dat->prpre);
} else
prpre = dupstring(prpre);
dat->prpre = dupstring(dat->prpre);
/* Select the group in which to store the matches. */
if (group) {
if (dat->group) {
endcmgroup(NULL);
begcmgroup(group, (aflags & CAF_NOSORT));
if (aflags & CAF_NOSORT)
begcmgroup(dat->group, (dat->aflags & CAF_NOSORT));
if (dat->aflags & CAF_NOSORT)
mgroup->flags |= CGF_NOSORT;
} else {
endcmgroup(NULL);
begcmgroup("default", 0);
}
/* Select the set of matches. */
oisalt = (aflags & CAF_ALT);
oisalt = (dat->aflags & CAF_ALT);
if (remf) {
remf = dupstring(remf);
rems = NULL;
} else if (rems)
rems = dupstring(rems);
if (dat->remf) {
dat->remf = dupstring(dat->remf);
dat->rems = NULL;
} else if (dat->rems)
dat->rems = dupstring(dat->rems);
/* Probably quote the prefix and suffix for testing. */
if (!cp && (aflags & CAF_MATCH) && !(aflags & CAF_QUOTE)) {
if (!cp && (dat->aflags & CAF_MATCH) &&
!(dat->aflags & CAF_QUOTE)) {
lpre = quotename(lpre, NULL);
lsuf = quotename(lsuf, NULL);
llpl = strlen(lpre);
llsl = strlen(lsuf);
}
}
/* Walk through the matches given. */
@ -3638,7 +3687,7 @@ addmatches(char *ipre, char *isuf,
bpl = brpl;
bsl = brsl;
isalt = oisalt;
if ((!psuf || !*psuf) && aign) {
if ((!dat->psuf || !*(dat->psuf)) && aign) {
/* Do the suffix-test. If the match has one of the
* suffixes from ign, we put it in the alternate set. */
char **pt = aign;
@ -3649,39 +3698,52 @@ addmatches(char *ipre, char *isuf,
&& !strcmp(*pt, s + sl - filell))
isalt = 1;
if (isalt && !doadd)
if (isalt && !doadd) {
if (dparr && !*++dparr)
dparr = NULL;
continue;
}
}
if (!(aflags & CAF_MATCH)) {
if (!(dat->aflags & CAF_MATCH)) {
ms = dupstring(s);
lc = bld_parts(ms, sl, -1, NULL);
isexact = 0;
} else if (!(ms = comp_match(lpre, lsuf, s, cp, &lc,
!(aflags & CAF_QUOTE),
&bpl, &bsl, &isexact)))
!(dat->aflags & CAF_QUOTE),
&bpl, &bsl, &isexact))) {
if (dparr && !*++dparr)
dparr = NULL;
continue;
}
if (doadd) {
cm = add_match_data(isalt, ms, lc, ipre, ipre, isuf, pre,
prpre, ppre, psuf, suf, bpl, bsl,
flags, isexact);
cm->rems = rems;
cm->remf = remf;
cm = add_match_data(isalt, ms, lc, dat->ipre, dat->ipre,
dat->isuf, dat->pre, dat->prpre,
dat->ppre, dat->psuf, dat->suf,
bpl, bsl, dat->flags, isexact);
cm->rems = dat->rems;
cm->remf = dat->remf;
} else {
if (apar)
if (dat->apar)
addlinknode(aparl, ms);
if (opar)
if (dat->opar)
addlinknode(oparl, s);
if (dat->dpar && dparr) {
addlinknode(dparl, *dparr);
if (!*++dparr)
dparr = NULL;
}
free_cline(lc);
}
}
compnmatches = mnum;
if (exp)
if (dat->exp)
addexpl();
if (apar)
set_param(apar, aparl);
if (opar)
set_param(opar, oparl);
if (dat->apar)
set_param(dat->apar, aparl);
if (dat->opar)
set_param(dat->opar, oparl);
if (dat->dpar)
set_param(dat->dpar, dparl);
} LASTALLOC;
} SWITCHBACKHEAPS;
@ -4128,6 +4190,7 @@ docompletion(char *s, int lst, int incmd)
(unset(ALWAYSLASTPROMPT) && zmult != 1)) ?
"yes" : "");
movetoend = ((cs == we || isset(ALWAYSTOEND)) ? 2 : 1);
showinglist = 0;
/* Make sure we have the completion list and compctl. */
if (makecomplist(s, incmd, lst)) {
@ -4217,14 +4280,22 @@ callcompfunc(char *s, char *fn)
if ((list = getshfunc(fn)) != &dummy_list) {
char **p, *tmp;
int set, aadd = 0, usea = 1, icf = incompfunc, osc = sfcontext;
int aadd = 0, usea = 1, icf = incompfunc, osc = sfcontext;
unsigned int set;
Param *ocpms = comppms;
comppms = (Param *) zalloc(CP_NUM * sizeof(Param));
set = -1 & ~(CP_PARAMETER | CP_REDIRECT | CP_QUOTE | CP_QUOTING |
CP_EXACTSTR | CP_FORCELIST | CP_OLDLIST | CP_OLDINS |
(useglob ? 0 : CP_PATMATCH));
set = CP_ALLMASK &
~(CP_PARAMETER | CP_REDIRECT | CP_QUOTE | CP_QUOTING |
CP_EXACTSTR | CP_FORCELIST | CP_OLDLIST | CP_OLDINS |
(useglob ? 0 : CP_PATMATCH));
zsfree(compvared);
if (varedarg) {
compvared = ztrdup(varedarg);
set |= CP_VARED;
} else
compvared = ztrdup("");
if (!*complastprompt)
set &= ~CP_LASTPROMPT;
zsfree(compcontext);
@ -4257,7 +4328,7 @@ callcompfunc(char *s, char *fn)
} else
switch (linwhat) {
case IN_ENV:
compcontext = "array_value";
compcontext = (linarr ? "array_value" : "value");
compparameter = varname;
set |= CP_PARAMETER;
if (!clwpos) {
@ -4551,6 +4622,7 @@ makecomplist(char *s, int incmd, int lst)
insmnum = insgnum = 1;
insgroup = oldlist = oldins = 0;
begcmgroup("default", 0);
menucmp = 0;
ccused = newlinklist();
ccstack = newlinklist();
@ -6717,11 +6789,13 @@ unambig_data(int *cp)
return scache;
}
/* Insert the given match. This returns the number of characters inserted.*/
/* Insert the given match. This returns the number of characters inserted.
* scs is used to return the position where a automatically created suffix
* has to be inserted. */
/**/
static int
instmatch(Cmatch m)
instmatch(Cmatch m, int *scs)
{
int l, r = 0, ocs, a = cs;
@ -6771,6 +6845,7 @@ instmatch(Cmatch m)
} else
brscs = -1;
/* -S suffix */
*scs = cs;
if (m->suf) {
inststrlen(m->suf, 1, (l = strlen(m->suf)));
r += l;
@ -6842,13 +6917,13 @@ do_ambiguous(void)
/* If REC_EXACT and AUTO_MENU are set and what we inserted is an *
* exact match, we want menu completion the next time round *
* so we set fromcomp,to ensure that the word on the line is not *
* so we set fromcomp, to ensure that the word on the line is not *
* taken as an exact match. Also we remember if we just moved the *
* cursor into the word. */
fromcomp = ((isset(AUTOMENU) ? FC_LINE : 0) |
((atend && cs != lastend) ? FC_INWORD : 0));
/* Probably move the cursor to then end. */
/* Probably move the cursor to the end. */
if (movetoend == 3)
cs = lastend;
@ -6907,7 +6982,7 @@ ztat(char *nam, struct stat *buf, int ls)
static void
do_single(Cmatch m)
{
int l, sr = 0;
int l, sr = 0, scs;
int havesuff = 0;
char *str = m->str, *ppre = m->ppre, *psuf = m->psuf, *prpre = m->prpre;
@ -6937,7 +7012,7 @@ do_single(Cmatch m)
foredel(l);
/* And then we insert the new string. */
menulen = instmatch(m);
menulen = instmatch(m, &scs);
menuend = cs;
cs = menupos + menulen;
@ -6956,6 +7031,7 @@ do_single(Cmatch m)
} else {
/* There is no user-specified suffix, *
* so generate one automagically. */
cs = scs;
if (m->ripre && (m->flags & CMF_PARBR)) {
/*{{*/
/* Completing a parameter in braces. Add a removable `}' suffix. */
@ -7006,6 +7082,8 @@ do_single(Cmatch m)
}
}
}
if (!menuinsc)
cs = menupos + menulen;
}
/* If completing in a brace expansion... */
if (brbeg) {
@ -7018,7 +7096,7 @@ do_single(Cmatch m)
} else if (!menucmp) {
/*{{*/
/* Otherwise, add a `,' suffix, and let `}' remove it. */
cs = menuend;
cs = scs;
havesuff = 1;
inststrlen(",", 1, 1);
menuinsc++;
@ -7492,7 +7570,12 @@ listlist(LinkList l)
struct cmgroup dg;
Cmgroup am = amatches;
int vl = validlist, sm = smatches;
char *oclp = complastprompt;
if (listshown)
showagain = 1;
complastprompt = ((zmult == 1) == !!isset(ALWAYSLASTPROMPT) ? "yes" : NULL);
smatches = 1;
validlist = 1;
amatches = &dg;
@ -7503,6 +7586,7 @@ listlist(LinkList l)
amatches = am;
validlist = vl;
smatches = sm;
complastprompt = oclp;
}
/* Expand the history references. */

View file

@ -120,7 +120,7 @@ static struct builtin builtins[] =
BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsw", "c"),
#ifdef DYNAMIC
BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "LaudicI", NULL),
BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "LaudicIp", NULL),
#endif
};
@ -1485,7 +1485,7 @@ typeset_single(char *cname, char *pname, Param pm, int func,
int usepm, tc, keeplocal = 0;
/* use the existing pm? */
usepm = pm && !(pm->flags & PM_UNSET);
usepm = pm && !(pm->flags & (PM_UNSET | PM_AUTOLOAD));
/* Always use an existing pm if special at current locallevel */
if (pm && (pm->flags & PM_SPECIAL) && pm->level == locallevel)
@ -1793,7 +1793,9 @@ bin_typeset(char *name, char **argv, char *ops, int func)
continue;
}
if (!typeset_single(name, asg->name,
(Param)paramtab->getnode(paramtab, asg->name),
(Param) (paramtab == realparamtab ?
gethashnode2(paramtab, asg->name) :
paramtab->getnode(paramtab, asg->name)),
func, on, off, roff, asg->value, NULL))
returnval = 1;
}
@ -1945,7 +1947,7 @@ bin_unset(char *name, char **argv, char *ops, int func)
next = (Param) pm->next;
if ((!(pm->flags & PM_RESTRICTED) ||
unset(RESTRICTED)) && domatch(pm->nam, com, 0)) {
unsetparam(pm->nam);
unsetparam_pm(pm, 0, 1);
match++;
}
}
@ -1974,7 +1976,9 @@ bin_unset(char *name, char **argv, char *ops, int func)
}
*ss = 0;
}
pm = (Param) paramtab->getnode(paramtab, s);
pm = (Param) (paramtab == realparamtab ?
gethashnode2(paramtab, s) :
paramtab->getnode(paramtab, s));
if (!pm)
returnval = 1;
else if ((pm->flags & PM_RESTRICTED) && isset(RESTRICTED)) {

View file

@ -3379,16 +3379,14 @@ tokenize(char *s)
*t = Inang;
*s = Outang;
break;
case '^':
case '#':
case '~':
if (unset(EXTENDEDGLOB))
break;
case '(':
case '|':
case ')':
if (isset(SHGLOB))
break;
case '^':
case '#':
case '~':
case '[':
case ']':
case '*':

View file

@ -24,7 +24,7 @@ for x_mod in $x_mods; do
*" $x_mod "*) ;;
*) echo "/* non-linked-in known module \`$x_mod' */"
eval "loc=\$loc_$x_mod"
unset moddeps autobins autoinfixconds autoprefixconds
unset moddeps autobins autoinfixconds autoprefixconds autoparams
. $srcdir/../$loc/${x_mod}.mdd
for bin in $autobins; do
echo " add_autobin(\"$bin\", \"$x_mod\");"
@ -35,6 +35,9 @@ for x_mod in $x_mods; do
for cond in $autoprefixconds; do
echo " add_autocond(\"$cond\", 0, \"$x_mod\");"
done
for param in $autoparams; do
echo " add_autoparam(\"$param\", \"$x_mod\");"
done
for dep in $moddeps; do
case $bin_mods in
*" $dep "*)

View file

@ -24,6 +24,7 @@
# autoinfixconds infix condition codes defined by the module, for
# autoloading (without the leading `-')
# autoprefixconds like autoinfixconds, but for prefix condition codes
# autoparams parameters defined by the module, for autoloading
# objects .o files making up this module (*must* be defined)
# proto .pro files for this module (default generated from $objects)
# headers extra headers for this module (default none)
@ -170,7 +171,7 @@ if $first_stage; then
for module in $here_modules; do
unset moddeps nozshdep alwayslink hasexport
unset autobins autoinfixconds autoprefixconds
unset autobins autoinfixconds autoprefixconds autoparams
unset objects proto headers hdrdeps otherincs
. $top_srcdir/$the_subdir/${module}.mdd
test -n "${moddeps+set}" || moddeps=

View file

@ -539,18 +539,24 @@ load_module(char const *name)
m = zcalloc(sizeof(*m));
m->nam = ztrdup(name);
m->handle = handle;
m->flags |= MOD_SETUP;
PERMALLOC {
node = addlinknode(modules, m);
} LASTALLOC;
if (setup_module(m) || init_module(m)) {
finish_module(m);
remnode(modules, node);
zsfree(m->nam);
zfree(m, sizeof(*m));
m->flags &= ~MOD_SETUP;
return NULL;
}
PERMALLOC {
addlinknode(modules, m);
} LASTALLOC;
m->flags &= ~MOD_SETUP;
return m;
}
m = (Module) getdata(node);
if (m->flags & MOD_SETUP)
return m;
if (m->flags & MOD_UNLOAD)
m->flags &= ~MOD_UNLOAD;
else if (m->handle)
@ -570,17 +576,22 @@ load_module(char const *name)
if (!m->handle) {
if (!(m->handle = do_load_module(name)))
return NULL;
m->flags |= MOD_SETUP;
if (setup_module(m)) {
finish_module(m->handle);
m->handle = NULL;
m->flags &= ~MOD_SETUP;
return NULL;
}
}
m->flags |= MOD_SETUP;
if (init_module(m)) {
finish_module(m->handle);
m->handle = NULL;
m->flags &= ~MOD_SETUP;
return NULL;
}
m->flags &= ~MOD_SETUP;
return m;
}
@ -690,6 +701,8 @@ bin_zmodload(char *nam, char **args, char *ops, int func)
return bin_zmodload_auto(nam, args, ops);
else if (ops['c'] || ops['C'])
return bin_zmodload_cond(nam, args, ops);
else if (ops['p'])
return bin_zmodload_param(nam, args, ops);
else
return bin_zmodload_load(nam, args, ops);
}
@ -888,6 +901,66 @@ bin_zmodload_cond(char *nam, char **args, char *ops)
}
}
static void
printautoparams(HashNode hn, int lon)
{
Param pm = (Param) hn;
if (pm->flags & PM_AUTOLOAD) {
if (lon)
printf("zmodload -p %s %s\n", pm->u.str, pm->nam);
else
printf("%s (%s)\n", pm->nam, pm->u.str);
}
}
/**/
static int
bin_zmodload_param(char *nam, char **args, char *ops)
{
int ret = 0;
if (ops['u']) {
/* remove autoloaded parameters */
for (; *args; args++) {
Param pm = (Param) gethashnode2(paramtab, *args);
if (!pm) {
if (!ops['i']) {
zwarnnam(nam, "%s: no such parameter", *args, 0);
ret = 1;
}
} else if (!(pm->flags & PM_AUTOLOAD)) {
zwarnnam(nam, "%s: parameter is already defined", *args, 0);
ret = 1;
} else
unsetparam_pm(pm, 0, 1);
}
return ret;
} else if (!*args) {
scanhashtable(paramtab, 1, 0, 0, printautoparams, ops['L']);
return 0;
} else {
/* add autoloaded parameters */
char *modnam;
modnam = *args++;
if(isset(RESTRICTED) && strchr(modnam, '/')) {
zwarnnam(nam, "%s: restricted", modnam, 0);
return 1;
}
do {
char *pnam = *args ? *args++ : modnam;
if (strchr(pnam, '/')) {
zwarnnam(nam, "%s: `/' is illegal in a parameter", pnam, 0);
ret = 1;
} else
add_autoparam(pnam, modnam);
} while(*args);
return ret;
}
}
/**/
int
unload_module(Module m, LinkNode node)
@ -1114,6 +1187,71 @@ addconddefs(char const *nam, Conddef c, int size)
return hadf ? hads : 1;
}
/* This adds the given parameter definition. The return value is zero on *
* success and 1 on failure. */
/**/
int
addparamdef(Paramdef d)
{
Param pm;
if ((pm = (Param) gethashnode2(paramtab, d->name)))
unsetparam_pm(pm, 0, 1);
if (!(pm = createparam(d->name, d->flags)) &&
!(pm = (Param) paramtab->getnode(paramtab, d->name)))
return 1;
pm->level = 0;
pm->u.data = d->var;
pm->sets.ifn = (void (*)(Param, long)) d->set;
pm->gets.ifn = (long (*)(Param)) d->get;
pm->unsetfn = (void (*)(Param, int)) d->unset;
return 0;
}
/* This adds multiple parameter definitions. This is like addbuiltins(). */
/**/
int
addparamdefs(char const *nam, Paramdef d, int size)
{
int hads = 0, hadf = 0;
while (size--) {
if (addparamdef(d)) {
zwarnnam(nam, "error when adding parameter `%s'", d->name, 0);
hadf = 1;
} else
hads = 2;
d++;
}
return hadf ? hads : 1;
}
/* Delete parameters defined. No error checking yet. */
/**/
int
deleteparamdef(Paramdef d)
{
unsetparam(d->name);
return 0;
}
/**/
int
deleteparamdefs(char const *nam, Paramdef d, int size)
{
while (size--) {
deleteparamdef(d);
d++;
}
return 1;
}
#ifdef DYNAMIC
/* This adds a definition for autoloading a module for a condition. */
@ -1188,4 +1326,20 @@ deleteconddefs(char const *nam, Conddef c, int size)
return hadf ? hads : 1;
}
/* This adds a definition for autoloading a module for a parameter. */
/**/
void
add_autoparam(char *nam, char *module)
{
Param pm;
if ((pm = (Param) gethashnode2(paramtab, nam)))
unsetparam_pm(pm, 0, 1);
pm = setsparam(ztrdup(nam), ztrdup(module));
pm->flags |= PM_AUTOLOAD;
}
#endif

View file

@ -255,7 +255,11 @@ static Param argvparam;
/* hash table containing the parameters */
/**/
HashTable paramtab;
HashTable paramtab, realparamtab;
#ifndef DYNAMIC
#define getparamnode gethashnode2
#endif /* DYNAMIC */
/**/
HashTable
@ -267,8 +271,8 @@ newparamtable(int size, char const *name)
ht->emptytable = emptyhashtable;
ht->filltable = NULL;
ht->addnode = addhashnode;
ht->getnode = gethashnode2;
ht->getnode2 = gethashnode2;
ht->getnode = getparamnode;
ht->getnode2 = getparamnode;
ht->removenode = removehashnode;
ht->disablenode = NULL;
ht->enablenode = NULL;
@ -278,6 +282,25 @@ newparamtable(int size, char const *name)
return ht;
}
#ifdef DYNAMIC
/**/
static HashNode
getparamnode(HashTable ht, char *nam)
{
HashNode hn = gethashnode2(ht, nam);
Param pm = (Param) hn;
if (pm && pm->u.str && (pm->flags & PM_AUTOLOAD)) {
char *mn = dupstring(pm->u.str);
if (!load_module(mn))
return NULL;
hn = gethashnode2(ht, nam);
}
return hn;
}
#endif /* DYNAMIC */
/* Copy a parameter hash table */
static HashTable outtable;
@ -402,7 +425,7 @@ createparamtable(void)
char buf[50], *str, *iname;
int num_env;
paramtab = newparamtable(151, "paramtab");
paramtab = realparamtab = newparamtable(151, "paramtab");
/* Add the special parameters to the hash table */
for (ip = special_params; ip->nam; ip++)
@ -542,7 +565,9 @@ createparam(char *name, int flags)
Param pm, oldpm;
if (name != nulstring) {
oldpm = (Param) paramtab->getnode(paramtab, name);
oldpm = (Param) (paramtab == realparamtab ?
gethashnode2(paramtab, name) :
paramtab->getnode(paramtab, name));
if (oldpm && oldpm->level == locallevel) {
if (!(oldpm->flags & PM_UNSET) || (oldpm->flags & PM_SPECIAL)) {
@ -2703,6 +2728,8 @@ printparamnode(HashNode hn, int printflags)
/* Print the attributes of the parameter */
if (printflags & PRINT_TYPE) {
if (p->flags & PM_AUTOLOAD)
printf("undefined ");
if (p->flags & PM_INTEGER)
printf("integer ");
else if (p->flags & PM_ARRAY)
@ -2736,6 +2763,11 @@ printparamnode(HashNode hn, int printflags)
}
quotedzputs(p->nam, stdout);
if (p->flags & PM_AUTOLOAD) {
putchar('\n');
return;
}
if (printflags & PRINT_KV_PAIR)
putchar(' ');
else

View file

@ -232,7 +232,7 @@ putpromptchar(int doprint, int endchar)
break;
case 'l':
*bp = '\0';
countprompt(bufline, &t0, 0);
countprompt(bufline, &t0, 0, 0);
if (t0 >= arg)
test = 1;
break;
@ -678,11 +678,15 @@ putstr(int d)
/**/
void
countprompt(char *str, int *wp, int *hp)
countprompt(char *str, int *wp, int *hp, int overf)
{
int w = 0, h = 1;
int s = 1;
for(; *str; str++) {
if(w >= columns) {
w = 0;
h++;
}
if(*str == Meta)
str++;
if(*str == Inpar)
@ -694,12 +698,15 @@ countprompt(char *str, int *wp, int *hp)
else if(s) {
if(*str == '\t')
w = (w | 7) + 1;
else if(*str == '\n')
w = columns;
else
else if(*str == '\n') {
w = 0;
h++;
} else
w++;
}
if(w >= columns) {
}
if(w >= columns) {
if (!overf || w > columns) {
w = 0;
h++;
}

View file

@ -4,6 +4,7 @@ addbuiltins
addconddefs
addedx
addhashnode
addparamdefs
addwrapper
arrvargetfn
arrvarsetfn
@ -40,6 +41,7 @@ current_limits
deletebuiltins
deleteconddefs
deletehashtable
deleteparamdefs
deletewrapper
domatch
doshfunc

View file

@ -231,6 +231,7 @@ typedef struct hashtable *HashTable;
typedef struct reswd *Reswd;
typedef struct alias *Alias;
typedef struct param *Param;
typedef struct paramdef *Paramdef;
typedef struct cmdnam *Cmdnam;
typedef struct shfunc *Shfunc;
typedef struct funcwrap *FuncWrap;
@ -850,6 +851,7 @@ struct module {
#define MOD_BUSY (1<<0)
#define MOD_UNLOAD (1<<1)
#define MOD_SETUP (1<<2)
/* node used in parameter hash table (paramtab) */
@ -923,6 +925,7 @@ struct param {
#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 */
#define PM_AUTOLOAD (1<<18) /* autoloaded from module */
/* Flags for extracting elements of arrays and associative arrays */
#define SCANPM_WANTVALS (1<<0)
@ -955,6 +958,27 @@ struct param {
#define PF_ASSIGN 0x02 /* argument handled like the RHS of foo=bar */
#define PF_SINGLE 0x04 /* single word substitution */
struct paramdef {
char *name;
int flags;
void *var;
void *set;
void *get;
void *unset;
};
#define PARAMDEF(name, flags, var, set, get, unset) \
{ name, flags, (void *) var, (void *) set, (void *) get, (void *) unset }
#define INTPARAMDEF(name, var) \
{ name, PM_INTEGER, (void *) var, (void *) intvarsetfn, \
(void *) intvargetfn, (void *) stdunsetfn }
#define STRPARAMDEF(name, var) \
{ name, PM_SCALAR, (void *) var, (void *) strvarsetfn, \
(void *) strvargetfn, (void *) stdunsetfn }
#define ARRPARAMDEF(name, var) \
{ name, PM_ARRAY, (void *) var, (void *) arrvarsetfn, \
(void *) arrvargetfn, (void *) stdunsetfn }
/* node for named directory hash table (nameddirtab) */
struct nameddir {

View file

@ -127,6 +127,7 @@ variables:
- autoinfixconds infix condition codes defined by the module, for
autoloading (without the leading `-')
- autoprefixconds like autoinfixconds, but for prefix condition codes
- autoparams parameters defined by the module, for autoloading
- objects .o files making up this module (*must* be defined)
- proto .pro files for this module (default generated from $objects)
- headers extra headers for this module (default none)
@ -137,7 +138,7 @@ Be sure to put the values in quotes. For further enlightenment have a
look at the `mkmakemod.sh' script in the Src directory of the
distribution.
Modules have to define four functions which will automatically called
Modules have to define four functions which will be called automatically
by the zsh core. The first one, named `setup_foo' for a module named
`foo', should set up any data needed in the module, at least any data
other modules may be interested in. The second one, named `boot_foo',
@ -323,6 +324,78 @@ almost exactly the same as for builtins, using the functions
Arguments and return values are the same as for the functions for
builtins.
For defining parameters, a module can call `createparam()' directly or
use a table to describe them, e.g.:
static struct paramdef patab[] = {
PARAMDEF("foo", PM_INTEGER, NULL, get_foo, set_foo, unset_foo),
INTPARAMDEF("exint", &intparam),
STRPARAMDEF("exstr", &strparam),
ARRPARAMDEF("exarr", &arrparam),
};
There are four macros used:
- PARAMDEF() gets as arguments:
- the name of the parameter
- the parameter flags to set for it (from the PM_* flags defined
in zsh.h)
- optionally a pointer to a variable holding the value of the
parameter
- three functions that will be used to get the value of the
parameter, store a value in the parameter, and unset the
parameter
- the other macros provide simple ways to define the most common
types of parameters; they get the name of the parameter and a
pointer to a variable holding the value as arguments; they are
used to define integer-, scalar-, and array-parameters, so the
variables whose addresses are given should be of type `long',
`char *', and `char **', respectively
For a description of how to write functions for getting or setting the
value of parameters, or how to write a function to unset a parameter,
see the description of the following functions in the `params.c' file:
- `intvargetfn()' and `intvarsetfn()' for integer parameters
- `strvargetfn()' and `strvarsetfn()' for scalar parameters
- `arrvargetfn()' and `arrvarsetfn()' for array parameters
- `stdunsetfn()' for unsetting parameters
Note that if one defines parameters using the last two macros (for
scalars and arrays), the variable holding the value should be
initialized to either `NULL' or to a a piece of memory created with
`zalloc()'. But this memory should *not* be freed in the
finish-function of the module because that will be taken care of by
the `deleteparamdefs()' function described below.
To register the parameters in the zsh core, the function
`addparamdefs()' is called as in:
/**/
int
boot_example(Module m)
{
int ret;
ret = addparamdefs(m->nam, patab, sizeof(patab)/sizeof(*patab))
...
}
The arguments and the return value are as for the functions used to
add builtins and condition codes and like these, it should be called
in the boot-function of the module. To remove the parameters defined,
the function `deleteparamdefs()' should be called, again with the same
arguments and the same return value as for the functions to remove
builtins and condition codes:
/**/
int
cleanup_example(Module m)
{
deleteparamdefs(m->nam, patab, sizeof(patab)/sizeof(*patab));
...
}
Finally, modules can define wrapper functions. These functions are
called whenever a shell function is to be executed.

View file

@ -940,7 +940,7 @@ pws: 6053: compwid.yo
Sven: 6056: compwid.yo
Sven: 6058: small changes
Sven: 6058: small changes in _path_files, compinit and documentation
Sven: 6060: don't invalidatelist() in zle_main.c before calling completion
functions
@ -967,3 +967,52 @@ Tanaka Akira: 6085: _make can hang when no [mM]akefile
Tanaka Akira: 6092: _find, bad glob pattern
pws: 6101: multi-line prompt ending in '\n' got another newline
pws-17
Geoff: 6104: multi-line prompt fix (6101 backed off)
Sven: 6105: _make patch whitespace
Bart: 6106: short documentation fixes in expn.yo, options.yo, redirect.yo
Sven: 6109: completion in parameter assignment should set context `value'
Sven: 6113: compadd -D, nuke element in an array for each failed match
Sven: 6117: position of ignored suffix in inserted match
pws: 6118: _closequote and _oldlist completers
Sven: 6119: don't insert word separator before ignored suffix
Sven: 6121: try harder with braces after a parameter expansion
Sven: 6124: menu completion wasn't consistent between tabs
Sven: 6128: completion after an expansion; list after a non-completion list
Sven: 6129: comments for struct cadata
Ville Herva: 6131, see 6126: reset tv.tv_sec before select for Linux
Sven: 6132: compctl.mdd
Sven: 6133: autoloaded parameters
Sven: 6150: alwayslastprompt sometimes failed in M-x
Sven: 6152: compstate[vared]
Sven: 6153: realparamtab to smooth access to autoloaded parameters
Bart: 6162: autoloadable parameter code links without dynamic loading
pws: 6165: globsubst'd foo='~/bin' depended on extendedglob being set
Sven: 6167: show unloaded parameters as undefined
Bart: 6171 as rewritten in 6174: old RedHat Linux doesn't have normall
definitions for poll.
pws: 6180: Completion/Core/compinstall