Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: Completion weirdity after `for'
- X-seq: zsh-workers 4930
- From: Sven Wischnowsky <wischnow@xxxxxxxxxxxxxxxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxxxxxxx
- Subject: Re: Completion weirdity after `for'
- Date: Wed, 20 Jan 1999 12:12:27 +0100 (MET)
- In-reply-to: Peter Stephenson's message of Mon, 18 Jan 1999 18:20:06 +0100
Peter Stephenson wrote:
>
> After
>
> for f in <TAB>
>
> completion takes place as if the command name is `in', not `for'.
> This showed up because I have a function called `in' such that `in dir
> cmdlist' executes cmdlist in directory dir, so I have the first word
> after `in' complete directories, which is not what is wanted here.
>
> The natural way to handle this would be such that everything up to and
> including the list were treated as words of a fictitious `for'
> command, so e.g. you can specify special behaviour for arguments 1 and
> 2 and default for the rest. This is possible to fix, but like most
> things to do with get_comp_string() the fix could be a little ad hoc.
> Maybe other reserved words need some fix-up, but for and foreach are
> the worst offenders since others tend to be followed by a specific
> command which then works in the expected way.
The patch below is my attempt at this. With it you can define things
like:
compctl -v -x 'p[2]' -k '(in)' - 'p[3,-1]' -f -- for
(or whatever you like to complete).
This is done for `for', `foreach', `select', `repeat', and `case'. The
thing for `repeat' was a bi more complicated to make completion after
`repeat x ' and after `repeat x do' work. For `case' I haven't done
any special handling yet, so this still fails utterly (try completion
after a pattern, you'll get default completion, not command
completion). Due to the way the lexer reports things for the `case'
construct making this work right may get a bit more complicated
(though I have the feeling that we should make this work, too, so I
may come back to this).
Anyway, I would like to hear about any problems you encounter with
patch...
Bye
Sven
*** os/Zle/zle_tricky.c Wed Jan 20 09:09:56 1999
--- Src/Zle/zle_tricky.c Wed Jan 20 12:01:43 1999
***************
*** 890,896 ****
static char *
get_comp_string(void)
{
! int t0, tt0, i, j, k, cp, rd, sl, ocs;
char *s = NULL, *linptr, *tmp, *p, *tt = NULL;
zsfree(brbeg);
--- 890,896 ----
static char *
get_comp_string(void)
{
! int t0, tt0, i, j, k, cp, rd, sl, ocs, ins, oins;
char *s = NULL, *linptr, *tmp, *p, *tt = NULL;
zsfree(brbeg);
***************
*** 950,956 ****
inpush(dupstrspace((char *) linptr), 0, NULL);
strinbeg();
stophist = 2;
! i = tt0 = cp = rd = 0;
/* This loop is possibly the wrong way to do this. It goes through *
* the previously massaged command line using the lexer. It stores *
--- 950,956 ----
inpush(dupstrspace((char *) linptr), 0, NULL);
strinbeg();
stophist = 2;
! i = tt0 = cp = rd = ins = oins = 0;
/* This loop is possibly the wrong way to do this. It goes through *
* the previously massaged command line using the lexer. It stores *
***************
*** 964,971 ****
* this would be to pass the command line through the parser too, *
* and get the arguments that way. Maybe in 3.1... */
do {
! lincmd = incmdpos;
! linredir = inredir;
/* Get the next token. */
ctxtlex();
if (tok == DINPAR)
--- 964,973 ----
* this would be to pass the command line through the parser too, *
* and get the arguments that way. Maybe in 3.1... */
do {
! lincmd = ((incmdpos && !ins) || (oins == 2 && i == 2) ||
! (ins == 3 && i == 1));
! linredir = (inredir && !ins);
! oins = ins;
/* Get the next token. */
ctxtlex();
if (tok == DINPAR)
***************
*** 974,980 ****
/* We reached the end. */
if (tok == ENDINPUT)
break;
! if (tok == BAR || tok == AMPER ||
tok == BARAMP || tok == AMPERBANG ||
((tok == DBAR || tok == DAMPER) && !incond)) {
/* This is one of the things that separate commands. If we *
--- 976,984 ----
/* We reached the end. */
if (tok == ENDINPUT)
break;
! if ((ins && (tok == DO || tok == SEPER)) ||
! (ins == 2 && i == 2) || (ins == 3 && i == 3) ||
! tok == BAR || tok == AMPER ||
tok == BARAMP || tok == AMPERBANG ||
((tok == DBAR || tok == DAMPER) && !incond)) {
/* This is one of the things that separate commands. If we *
***************
*** 983,993 ****
if (tt)
break;
/* Otherwise reset the variables we are collecting data in. */
! i = tt0 = cp = rd = 0;
}
! if (lincmd && tok == STRING) {
/* The lexer says, this token is in command position, so *
* store the token string (to find the right compctl). */
zsfree(cmdstr);
cmdstr = ztrdup(tokstr);
i = 0;
--- 987,999 ----
if (tt)
break;
/* Otherwise reset the variables we are collecting data in. */
! i = tt0 = cp = rd = ins = 0;
}
! if (lincmd && (tok == STRING || tok == FOR || tok == FOREACH ||
! tok == SELECT || tok == REPEAT || tok == CASE)) {
/* The lexer says, this token is in command position, so *
* store the token string (to find the right compctl). */
+ ins = (tok == REPEAT ? 2 : (tok != STRING));
zsfree(cmdstr);
cmdstr = ztrdup(tokstr);
i = 0;
***************
*** 1008,1013 ****
--- 1014,1022 ----
}
if (!tokstr)
continue;
+ /* Hack to allow completion after `repeat n do'. */
+ if (oins == 2 && !i && !strcmp(tokstr, "do"))
+ ins = 3;
/* We need to store the token strings of all words (for some of *
* the more complicated compctl -x things). They are stored in *
* the clwords array. Make this array big enough. */
--
Sven Wischnowsky wischnow@xxxxxxxxxxxxxxxxxxxxxxx
Messages sorted by:
Reverse Date,
Date,
Thread,
Author