I was planing on writing something like this for an existing project and then noticed this, which looks to go along way to whats required. On reading the manual I have the following questions:
1) SwitchArgs: that gives you the +<param> -<param> type?
2) Do params with arguments support both the -<param><val> and -<param> <val> syntaxs?
3) Are params like this supported (best match first)?
4) How do you create compound args resulting in:
-n[a|b|c] - If -n is provided it may take a optional a, b, or c.
-n [-p] - If -n is provided the additional parameter -p may be provided.
There is another case which I'm not sure of the correct syntax but I used -n<a|b> (although normally <> is used to specify a user supplied field), which means -n and either a or b must be provided.
Alot of this was to cut down the size of help to fit it all on a standard non-scrolling console and also because the parameters were associated so didn't have to repeat help text multiple times.
5) Can the Args be made to have callbacks, are suitable virtuals provided,rather than checking if set and querying the value.
6) I doubt this is standard but due to the number of args what I was planning to develop used prefixs. What I mean by this is that args can be grouped and those grouped items wont appear normally in help. In some programs --help gives:
--help-<prefix> Help on these additional grouped params
You can then use --help-<prefix> to get to the additional help. Have you seen this before? All params would therefore be --<prefix>-<param> on the command line, although probably not necessary for the help to actually show the prefix for each param (to save space).
Lastly to help the user with the prefixed args I planned builtins like --<prefix>-( <args> -) where the args would be auto prefixed (all args must from the group without the need to supply the group prefix). -) terminates the auto prefixing.
Thoughts, maybe support is basically there, maybe things can be added or perhaps theres better ways?
Lots of questions! Lets see if I can help...
1. SwitchArgs simply return bool values. The only syntax available is "-x". You specify the default value in the constructor and if the switch matches on the command line, then the complement of the default is returned. We don't have "+x" to turn on or "-x" to turn off. We get the same behavior using defaults.
2. You can specify the character used to separate the flag from the arg value in the CmdLine constructor. At the moment you can only specify one. The default is space. So, by default you get "-x blah", but you can change that to get "-x=blah", or "-x|blah", or whatever. You must specify a character; '' or no space is not supported. Let me know if there is desire for different behavior, as it is something I've considered changing.
3. I don't understand this question. If you have two SwitchArgs -n and -f, you can combine them into one arg on the command line, -nf (or -fn) and both switches will match. The order that the args are specified in doesn't matter for SwitchArgs.
4. Again, I'm not sure I understand the question. If -n is a ValueArg, which is to say it will read a value in addition to "-n", then you can specify a list a valid values that can be parsed. If -n is a ValueArg, then it _must_ read a value. We don't have anything where -n can be specified with or without value.
You can specify combinations of Args that must occur exclusive of one another using the XorHandler. For instance, you can say something like: either (-a and possibly -b must occur) OR (-c <value> must occur).
That said, we don't have support for complicated boolean expressions of args. This is something that we have considered, but is not likely to occur in the near future.
5. We provide a Visitor interface so that when an Arg matches on the command line, the specified Visitor will execute. I _think_ this is what you're looking for. We don't have a virtual method to accomplish this, although it would be straightforward to add.
6. We don't support this directly, but, with effort, I think you could accomplish this. You would have to write your own Visitors, an Output class, and then keep track of which args should appear with which help switch.
Lastly. Hmmm, we don't support this directly. You might be able to accomplish something like this by using XorHandler creatively, but there may be a few issues.
Let me know if something isn't clear or if you have further questions. We're currently planning future releases, so if you have a wish-list, let me know so that we can work something out. Definitely trying to avoid wheel re-invention.
>You must specify a character; '' or no space is not supported. Let me know if there is desire for different behavior, as it is something I've considered changing.
Defining the character is fine when a character is needed, however I also do find that no character is usefull in my apps. Also note things like gcc which seem to be able to do:
gcc -I <path> and/or gcc -I<path>
I've had people ask for this support from my apps, people prefer it one way and others prefer it the other. For most things it does seem pretty easy to support an optional no space.
3) To explain this again, if I have defined the flags both -n and -nf and a user puts -nf on the command line do I get a -nf match or do I get a -n match with parameter f? (remember if no space is supported between switch and parameter).
4) Ok, I'm not necessarily saying that complex boolean operations should be supported by the classes from the switch object, and you have provided OR,etc classes to help with that. The reason I did this was to support with the help, to get it much smaller. A simple thing to do might be to support a dummy class that does nothing but provide a help description in the managled format and it holds a list switch objects in the way your expecting it, but those don't cause any help output.
6) ok, wasn't expecting this to be supported, will have a play a little to see what can be done, but atleast some support with nested help pages would be usefull I think in future versions.
2) At the moment I'm leaning towards not supporting this. The reason is because it leads to ambiguity problems. For example, say you define two ValueArgs:
So, things would be fine if we only allowed short args (-a) instead of short and long args (--abc). For example:
cmd -Acc -acc
would work fine, both args "one" and "two" would end up with values "cc". However, the problems crop up with long args (and assuming no space):
cmd --abcc --abccc
Which ValueArgs should match? Without a delimiter separating the flag from the value, there is no way to tell. Is the first arg "one" with the value of "c" or is it arg "two" with the value "cc".
I want to avoid traps like this because this is meant to be a general library. There may be a way around problems like this, but I haven't come up with anything, aside from perhaps adding precedence rules. The way gcc accomplishes this sort of thing is to hand code the arg parsing, precisely what I want to avoid.
3) There are a couple of things to consider. First, args can be identified on the command line in two ways: a dash followed by a single character (what I refer to as flags, e.g. -a) or two dashes followed by a string (long-args, e.g. --apple). You cannot refer to the arg as -apple (one dash followed by a string). This is for parsing sanity as described in 2 above.
There is one exception to this. When you have two SwitchArgs (which don't accept values), say -n and -f, you can combine the flags into a single arg: -nf. This is to avoid forcing people to type -n -f -x -y, etc.
The reason I force flags to be a single character is to allow these combined args. If I allowed -apple then I wouldn't know whether I was parsing the apple arg or the -a, -p, -l, -e switches.
In cases where there are large numbers of switches, e.g. more args than possible single characters, then simply force long args. You do this by specifying the args without flags. It is possible to have a combination where some args accept short or long args, and where some only accept long-args.
4,6) Upon reflection, it is possible to create nested help output.
Prefixes might be a bit trickier, but may be possible. Let me make sure I understand what you're getting at. Here is what I'm hearing:
You have 4 normal args:
and 2 prefix args:
Without either of the prefixes, you could have a command line like:
cmd --A-file foo --B-name bar
However, if you used one of the prefix args, you would could have something like:
cmd -A --file foo --name bar
Which would set the args
--A-file set to foo
--A-name set to bar
cmd -A -B
would not be allowed, but
cmd -A --file foo --name bar --B-name homer
would be allowed and set args:
--A-file to foo
--A-name to bar
--B-name to homer
Does that sound right? Are there any cases I'm missing?
2 & 3) I can see the problem, it's happened before. But your right generally either more specific matches win, precedence definations or I guess the developer shouldn't have been so silly with the switches.
4 & 6) Yes it does and I think only a termination is missing... e.g. if you were unlucky enough to have:
--A -f ... yep ok so how to get non prefixed -f?
Am always a little in favour of specifying start and stop e.g. --A-( ... ... .. -), or something similar. I think this approach may even be suitable for multi args mixed with unnamed args (I noticed in another forum message).