zsh-users
 help / color / mirror / code / Atom feed
* ordering of file-patterns completions
@ 2013-11-06 15:24 John
  2013-11-06 16:03 ` Bart Schaefer
  0 siblings, 1 reply; 6+ messages in thread
From: John @ 2013-11-06 15:24 UTC (permalink / raw)
  To: Zsh-Users List

I have a tool which needs one file-patterns for the first file matched, 
then the second and the rest should be of a different file-patterns.  I 
don't see a way to do this.

Are there any examples of something similar to this around? Something like:

foo XXX.blah XXX-YYY.blah [XXX-ZZZ.blah]

What would even be better is if I had a way of handling the latter ones 
so that it only matched the "blah" portion from the first file to the rest.

TIA,
John


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: ordering of file-patterns completions
  2013-11-06 15:24 ordering of file-patterns completions John
@ 2013-11-06 16:03 ` Bart Schaefer
  2013-11-07  1:11   ` John
  0 siblings, 1 reply; 6+ messages in thread
From: Bart Schaefer @ 2013-11-06 16:03 UTC (permalink / raw)
  To: Zsh-Users List

On Nov 6,  8:24am, John wrote:
}
} I have a tool which needs one file-patterns for the first file matched, 
} then the second and the rest should be of a different file-patterns.  I 
} don't see a way to do this.

You probably want to write a custom completer with the _arguments utility
function, and to leave file-patterns unspecified.


    _foo() {
      _arguments '1:The first file:_files -g "XXX.*"' \
		 '*:All other files:_files -g "*.${words[2]:x}"'
    } 

    compdef _foo foo

Here "1:" refers to the first argument (after skipping the command name
and any option flags) whereas "$words[2]" refers to the second word
of the entire command line (first word after the command name), so this
doesn't quite generalize if there may be options (words starting with
a hyphen) between the command name and the first file.  If that is the
case, you'll need to do some pre-processing of $words before calling
_arguments to determine which position to reference instead of [2].

(You can skip the "compdef" command if you put the body of _foo in a file
named _foo in a directory referenced in your $fpath, and begin that file
with the line "#compdef foo".)

} Are there any examples of something similar to this around?

There are lots of examples of using _arguments in the default set of
completion functions.  If there is a standard tool that you know of that
accepts arguments something like your custom one, try looking at the
completion function for that.  You can usually find the name of that
function by looking at ${_comps[command-name-here]}.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: ordering of file-patterns completions
  2013-11-06 16:03 ` Bart Schaefer
@ 2013-11-07  1:11   ` John
  2013-11-07  4:17     ` Bart Schaefer
  0 siblings, 1 reply; 6+ messages in thread
From: John @ 2013-11-07  1:11 UTC (permalink / raw)
  To: zsh-users

On 11/6/13, 9:03 AM, Bart Schaefer wrote:
> On Nov 6,  8:24am, John wrote:
> }
> } I have a tool which needs one file-patterns for the first file matched,
> } then the second and the rest should be of a different file-patterns.  I
> } don't see a way to do this.
>
> You probably want to write a custom completer with the _arguments utility
> function, and to leave file-patterns unspecified.
>
>
>      _foo() {
>        _arguments '1:The first file:_files -g "XXX.*"' \
> 		 '*:All other files:_files -g "*.${words[2]:x}"'
>      }
>
>      compdef _foo foo
>
> Here "1:" refers to the first argument (after skipping the command name
> and any option flags) whereas "$words[2]" refers to the second word
> of the entire command line (first word after the command name), so this
> doesn't quite generalize if there may be options (words starting with
> a hyphen) between the command name and the first file.  If that is the
> case, you'll need to do some pre-processing of $words before calling
> _arguments to determine which position to reference instead of [2].
Yeah, unfortunately I do.  I was using _arguments to process those, and 
then zstyle to deal with the files.  But I'm not quite understanding how 
to do what you're describing to pre-process them instead of using 
_arguments.
>
> (You can skip the "compdef" command if you put the body of _foo in a file
> named _foo in a directory referenced in your $fpath, and begin that file
> with the line "#compdef foo".)
>
> } Are there any examples of something similar to this around?
>
> There are lots of examples of using _arguments in the default set of
> completion functions.  If there is a standard tool that you know of that
> accepts arguments something like your custom one, try looking at the
> completion function for that.  You can usually find the name of that
> function by looking at ${_comps[command-name-here]}.

I searched through a number of them, but haven't found anything which 
has helped yet.

