如何使用 NDesk.Options 强制执行所需的命令行选项?
我只是在编写一个控制台实用程序,并决定使用 NDesk.Options 进行命令行解析。我的问题是,如何强制执行所需的命令行选项?
我在 文档 中看到:
具有必需值(将“=”附加到选项名称)或可选值(将“:”附加到选项名称)的选项。
但是,当我在选项名称末尾添加 =
时,行为没有任何区别。理想情况下,Parse 方法会抛出异常。
我还需要做些什么吗?
这是我的测试代码:
class Program
{
static void Main(string[] args)
{
bool show_help = false;
string someoption = null;
var p = new OptionSet() {
{ "someoption=", "Some String Option", v => someoption = v},
{ "h|help", "show this message and exit", v => show_help = v != null }
};
List<string> extra;
try
{
extra = p.Parse(args);
}
catch (OptionException e)
{
System.Console.Write("myconsole: ");
System.Console.WriteLine(e.Message);
System.Console.WriteLine("Try `myconsole --help' for more information.");
return;
}
if (show_help)
{
ShowHelp(p);
return;
}
System.Console.WriteLine("==================");
System.Console.WriteLine(someoption);
}
static void ShowHelp(OptionSet p)
{
System.Console.WriteLine("Usage: myconsole [OPTIONS]");
System.Console.WriteLine();
System.Console.WriteLine("Options:");
p.WriteOptionDescriptions(System.Console.Out);
}
}
I was just writing a console utility and decided to use NDesk.Options for command-line parsing. My question is, How do I enforce required command-line options?
I see in the docs that:
options with a required value (append '=' to the option name) or an optional value (append ':' to the option name).
However, when I put a =
at the end of the option name there is no difference in behavior. Ideally the Parse method would throw an exception.
Is there something else I need to do?
Here is my test code:
class Program
{
static void Main(string[] args)
{
bool show_help = false;
string someoption = null;
var p = new OptionSet() {
{ "someoption=", "Some String Option", v => someoption = v},
{ "h|help", "show this message and exit", v => show_help = v != null }
};
List<string> extra;
try
{
extra = p.Parse(args);
}
catch (OptionException e)
{
System.Console.Write("myconsole: ");
System.Console.WriteLine(e.Message);
System.Console.WriteLine("Try `myconsole --help' for more information.");
return;
}
if (show_help)
{
ShowHelp(p);
return;
}
System.Console.WriteLine("==================");
System.Console.WriteLine(someoption);
}
static void ShowHelp(OptionSet p)
{
System.Console.WriteLine("Usage: myconsole [OPTIONS]");
System.Console.WriteLine();
System.Console.WriteLine("Options:");
p.WriteOptionDescriptions(System.Console.Out);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题在于文档并不像它显然需要的那样清晰。 :-(
具体来说,按照:
http://www.ndesk.org/doc/ndesk-options/NDesk.Options/OptionValueType.html#F:NDesk.Options.OptionValueType.Required
中的
=
选项规范不适用于整个 OptionSet,而仅适用于该特定选项的值。这一点的重要性实际上仅与两种情况相关,因此首先让我们考虑 OptionSet 解析器。 :
在场景 1 中,重要的是 OptionSet.Parse() 以单遍、仅向前的方式工作,并且不查看选项值来确定它们是否“应该是”值。 ,考虑:
这样的结果将是
a
的值为"-b"
,而b
为null
> 由于-a
的处理程序需要一个值,因此它总是获取以下值(除非该值被“编码”到原始值中)。选项,例如-a=value
)。第二个重要的地方是当需要值的选项是最后一个选项,并且没有值存在时:
这将抛出 OptionException,作为
-a
的处理程序em>需要一个值,但不存在任何值。因此,如果您有一个选项本身是必需的(而不是需要值的选项),则需要手动检查:
The problem is that documentation isn't as clear as it apparently needs to be. :-(
Specifically, as per:
http://www.ndesk.org/doc/ndesk-options/NDesk.Options/OptionValueType.html#F:NDesk.Options.OptionValueType.Required
The
=
within an option specification doesn't apply to the OptionSet as a whole, but just to the value for that specific option.The importance of this is really only relevant in two scenarios, so first let's consider the OptionSet parser:
Scenario 1 where it's important is that OptionSet.Parse() works in a single-pass, forward-only manner, and does not look at option values to determine if they "should be" values. Thus, consider:
The result of this will be that
a
has the value"-b"
, andb
isnull
. Since the handler for-a
requires a value, it always gets the following value (unless the value is "encoded" into the original option, e.g.-a=value
).The second place where this is important is when a value-requiring option is the last option, and there isn't a value present for it:
This will throw an OptionException, as the handler for
-a
requires a value, and no value is present.Consequently, if you have an option that itself is required (as opposed to an option that requires a value), you need to manually check for this:
可以稍微扩展 NDesk.Options 来添加此功能。
首先,创建一个将实现 INotifyPropertyChanged 的 SetupOption 类:
其次,向 ActionOption 添加一个重载,该重载采用 INotifyPropertyChanged 实例作为参数(将其称为 targetValue)。
第三,修改Option类以添加私有INotifyPropertyChanged targetValue和私有bool optionSet。
第四,创建Option时将targetValue传递给Option。订阅 PropertyChanged 事件。其中,如果发件人不为空,则将“optionSet”设置为 true。
将 Validate() 方法添加到 Option 类,如果 targetValue 不为 null 并且 optionSet 为 false,该方法将引发异常。
最后,向 OptionContext 添加一个 Validate() 方法,该方法将循环遍历所有选项并调用它们各自的 Validate() 方法。在 Parse() 方法的最后调用它。
以下是修改后的代码的 zip:http://www.davidair.com/misc/options。邮编
One can extend NDesk.Options a little bit to add this functionality.
First, create a SetupOption class that would implement INotifyPropertyChanged:
Second, add an overload to ActionOption that takes an instance of INotifyPropertyChanged as an argument (call it targetValue).
Third, modify the Option class to add private INotifyPropertyChanged targetValue and private bool optionSet.
Fourth, pass the targetValue to the Option when creating it. Subscribe to the PropertyChanged event. In it, set "optionSet" to true if the sender is not null.
Add a Validate() method to the Option class that would throw an exception if targetValue is not null and optionSet is false.
Finally, add a Validate() method to the OptionContext that would loop over all options and call their respective Validate() methods. Call it at the very end of the Parse() method.
Here is the zip of the modified code: http://www.davidair.com/misc/options.zip