nemec / clipr

Command Line Interface ParseR for .Net

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Ability to reverse a boolean option.

dwrogers opened this issue · comments

I have a program that I have hardcoded some options into, including a couple of Boolean ones. I would like to be able to prompt the user for additional options, including the ability for them to undo options that were set by default. I had hoped to be able to just append user input to the string I hardcoded prior to calling CLIPR. To do this, I would need them to be able to specify options such as:

--whatIf false
or

--whatIf-

...in order to negate the "--whatIf" I had already included in the string. Is there a way to do this? Is this something that has come up before?

I have worked around this issue by adding a new, inverted logic option '--forReal'.

        bool _whatIfMode;

        [NamedArgument('w', "whatIf", Action = ParseAction.StoreTrue, Required = false,
            Description = "Perform all processing except for anything which would send messages or update the system")]
        public bool WhatIfMode
        {
            get { return _whatIfMode; }
            set { _whatIfMode = value; }
        }

        [NamedArgument('f', "forReal", Action = ParseAction.StoreFalse, Required = false,
            Description = "Resets 'whatIf' mode")]
        public bool ForRealMode
        {
            get { return !_whatIfMode; }
            set { _whatIfMode = value; }
        }

commented

So you're saying you've hardcoded a partial set of arguments (like --first value1 --whatIf true --second value2) and want to be able to append additional arguments to cancel out the ones that are already there? So in the end it would look something like this?

--first value1 --whatIf true --second value2 --whatIf false

Where options.WhatIfMode == false in the end?
Interesting, I haven't thought about this scenario.

Something that might work for you would be to take advantage of ParseAction.Count which will increment an integer every time the argument is specified. You can then have a second getter ask "is the count > 1?" to know whether you specified --whatIf twice. Or count % 2 == 0 to turn it on and off by specifying --whatIf an even or odd number of times.

class Options
{
    [NamedArgument('w', "whatIf", Action = ParseAction.Count)]
    public int WhatIfCount { get; set;}

    public bool WhatIfMode
    {
        get { return WhatIfCount > 1; }
    }
}

And to use it

void Main()
{
    var hardcoded = "--whatIf";
    string[] args;

    var addAnother = false;
    if (addAnother)
    {
        args = (hardcoded + " " + "--whatIf").Split();
    }
    else
    {
        args = hardcoded.Split();
    }

    var opts = CliParser.Parse<Options>(args);
    Console.WriteLine(opts.WhatIfMode);
}

Thoughts?

commented

Another option, and this is more of a parsing quirk than an actual feature, is that the parser seems to keep the last instance of a stored value:

class Options
{
    [NamedArgument('w', "whatIf", Action = ParseAction.Store)]
    public bool WhatIfMode { get; set; }
}
var opts = CliParser.Parse<Options>("--mode false --mode true".Split());
Console.WriteLine(opts.WhatIfMode); // prints true

Try the same with the second as false and it prints false. So you could hardcode the first part as --whatIf true and append --whatIf false as needed.

I guess it is a weird use case... I set the options up this way to allow the clients to develop a complicated form-based messaging configuration against live data without having to worry about changing any data - that's why the "whatIf" mode is turned on by default. I wanted them to have to have to do something different and obvious to be able to actually change data. But I also wanted to be able to let them fly at the right time without changing and republishing the program. (It is a ClickOnce program so they can't just change the program arguments.)

The ParseAction.Count method seems too imprecise to me - "do I have one of them or two of them?" The ParseAction.Store last-value-wins semantics does not have that problem. (I wasn't aware that clipr would figure out that it needed to convert the parameter to Boolean if the property was a Boolean!) I'll probably go that way in the future.

Thanks!
David

commented

Glad I could help. Also, if all you want is to have whatIf default to True (and then be able to set --whatIf false if needed), set it to True in the constructor for your options class:

class Options
{
    public Options()
    {
        WhatIfMode = true;
    }
    [NamedArgument('w', "whatIf", Action = ParseAction.Store)]
    public bool WhatIfMode { get; set; }
}