From mboxrd@z Thu Jan 1 00:00:00 1970 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes Date: Wed, 27 Jan 1999 13:25:59 +0100 (MET) Message-Id: <199901271225.NAA31324@beta.informatik.hu-berlin.de> From: Sven Wischnowsky To: zsh-workers@sunsite.auc.dk In-reply-to: "Andrej Borsenkow"'s message of Tue, 26 Jan 1999 14:52:04 +0300 Subject: RE: zsh-3.1.5-pws-5: mixing "old" and "new" completions? X-Mailing-List: 5059 Andrej Borsenkow wrote: > What I think about, is two interfaces: compctl->new completion and new > completion->compctl. That is The patch below implements this: new->old: The builtin `compcall' can be called from a new style completion function and makes the `compctl's for the current settings of COMMAND, IPREFIX, PREFIX, SUFFIX, and argv be used. Currently this builtin accepts only to options: `T' and `D'. Without any options the `compctl's for first completion (`-T') and for default (`-D') completion are *not* tried. You can switch this on by using the appropriate option. `compcall' accepts no other option or argument, for now. It would be easy to make it accept arguments for the command line words to use, for the command name to use, etc. If this turns out to be interesting to have, I'll add it. old->new: I'm not too sure that I like to support this way, so this is rather hackish at the moment (meaning: even more than the rest of the new style completion). If you give the `-K' option to `compctl' a string that begins with one space, the named function will be called with the variables and arguments as expected by new style completion functions. Ok. Even though I said that this is very experimental, I strongly suggest to use this patch. First, it makes testing the new stuff easier, and second, the patch contains also a minor fix (compadd now accepts zero arguments). The patch also changes the file `new-completion-examples' to use `compctl's that are defined. With that you should be able to just source this file, use the new completion stuff and still be able to use your `compctl's. You may want to modify or delete some of the examples in the file. You may also want to alter the way compcall is invoked, see the comments in the file after applying this patch (or look at the end of this patch). [The patch looks big, but this is almost only because it contains a lot of moving-code-around and re-indent-stuff.] Bye Sven diff -u os/Zle/comp.h Src/Zle/comp.h --- os/Zle/comp.h Tue Jan 26 14:24:21 1999 +++ Src/Zle/comp.h Wed Jan 27 11:14:43 1999 @@ -267,3 +267,8 @@ #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 diff -u os/Zle/compctl.c Src/Zle/compctl.c --- os/Zle/compctl.c Tue Jan 26 14:24:21 1999 +++ Src/Zle/compctl.c Wed Jan 27 12:07:24 1999 @@ -1677,7 +1677,7 @@ 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 +1706,7 @@ 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; } @@ -1800,6 +1800,15 @@ return 0; } +/**/ +static int +bin_compcall(char *name, char **argv, char *ops, int func) +{ + makecomplistctl((ops['T'] ? 0 : CFN_FIRST) | + (ops['D'] ? 0 : CFN_DEFAULT)); + return 0; +} + #define VAR(X) ((void *) (&(X))) static struct compparam { char *name; @@ -1855,7 +1864,7 @@ static int comp_wrapper(List list, FuncWrap w, char *name) { - if (!incompfunc) + if (incompfunc != 1) return 1; else { char *octxt, *ocmd, *opre, *osuf, *oipre; @@ -1906,7 +1915,7 @@ static int comp_check(void) { - if (!incompfunc) { + if (incompfunc != 1) { zerr("condition can only be used in completion function", NULL, 0); return 0; } @@ -2118,7 +2127,8 @@ 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[] = { diff -u os/Zle/zle_tricky.c Src/Zle/zle_tricky.c --- os/Zle/zle_tricky.c Tue Jan 26 14:24:23 1999 +++ Src/Zle/zle_tricky.c Wed Jan 27 12:55:02 1999 @@ -3172,6 +3172,105 @@ } LASTALLOC; } +/* This calls the given function for new style completion. */ + +/**/ +static void +callcompfunc(char *s, char *fn) +{ + List list; + int lv = lastval; + + if ((list = getshfunc(fn)) != &dummy_list) { + LinkList args = newlinklist(); + char **p, *tmp; + int aadd = 0, usea = 1, icf = incompfunc; + + addlinknode(args, fn); + + zsfree(compcontext); + zsfree(compcommand); + compcommand = ""; + if (inwhat == IN_MATH) { + if (insubscr) { + compcontext = "subscript"; + compcommand = varname ? varname : ""; + } else + compcontext = "math"; + usea = 0; + } else if (lincmd) + compcontext = (insubscr ? "subscript" : "command"); + else if (linredir) { + compcontext = "redirect"; + if (rdstr) + compcommand = rdstr; + } else + switch (inwhat) { + case IN_ENV: + compcontext = "value"; + compcommand = varname; + usea = 0; + break; + case IN_COND: + compcontext = "condition"; + break; + default: + if (cmdstr) { + compcontext = "argument"; + compcommand = cmdstr; + } else { + compcontext = "value"; + if (clwords[0]) + compcommand = clwords[0]; + } + aadd = 1; + } + compcontext = ztrdup(compcontext); + tmp = quotename(compcommand, NULL, NULL, NULL); + untokenize(tmp); + compcommand = ztrdup(tmp); + if (usea && (!aadd || clwords[0])) + for (p = clwords + aadd; *p; p++) { + tmp = dupstring(*p); + untokenize(tmp); + addlinknode(args, tmp); + } + zsfree(compprefix); + zsfree(compsuffix); + if (unset(COMPLETEINWORD)) { + tmp = quotename(s, NULL, NULL, NULL); + untokenize(tmp); + compprefix = ztrdup(tmp); + compsuffix = ztrdup(""); + } else { + char *ss = s + offs, sav; + + tmp = quotename(s, &ss, NULL, NULL); + sav = *ss; + *ss = '\0'; + untokenize(tmp); + compprefix = ztrdup(tmp); + *ss = sav; + untokenize(ss); + compsuffix = ztrdup(ss); + } + zsfree(compiprefix); + compiprefix = ztrdup(""); + compcurrent = (usea ? (clwpos + 1 - aadd) : 1); + compnmatches = mnum; + incompfunc = 1; + startparamscope(); + makecompparamsptr(); + NEWHEAPS(compheap) { + doshfunc(fn, list, args, 0, 1); + } OLDHEAPS; + endparamscope(); + lastcmd = 0; + incompfunc = icf; + } + lastval = lv; +} + /* The beginning and end of a word range to be used by -l. */ static int brange, erange; @@ -3224,100 +3323,10 @@ ccused = newlinklist(); ccstack = newlinklist(); - if (compfunc) { - List list; - int lv = lastval; - - if ((list = getshfunc(compfunc)) != &dummy_list) { - LinkList args = newlinklist(); - char **p, *tmp; - int aadd = 0, usea = 1; - - addlinknode(args, compfunc); - - zsfree(compcontext); - zsfree(compcommand); - compcommand = ""; - if (inwhat == IN_MATH) { - if (insubscr) { - compcontext = "subscript"; - compcommand = varname ? varname : ""; - } else - compcontext = "math"; - usea = 0; - } else if (lincmd) - compcontext = (insubscr ? "subscript" : "command"); - else if (linredir) { - compcontext = "redirect"; - if (rdstr) - compcommand = rdstr; - } else - switch (inwhat) { - case IN_ENV: - compcontext = "value"; - compcommand = varname; - usea = 0; - break; - case IN_COND: - compcontext = "condition"; - break; - default: - if (cmdstr) { - compcontext = "argument"; - compcommand = cmdstr; - } else { - compcontext = "value"; - if (clwords[0]) - compcommand = clwords[0]; - } - aadd = 1; - } - compcontext = ztrdup(compcontext); - tmp = quotename(compcommand, NULL, NULL, NULL); - untokenize(tmp); - compcommand = ztrdup(tmp); - if (usea && (!aadd || clwords[0])) - for (p = clwords + aadd; *p; p++) { - tmp = dupstring(*p); - untokenize(tmp); - addlinknode(args, tmp); - } - zsfree(compprefix); - zsfree(compsuffix); - if (unset(COMPLETEINWORD)) { - tmp = quotename(s, NULL, NULL, NULL); - untokenize(tmp); - compprefix = ztrdup(tmp); - compsuffix = ztrdup(""); - } else { - char *ss = s + offs, sav; - - tmp = quotename(s, &ss, NULL, NULL); - sav = *ss; - *ss = '\0'; - untokenize(tmp); - compprefix = ztrdup(tmp); - *ss = sav; - untokenize(ss); - compsuffix = ztrdup(ss); - } - zsfree(compiprefix); - compiprefix = ztrdup(""); - compcurrent = (usea ? (clwpos + 1 - aadd) : 1); - compnmatches = mnum; - incompfunc = 1; - startparamscope(); - makecompparamsptr(); - NEWHEAPS(compheap) { - doshfunc(compfunc, list, args, 0, 1); - } OLDHEAPS; - endparamscope(); - lastcmd = 9; - incompfunc = 0; - } - lastval = lv; - } else - makecomplistglobal(s, incmd, lst); + if (compfunc) + callcompfunc(s, compfunc); + else + makecomplistglobal(s, incmd, lst, 0); endcmgroup(NULL); @@ -3362,11 +3371,11 @@ if (*p == '\\') bslash = 1; else { - if (*p == '$') { + if (*p == '$' || *p == '=') { if (bslash) p[-1] = Bnull; else - *p = String; + *p = (*p == '$' ? String : Equals); } bslash = 0; } @@ -3425,16 +3434,59 @@ } SWITCHBACKHEAPS; } +/**/ +void +makecomplistctl(int flags) +{ + SWITCHHEAPS(compheap) { + HEAPALLOC { + int ooffs = offs, lip, lp; + char *str = comp_str(&lip, &lp), *t; + char *os = cmdstr, **ow = clwords, **p, **q; + int on = clwnum, op = clwpos; + + clwnum = arrlen(pparams) + 1; + clwpos = compcurrent - 1; + cmdstr = ztrdup(compcommand); + clwords = (char **) zalloc((clwnum + 1) * sizeof(char *)); + clwords[0] = ztrdup(cmdstr); + for (p = pparams, q = clwords + 1; *p; p++, q++) { + t = dupstring(*p); + ctokenize(t); + remnulargs(t); + *q = ztrdup(t); + } + *q = NULL; + offs = lip + lp; + incompfunc = 2; + makecomplistglobal(str, + (!clwpos && !strcmp(compcontext, "command")), + COMP_COMPLETE, flags); + incompfunc = 1; + offs = ooffs; + compnmatches = mnum; + zsfree(cmdstr); + freearray(clwords); + cmdstr = os; + clwords = ow; + clwnum = on; + clwpos = op; + } LASTALLOC; + } SWITCHBACKHEAPS; +} + /* This function gets the compctls for the given command line and * * adds all completions for them. */ /**/ static void -makecomplistglobal(char *os, int incmd, int lst) +makecomplistglobal(char *os, int incmd, int lst, int flags) { Compctl cc; char *s; + ccont = CC_CCCONT; + if (lst == COMP_WIDGET) { cc = compwidget->u.cc; } else if (inwhat == IN_ENV) @@ -3463,16 +3515,17 @@ cc = &cc_default; else { /* Otherwise get the matches for the command. */ - makecomplistcmd(os, incmd); + makecomplistcmd(os, incmd, flags); cc = NULL; } if (cc) { /* First, use the -T compctl. */ - makecomplistcc(&cc_first, os, incmd); - - if (!(ccont & CC_CCCONT)) - return; + if (!(flags & CFN_FIRST)) { + makecomplistcc(&cc_first, os, incmd); + if (!(ccont & CC_CCCONT)) + return; + } makecomplistcc(cc, os, incmd); } } @@ -3481,18 +3534,19 @@ /**/ static void -makecomplistcmd(char *os, int incmd) +makecomplistcmd(char *os, int incmd, int flags) { Compctl cc; Compctlp ccp; char *s; /* First, use the -T compctl. */ - makecomplistcc(&cc_first, os, incmd); - - if (!(ccont & CC_CCCONT)) - return; + if (!(flags & CFN_FIRST)) { + makecomplistcc(&cc_first, os, incmd); + if (!(ccont & CC_CCCONT)) + return; + } /* Then search the pattern compctls, with the command name and the * * full pathname of the command. */ makecomplistpc(os, incmd); @@ -3520,9 +3574,11 @@ (cc = ccp->cc)) || ((s = dupstring(cmdstr)) && remlpaths(&s) && (ccp = (Compctlp) compctltab->getnode(compctltab, s)) && - (cc = ccp->cc))))) + (cc = ccp->cc))))) { + if (flags & CFN_DEFAULT) + return; cc = &cc_default; - + } makecomplistcc(cc, os, incmd); } @@ -3811,12 +3867,12 @@ ccont |= (cc->mask2 & (CC_CCCONT | CC_DEFCONT | CC_PATCONT)); - if (!incompfunc && findnode(ccstack, cc)) + if (incompfunc != 1 && findnode(ccstack, cc)) return; addlinknode(ccstack, cc); - if (!incompfunc && allccs) { + if (incompfunc != 1 && allccs) { if (findnode(allccs, cc)) { uremnode(ccstack, firstnode(ccstack)); return; @@ -4424,45 +4480,50 @@ /* Add user names. */ maketildelist(); if (cc->func) { - /* This handles the compctl -K flag. */ - List list; - char **r; - int lv = lastval; - - /* Get the function. */ - if ((list = getshfunc(cc->func)) != &dummy_list) { - /* We have it, so build a argument list. */ - LinkList args = newlinklist(); - int osc = sfcontext; - - addlinknode(args, cc->func); - - if (delit) { - p = dupstrpfx(os, ooffs); - untokenize(p); - addlinknode(args, p); - p = dupstring(os + ooffs); - untokenize(p); - addlinknode(args, p); - } else { - addlinknode(args, lpre); - addlinknode(args, lsuf); + if (cc->func[0] == ' ') + /* Temporary hack for access to new style completione. */ + callcompfunc(os, cc->func + 1); + else { + /* This handles the compctl -K flag. */ + List list; + char **r; + int lv = lastval; + + /* Get the function. */ + if ((list = getshfunc(cc->func)) != &dummy_list) { + /* We have it, so build a argument list. */ + LinkList args = newlinklist(); + int osc = sfcontext; + + addlinknode(args, cc->func); + + if (delit) { + p = dupstrpfx(os, ooffs); + untokenize(p); + addlinknode(args, p); + p = dupstring(os + ooffs); + untokenize(p); + addlinknode(args, p); + } else { + addlinknode(args, lpre); + addlinknode(args, lsuf); + } + + /* This flag allows us to use read -l and -c. */ + if (incompfunc != 1) + incompctlfunc = 1; + sfcontext = SFC_COMPLETE; + /* Call the function. */ + doshfunc(cc->func, list, args, 0, 1); + sfcontext = osc; + incompctlfunc = 0; + /* And get the result from the reply parameter. */ + if ((r = get_user_var("reply"))) + while (*r) + addmatch(*r++, NULL); } - - /* This flag allows us to use read -l and -c. */ - if (!incompfunc) - incompctlfunc = 1; - sfcontext = SFC_COMPLETE; - /* Call the function. */ - doshfunc(cc->func, list, args, 0, 1); - sfcontext = osc; - incompctlfunc = 0; - /* And get the result from the reply parameter. */ - if ((r = get_user_var("reply"))) - while (*r) - addmatch(*r++, NULL); + lastval = lv; } - lastval = lv; } if (cc->mask & (CC_JOBS | CC_RUNNING | CC_STOPPED)) { /* Get job names. */ @@ -4619,7 +4680,7 @@ } /* No harm in allowing read -l and -c here, too */ - if (!incompfunc) + if (incompfunc != 1) incompctlfunc = 1; sfcontext = SFC_COMPLETE; doshfunc(cc->ylist, list, args, 0, 1); @@ -4686,7 +4747,7 @@ clwords += brange; } /* Produce the matches. */ - makecomplistcmd(s, incmd); + makecomplistcmd(s, incmd, CFN_FIRST); /* And restore the things we changed. */ clwords = ow; --- om/new-completion-examples Tue Jan 26 16:48:34 1999 +++ Misc/new-completion-examples Wed Jan 27 12:36:17 1999 @@ -90,11 +90,20 @@ # 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 -- Sven Wischnowsky wischnow@informatik.hu-berlin.de