如何使用 NDesk.Options 强制执行所需的命令行选项?

发布于 2024-09-13 05:40:35 字数 1515 浏览 3 评论 0原文

我只是在编写一个控制台实用程序,并决定使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

痴梦一场 2024-09-20 05:40:35

问题在于文档并不像它显然需要的那样清晰。 :-(

具体来说,按照:

http://www.ndesk.org/doc/ndesk-options/NDesk.Options/OptionValueType.html#F:NDesk.Options.OptionValueType.Required

中的 =选项规范不适用于整个 OptionSet,而仅适用于该特定选项的

这一点的重要性实际上仅与两种情况相关,因此首先让我们考虑 OptionSet 解析器。 :

string a = null;
string b = null;
var options = new OptionSet {
    { "a=", v => a = v },
    { "b=", v => b = v },
};

在场景 1 中,重要的是 OptionSet.Parse() 以单遍、仅向前的方式工作,并且查看选项值来确定它们是否“应该是”值。 ,考虑:

options.Parse(new[]{"-a", "-b"});

这样的结果将是 a 的值为 "-b",而 bnull > 由于 -a 的处理程序需要一个值,因此它总是获取以下值(除非该值被“编码”到原始值中)。选项,例如-a=value)。

第二个重要的地方是当需要值的选项是最后一个选项,并且没有值存在时:

options.Parse(new[]{"-a"});

这将抛出 OptionException,作为 -a 的处理程序em>需要一个值,但不存在任何值。

因此,如果您有一个选项本身是必需的(而不是需要值的选项),则需要手动检查:

string dir = null;
new OptionSet {
    { "o=", v => dir = v },
}.Parse (args);

if (dir == null)
    throw new InvalidOperationException ("Missing required option -o=DIR");

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:

string a = null;
string b = null;
var options = new OptionSet {
    { "a=", v => a = v },
    { "b=", v => b = v },
};

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:

options.Parse(new[]{"-a", "-b"});

The result of this will be that a has the value "-b", and b is null. 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:

options.Parse(new[]{"-a"});

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:

string dir = null;
new OptionSet {
    { "o=", v => dir = v },
}.Parse (args);

if (dir == null)
    throw new InvalidOperationException ("Missing required option -o=DIR");
弃爱 2024-09-20 05:40:35

可以稍微扩展 NDesk.Options 来添加此功能。

首先,创建一个将实现 INotifyPropertyChanged 的​​ SetupOption 类:

class SetupOption<T> : INotifyPropertyChanged
{
    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion

    private T _value;

    public T Value
    {
        get
        {
            return _value;
        }
        set
        {
            _value = value;
            if (PropertyChanged != null)
            {
                PropertyChanged(_value, new PropertyChangedEventArgs("Value"));
            }
        }
    }
}

其次,向 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:

class SetupOption<T> : INotifyPropertyChanged
{
    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion

    private T _value;

    public T Value
    {
        get
        {
            return _value;
        }
        set
        {
            _value = value;
            if (PropertyChanged != null)
            {
                PropertyChanged(_value, new PropertyChangedEventArgs("Value"));
            }
        }
    }
}

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文