John


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: ordering of file-patterns completions
  2013-11-07  1:11   ` John
@ 2013-11-07  4:17     ` Bart Schaefer
  2013-11-07  6:30       ` John
  0 siblings, 1 reply; 6+ messages in thread
From: Bart Schaefer @ 2013-11-07  4:17 UTC (permalink / raw)
  To: zsh-users

On Nov 6,  6:11pm, John wrote:
}
} > doesn't quite generalize if there may be options (words starting with
} > a hyphen) between the command name and the first file.  If that is the
} > case, you'll need to do some pre-processing of $words before calling
} > _arguments to determine which position to reference instead of [2].
} 
} Yeah, unfortunately I do.  I was using _arguments to process those, and 
} then zstyle to deal with the files.  But I'm not quite understanding how 
} to do what you're describing to pre-process them instead of using 
} _arguments.

How complicated this needs to be depends on what might appear in the
words preceding the first file.

If there's nothing but options, for example, then you can probably do:

  local first_file=$(( ${words[(I)-*]} + 1 ))

which says to start from the end of the array and look backward to
find the index of the first word that DOES start with a hyphen, and
then add one to it.  Or, if there might be file names that start with
hyphen, then:

  local first_file=$(( ${${words[2,-1]}[(i)[^-]*]} + 1 ))

which says "in the array formed by the second through last elements of
the words array, report the index of the first element that does not
begin with a hyphen" and then add one to compensate for starting at 2.

If there are options that might take arguments, so some of the words
before the first file might not begin with hyphen, then you'll have to
try something else; perhaps:

  local -a opts
  set -- $words[2,-1]
  zparseopts -a opts ...
  local first_file=$(( $#opts + 2 ))

where "..." is a description of the options.  Yeah, this kinda sucks
because you have to describe the same options to both zparseopts and
_arguments.  In any case, once you're done computing first_file:

  _arguments $stuff_describing_options \
    '1:The first file:_files -g "XXX.*"' \
    '*:All other files:_files -g "*.${words[first_file]:x}"'


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: ordering of file-patterns completions
  2013-11-07  4:17     ` Bart Schaefer
@ 2013-11-07  6:30       ` John
  2013-11-07 15:06         ` Bart Schaefer
  0 siblings, 1 reply; 6+ messages in thread
From: John @ 2013-11-07  6:30 UTC (permalink / raw)
  To: zsh-users

On 11/6/13, 9:17 PM, Bart Schaefer wrote:
> On Nov 6,  6:11pm, John wrote:
> }
> } > doesn't quite generalize if there may be options (words starting with
> } > a hyphen) between the command name and the first file.  If that is the
> } > case, you'll need to do some pre-processing of $words before calling
> } > _arguments to determine which position to reference instead of [2].
> }
> } Yeah, unfortunately I do.  I was using _arguments to process those, and
> } then zstyle to deal with the files.  But I'm not quite understanding how
> } to do what you're describing to pre-process them instead of using
> } _arguments.
>
> How complicated this needs to be depends on what might appear in the
> words preceding the first file.
>
> If there's nothing but options, for example, then you can probably do:
>
>    local first_file=$(( ${words[(I)-*]} + 1 ))
>
> which says to start from the end of the array and look backward to
> find the index of the first word that DOES start with a hyphen, and
> then add one to it.  Or, if there might be file names that start with
> hyphen, then:
>
>    local first_file=$(( ${${words[2,-1]}[(i)[^-]*]} + 1 ))
>
> which says "in the array formed by the second through last elements of
> the words array, report the index of the first element that does not
> begin with a hyphen" and then add one to compensate for starting at 2.
>
The first one nearly does it, but seems to be confused when there are no 
options at all.  That is, it works fine as long as there is a --opt1, 
but if there isn't, the *: portion says it's completing the right thing, 
but then lists all the files rather than the matching one:

% yes <tab>XXX.<tab>
Completing XXX file
XXX.0       XXX.bogus   XXX.bogus3
XXX.1       XXX.bogus2  XXX.bogus4

% yes --opt1 XXX.0 <tab>XXX-YYY.0

% yes XXX.0 XXX<tab>
Completing XXX extra files
XXX-YYY.0   XXX.0       XXX.bogus XXX.bogus3
XXX-YYY.1   XXX.1       XXX.bogus2  XXX.bogus4

This is with:

#compdef yes

local first_file=$(( ${words[(I)--*]} + 1 ))

_arguments \
         '--opt1[desc1]' \
         '--opt2[desc2]' \
         '1:XXX file:_files -g "*XXX.*"' \
         '*:XXX extra files:_files -g "*XXX-*.${words[first_file]:e}"'

I ended up adding:

if [[ $first_file -lt 2 ]]; then
         first_file=2
fi

And that fixed it.  Not realizing that the array was 1-based threw me 
for a bit.  I also changed the :x to a :e, as :x just gave me an error, 
and :e matched the description of what I think you had meant.

Thanks!
John


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: ordering of file-patterns completions
  2013-11-07  6:30       ` John
@ 2013-11-07 15:06         ` Bart Schaefer
  0 siblings, 0 replies; 6+ messages in thread
From: Bart Schaefer @ 2013-11-07 15:06 UTC (permalink / raw)
  To: zsh-users

On Nov 6, 11:30pm, John wrote:
} >
} > If there's nothing but options, for example, then you can probably do:
} >
} >    local first_file=$(( ${words[(I)-*]} + 1 ))
} >
} The first one nearly does it, but seems to be confused when there are no 
} options at all.

Ah, yes.  Because it's counting backwards it will run down to zero if it
finds nothing.  I listed that one first because it was the simplest
expression, but I should have stuck with the second one:

} >    local first_file=$(( ${${words[2,-1]}[(i)[^-]*]} + 1 ))

[...]

} I ended up adding:
} 
} if [[ $first_file -lt 2 ]]; then
}          first_file=2
} fi
} 
} And that fixed it.  Not realizing that the array was 1-based threw me 
} for a bit.  I also changed the :x to a :e, as :x just gave me an error, 
} and :e matched the description of what I think you had meant.

Oops, yes, I did mean :e.  Typo'd it earlier and then just kept copy-
pasting.


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2013-11-07 15:06 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-11-06 15:24 ordering of file-patterns completions John
2013-11-06 16:03 ` Bart Schaefer
2013-11-07  1:11   ` John
2013-11-07  4:17     ` Bart Schaefer
2013-11-07  6:30       ` John
2013-11-07 15:06         ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).