Closed disruptek closed 4 years ago
stopWords
was more about subcommands than "nested commands" as you seem to be trying to do. They may be the same or they may be just different enough to cause trouble. Conventionally, --
is more a separator between "possibly options" and "no longer possibly options" to the primary command, as in dups -lsumm foo -- -bar
to, say, allow filenames beginning with -
. --
is actually implemented in parseopt3
, IIRC. So, your putting it in stopWords
seems at least redundant. Anyway, we might be able to get stopWords
or --
in some combination to work as you need it to. I am mostly clarifying its original intent. It isn't quite your use case. I may have to think about your use case a bit.
If it's just a CLI then a maybe easy/overlooked way to achieve what you want might be able to do your own split("--")
of commandLineParams()
probably eating that delimiter as part of a custom mergeParams()
. Your mergeParams()
would just send only the first half through to cligen
, say, and package up the second half in a higher scope (could be global or maybe just higher) var
to be consulted later.
If it's helpful to see a concrete example of params shenanigans, one of the fancier mergeParams()
that I've written myself is the one in https://github.com/c-blake/procs (search procs.nim for mergeParams). That might spur some other creativity on your part, as well.
(If it's not just a CLI but an API-CLI hybrid as per the kind of inspiring use case of cligen
then what the semantics of cmdA ... -- cmdB ... -- cmdC ...
in terms of Nim code even are would need more careful consideration.)
Oh, and I should also have mentioned that my hypothetical proc split(sq: seq[string], dlm: string="--", eatDlm=true): seq[seq[string]]
is something you would have to implement yourself, though that should be easy. If you ask nicely I can add something like that to all the various support libs I put in cligen
.
I did look at mergeParams
but there was something that turned me off there. I think there's a cligen example in which you supply the input arguments for cligen parsing, which is probably the cleanest solution.
Here's the program: https://github.com/disruptek/golden
And an example usage is, eg. when we benchmark koch
:
$ golden --json koch -- boot -d:danger
but I realized I could just subtract the number of post---
arguments from the list of arguments that remain after cligen has processed them, since with the stopWord
, it should not adjust the remainder of the sequence.
https://github.com/disruptek/golden/blob/master/src/golden.nim#L105
So I guess that as long as stopWords
behavior doesn't change, I've got a trivial solution. Thanks for cligen and thanks for having my back! :smile:
I see. You want to wrap an array of command lines. Your current solution looks ok for just 1 command requiring arguments/options.
However, the theory of operation of your program to me suggests that your sources
parameter is really a seq[seq[string]]
all the time, conceptually. From your loop over targets and appearsBenchmarkable
, it seems you think you can automagically simplify that for CLI invokers some/most of the time, but there are other times when that's hard and you'll need the user to delimit things. Is that right? If so, maybe what would be best is two syntaxes - long form:
golden [gopts] -- cmd1 opts1 args1 -- cmd2 opts2 args2
and then a short form when your automagic can work:
golden [goldenopts] cmd1 identifiably-non-cmd-args1 cmd2
Your current solution for just 1 command then becomes a special case of the long form syntax for one wrapped command. The only limitation of the long form is that no commands can actually take --
as an argument themselves. You could take a user-supplied delimiter. E.g.,
golden --delim="" -- cmd1 * "" cmd2
(Note that the empty string is an illegal filename. So, *
cannot create it.)
cligen
should always leave any -*
after the very first --
alone since that is the main purposes of --
. So, I doubt you need any cligen
modifications if you like the above idea and "--"
is a fine default for that delimiter string.
Of course, if there is literally no string guaranteed absent in sub-argument lists of a given golden
invocation then perfect generality is lost. That's probably very rare, though. The only upshot is you cannot bundle such commands together into just one golden
call which also isn't so bad.
You would probably want that split I mentioned to simplify some proc parse()
taking param sources: seq[string]
over to a local variable seq[seq[string]]
as in let targets = parse(sources)
. (I would probably say let sources = parse(sources)
these days.) This would also keep your proc golden
callable as an API. You might also want to provide/export a join
matching that split
so that an import golden
Nim caller could say golden(sources=cmds.join("--"))
.
Besides probably simplifying downstream code for you, the above long/short form syntax separation idea (both producing seq[seq[string]]
) might also help you keep more cleanly separate any "interpreter deciding benchmarkability time" and "time actually running benchmarks". E.g., if testing if some arg is "a file or not" could decide benchmarkability and that file is on a network file system and that network is shared and you need to test he file/hit the net every time then that risks adding artificial noise.
That's good thinking, but it's a pretty sophisticated solution for a simple program. If you want to invoke the program with multiple command-lines, simply execute it, y'know, on multiple commmand-lines. :wink:
The feature we want to target here is the running of multiple programs with the same set of command-line arguments, not the fact that we can vary those options. We already get that for free. The typical benchmark of multiple inputs might be something like this:
$ golden benchmarks/*.nim -- cpp -d:danger -d:temp:/tmpfs -d:data:/some/input -d:owner:$USER
To put this another way, if I'm going to compose a different command-line for each program, I may as well just delineate each such filename and set of arguments with ;golden
, instead of --
:
$ ;golden prog1 -d:thing1 ;golden prog2 -d:thing2 ;golden prog3 -d:thing3
Ah. I see. I think I slightly misunderstood the idea you were after. Anyway, I may add that split
and join
to cligen
this weekend for anyone wanting to parse an "array of cmdlines". It may be helpful to someone.
Cool, yes, that'll be helpful. Thanks again,
I'm trying to make
--
work in the conventional way, using thestopWords
parameter. I wanted a command-line syntax likefoo -a -b bar -- biz -x -y
but I feel like I've simply overlooked an easier way to accomplish this, asstopWords
don't seem to help all that much.Here is
test/MultiFlag.nim
:An example invocation:
I modified this test to use
stopWords=@["--", "ho"]
:Here it's actually swallowing the stop word and I can't tell where my "extra" arguments begin and end, or if they exist at all, for that matter.