I have a Poco (v1.9.4) based class
class PreprocessingApp : public Poco::Util::Application
with these 2 methods:
void PreprocessingApp::defineOptions(OptionSet& options)
{
Application::defineOptions(options);
options.addOption(
Option("proxy", "p", "Proxify connection")
.required(false)
.repeatable(false)
.argument("the value", false)
.callback(OptionCallback<PreprocessingApp>(this, &PreprocessingApp::handleBooleanOption))
);
options.addOption(
Option("test", "t", "Test something")
.required(true)
.repeatable(false)
.callback(OptionCallback<PreprocessingApp>(this, &PreprocessingApp::handleBooleanOption))
);
}
void PreprocessingApp::handleBooleanOption(const string& name, const string& value)
{
bool actualValue = value.empty() | value == "true" | value == "1";
config().setBool(name, actualValue);
}
As you can see, "proxy" is a boolean option. I added ".argument("the value", false)" to allow passing argument with this option, but flagged the "required" as false to make it optional.
That way I hoped to allow this functionality:
PreprocessingApp [-p [value]] -t [value]
Both variants should work:
PreprocessingApp -p -t
PreprocessingApp -p true -t
In reality, when debugging handleBooleanOption, the "value" is always empty "".
When switching required to true (.argument("the value", true)), the "value" is "-t" and next option processing is omitted.
Is there any solution to get it work as intended?
According to the Poco documentation:
Option arguments can be specified in three ways. If a Unix short option ("-o") is given, the argument directly follows the option name, without any delimiting character or space ("-ovalue"). In default option mode, or if a Unix long option ("--option") is given, the option argument is delimited from the option name with either an equal sign ('=') or a colon (':'), as in "--option=value" or "/option:value". Finally, a required option argument can be specified on the command line after the option, delimited with a space, as in "--option value" or "-o value". The latter only works for required option arguments, not optional ones.
Basically a required argument needs a space between the name and value whilst an optional one doesn't. So for your optional argument, specify it like this: -ptrue
or --proxytrue
or --proxy:true
.
For the required argument, there's another issue here. You would have thought that using the setter .required(true)
with Poco::Util::Option
would be enough to define a required argument in the code, but apparently not. You also have to use the setter .argument()
, which by default sets required
to true:
Option & argument(
const std::string & name,
bool required = true
);
So change your code for the required argument to:
options.addOption(
Poco::Util::Option("test", "t", "Test something")
.required(true)
.repeatable(false)
.argument("test")
.callback(Poco::Util::OptionCallback<ModbusInterface>(this, &ModbusInterface::handleBooleanOption))
);
Then you should be able to call your application like this, for example:
PreprocessingApp -ptrue -t true