From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20622 invoked by alias); 10 Nov 2009 15:52:49 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 27383 Received: (qmail 15202 invoked from network); 10 Nov 2009 15:52:47 -0000 X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.2.5 Received-SPF: none (ns1.primenet.com.au: domain at closedmail.com does not designate permitted sender hosts) From: Bart Schaefer Message-id: <091110075221.ZM27832@torch.brasslantern.com> Date: Tue, 10 Nov 2009 07:52:21 -0800 In-reply-to: Comments: In reply to Greg Klanderman "Re: bug in 'rm' completion" (Nov 9, 12:52pm) References: <19191.43212.832827.724369@gargle.gargle.HOWL> <091109092926.ZM26572@torch.brasslantern.com> In-reply-to: Comments: In reply to Greg Klanderman "Re: bug in 'rm' completion" (Nov 9, 4:20pm) X-Mailer: OpenZMail Classic (0.9.2 24April2005) To: zsh-workers@zsh.org Subject: Re: bug in 'rm' completion MIME-version: 1.0 Content-type: text/plain; charset=us-ascii 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.