Menu

#28 (Request) Adding multiple optional unlabeled arguments

1.2.x
wont-fix
None
5
2021-08-15
2020-10-23
No

I have a command line that needs to be parsed as:

cmd <transport port> <websocket port>

Coding as this doesn't work:

  TCLAP::UnlabeledValueArg<uint16_t> transportArg(
      "port", "Port for the TCP and UDT transports to use",
      false, 9000, "port", cmd);
  TCLAP::UnlabeledValueArg<uint16_t> websocketArg(
      "websocket", "Port for the websocket to use, 0 if no socket",
      false, 8080, "websocket", cmd);

As this is thrown:

error: You can't specify ANY Unlabeled Arg following an optional Unlabeled Arg for arg Argument

However, as both arguments are optional it shouldn't matter that there are two. I would argue that the error should be:

error: You can't specify **a required** Unlabeled Arg following an optional Unlabeled Arg for arg Argument

Changing OptionalUnlabeledTracker.h as follows:

diff --git a/include/tclap/OptionalUnlabeledTracker.h b/include/tclap/OptionalUnlabeledTracker.h
index 92f8929..a522be1 100644
--- a/include/tclap/OptionalUnlabeledTracker.h
+++ b/include/tclap/OptionalUnlabeledTracker.h
@@ -47,7 +47,7 @@ class OptionalUnlabeledTracker

 inline void OptionalUnlabeledTracker::check( bool req, const std::string& argName )
 {

-    if ( OptionalUnlabeledTracker::alreadyOptional() )
+    if ( req && OptionalUnlabeledTracker::alreadyOptional() )
         throw( SpecificationException(
        "You can't specify ANY Unlabeled Arg following an optional Unlabeled Arg",
                        argName ) );

gives me what I want with (as far as I can tell) no ill effects. Is it possible to make this change, or is there a corner case that this would break that I am missing?

(This library is otherwise fantastic though!)

James

Discussion

  • Daniel Aarno

    Daniel Aarno - 2020-10-24
    • assigned_to: Daniel Aarno
     
  • Daniel Aarno

    Daniel Aarno - 2020-10-24

    So, I think the idea here was that you "can't" really have multiple optional positional arguments. As an example, in this case how would the user specify the websocket port if they did not specify the transport port?

    Of course it would be possible to allow this and create an implicit dependency between the optional args, but it may be error prone for the programmer and confusing for the end user.

    For 1.4 we have introduced something called ArgGroups, it may be possible (would have to think about it), to support this better with help of an ArgGroup (e.g., a group with a strict ordering of dependent arguments).

    If you want to keep the current behaviour in your program, the patch you suggested looks like the right thing to do, just remember, users will be forced to provide a transport port if they want to change the websocket port.

    Either way, thanks for the suggestion, it's definetely something to think about.

     
  • Daniel Aarno

    Daniel Aarno - 2020-12-30
    • status: open --> wont-fix
     
  • Daniel Aarno

    Daniel Aarno - 2020-12-30

    Closing as won't fix due to lack of details/agreement on the problem. If your patch solves your problem, you can always implement it locally. However, I don't think the behaviour you want (if I understand correctly) is suitable for the general purpose library. Feel free to re-open if you have additional details or thoughts.

     
  • KOLANICH

    KOLANICH - 2021-08-15

    Multiple optional positional arguments may make sense. I.e. <tool name> <backend type 1> <backend type 2>, and when a backend is not specified, use the default one. The easiest way to resolve ambiguity is to assumme that the args that have been supplied occupy the arguments going earlier.

     

Log in to post a comment.

MongoDB Logo MongoDB