34 votes

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

J'étais en train d'écrire un utilitaire de console et décidé de l'utiliser NDesk.Options de ligne de commande de l'analyse. Ma question est, Comment puis-je faire appliquer requis options de ligne de commande?

Je vois dans les docs que:

options avec une valeur obligatoire (append '=' le nom de l'option) ou une valeur facultative (append ':' pour le nom de l'option).

Cependant, quand je mets un = à la fin du nom de l'option il n'y a pas de différence dans le comportement. Idéalement, la méthode d'analyse permettrait de lever 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);
    }
}

42voto

jonp Points 10039

Le problème est que la documentation n'est pas aussi claire qu'elle en a apparemment besoin de l'être. :-(

Plus précisément, comme par:

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

L' = au sein d'une option de spécification ne s'applique pas à la OptionSet dans son ensemble, mais seulement à la valeur de cette option.

L'importance de ce qui est vraiment valable que dans les deux scénarios, alors d'abord, considérons le OptionSet analyseur:

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 que les OptionSet.Parse() fonctionne en un seul passage, de l'avant-seule manière, et de ne pas regarder les valeurs de l'option pour déterminer si elles doivent être " des valeurs. Ainsi, pensez à:

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

Le résultat de ce que sera a a la valeur "-b", et b est null. Depuis le gestionnaire de -a nécessite une valeur, c'est toujours obtient la valeur suivante (sauf si la valeur est "codé" dans l'option d'origine, par exemple, -a=value).

Le deuxième endroit où c'est important, c'est quand une valeur nécessitant de l'option est la dernière option, et il n'y a pas une valeur pour elle:

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

Cela permettra de jeter un OptionException, comme gestionnaire pour -a nécessite une valeur, et aucune valeur n'est présente.

Par conséquent, si vous avez une option qui lui-même est nécessaire (par opposition à une option qui nécessite une valeur de), 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");

2voto

David Airapetyan Points 667

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

Tout d'abord, créez un SetupOption classe qui permettrait d'implémenter 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"));
            }
        }
    }
}

Ensuite, ajoutez une surcharge de ActionOption qui prend une instance de INotifyPropertyChanged comme un argument (l'appeler valeurcible).

Troisièmement, modifier la classe d'Option pour ajouter privé INotifyPropertyChanged valeurcible et private bool optionSet.

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

Ajouter un Validate() la méthode de la classe d'Option qui permettrait de lever une exception si valeurcible n'est pas null et optionSet est faux.

Enfin, ajouter un Validate() la méthode la OptionContext qui serait en boucle sur toutes les options et appeler leurs respectifs Valider() méthodes. Appel à la fin de la méthode Parse ().

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X