Comment appliquer les options de ligne de commande requises avec NDesk.Options?

j'écrivais juste un utilitaire de console et j'ai décidé d'utiliser NDesk.Options de ligne de commande de l'analyse. Ma question Est, Comment puis-je appliquer les options de ligne de commande requises?

je vois dans le docs que:

options avec une valeur requise (ajoute ' = ' au nom de l'option) ou une valeur optionnelle (ajoute ':' au nom de l'option).

cependant, quand j'ai mis un = à la fin du nom de l'option il n'y a pas de différence dans le comportement. Idéalement, la méthode Parse ferait une exception.

Est-il autre chose que je dois faire?

Voici mon code de test:

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);
    }
}
34
demandé sur Geoff 2010-08-06 23:58:06

2 réponses

le problème est que la documentation n'est pas aussi claire qu'elle devrait l'être. :- (

plus précisément, selon:

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

la = dans une spécification d'option ne s'applique pas à l'ensemble des options, mais seulement à la valeur pour cette option spécifique.

l'importance de ceci n'est vraiment pertinente que dans deux scénarios, alors considérons d'abord le parser OptionSet:

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

scénario 1 où il est important est que OptionSet.Parse () fonctionne en un seul passage, de manière forward-only, et ne pas regarder les valeurs d'option pour déterminer si elles "devraient être" des valeurs. Ainsi, considérons:

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

Le résultat de cette volonté a a la valeur "-b" , et b est null . Puisque le gestionnaire pour -a nécessite une valeur, il toujours obtient la valeur suivante (à moins que la valeur soit "encodée" dans l'option originale, par exemple -a=value ).

la deuxième place où ceci est important est quand une option nécessitant une valeur est la dernière option, et qu'il n'y a pas de valeur présente pour elle:

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

cela lancera une OptionException, car le gestionnaire pour -a nécessite une valeur, et aucune valeur n'est présente.

par conséquent, si vous avez une option qui est elle-même requise (par opposition à une option qui nécessite une valeur), vous devez vérifier manuellement pour cela:

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

if (dir == null)
    throw new InvalidOperationException ("Missing required option -o=DIR");
41
répondu jonp 2010-09-20 19:30:37

on peut étendre NDesk.Options un peu pour ajouter cette fonctionnalité.

tout d'abord, créez une classe SetupOption qui implémenterait 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"));
            }
        }
    }
}

Deuxièmement, ajouter une surcharge à ActionOption qui prend une instance D'INotifyPropertyChanged comme argument (l'appeler targetValue).

Troisièmement, modifier la classe D'options pour ajouter private INotifyPropertyChanged targetValue et private bool optionSet.

Quatrièmement, passez la valeur cible à L'Option lors de sa création. Abonnez-vous à L'événement PropertyChanged. De définir "optionSet" true si l'expéditeur n'est pas null.

ajoute une méthode Validate () à la classe D'options qui lancerait une exception si targetValue n'est pas null et optionSet est false.

enfin, ajouter une méthode Validate() à L'OptionContext qui bouclerait toutes les options et appellerait leurs méthodes Validate () respectives. Appel à la fin de la méthode Parse ().

voici le zip du code modifié: http://www.davidair.com/misc/options.zip

2
répondu David Airapetyan 2012-06-18 22:33:14