Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: bug in 'rm' completion



On Nov 9, 12:52pm, Greg Klanderman wrote:
}
} Duh.. see below.  It's just not considering the last word from the
} line when generating the ignore pattern.  What I think is needed is to
} generally remove the current word from incorporation into the ignore
} pattern, but I don't know how to do that.  If I knew how to relate
} $CURRENT to an element of $line that would do it.

Amazingly there is a descriptive comment in Src/Zle/computil.c for the
behavior of comparguments.  It says:

case 'W':
    /* This gets two parameter names as arguments.  The first is set to
     * the current word sans any option prefixes handled by comparguments.
     * The second parameter is set to an array containing the options on
     * the line and their arguments.  I.e. the stuff _arguments returns
     * to its caller in the `line' and `opt_args' parameters. */

If that's accurate, $line should be a single word and $opt_args should
be an array.  However, the C code appears to be setting the first arg
as an array and the second as a hash, which agrees with the yodl doc
for the _arguments function:

     During the performance of the action the array `line' will be set
     to the command name and normal arguments from the command line,
     i.e. the words from the command line excluding all options and
     their arguments.  Options are stored in the associative array
     `opt_args' with option names as keys and their arguments as the
     values.  For options that have more than one argument these are
     given as one string, separated by colons.  All colons in the
     original arguments are preceded with backslashes.

Only Sven W. knows why the name "line" was chosen for this; forensics
might determine at what point the comment in computil.c corresponded
to reality, but it's probably not woth the effort.


On Nov 9,  4:20pm, Greg Klanderman wrote:
} Subject: Re: bug in 'rm' completion
}
} I think the patch below is the correct fix.  I'm still not sure
} whether it should be using $line or $words and I'm not certain on the
} difference between two and three colons in the _arguments definition
} ('*::files:->file' vs '*:::files:->file') but in both cases I suspect
} it doesn't actually matter.

Doc says:

      With two colons before the MESSAGE, the words special array
      and the CURRENT special parameter are modified to refer only
      to the normal arguments when the ACTION is executed or
      evaluated.  With three colons before the MESSAGE they are
      modified to refer only to the normal arguments covered by
      this description.

I believe this means that *:: and *::: are equivalent in this case
because there are no other descriptions to "cover" other arguments.

You're correct that using one of these forms will update CURRENT to
point into $line, which is what's needed for your solution.
 
} +    ignored=(${line[1,CURRENT-1]//(#m)[\[\]()\\*?#<>~\^]/\\$MATCH})
} +    ignored+=(${line[CURRENT+1,-1]//(#m)[\[\]()\\*?#<>~\^]/\\$MATCH})

I'd be inclined to wrap that in a check that ((CURRENT > 1)) just so
it's obvious that we don't ignore the only word on the line, rather
than rely on $line[1,0] to do the right thing, but otherwise this
seems right to me.



Messages sorted by: Reverse Date, Date, Thread, Author