2012-05-17 7 views
20

Ich fing an, das CommandLine Parser Library für ein Werkzeug zu verwenden, das eine GUI und eine Befehlszeilenausführung hat. Das Starten der GUI erfolgt über eine Befehlszeilenoption.Command Line Parser mit sich gegenseitig ausschließenden erforderlichen Parametern

Ich möchte daher Optionen benötigt, falls das Programm im Befehlszeilenmodus ausgeführt wird. Grundsätzlich würde ich Option 1 und Option 2 benötigen, wenn die Option "Gui" nicht gesetzt ist.

Ich habe versucht, die MutualExclusiveSet und Required Attribute wie unten gezeigt zu kombinieren, aber es funktioniert nicht, wie ich dachte. Habe ich das Konzept von "MutualExclusiveSet" falsch verstanden oder missbraucht? Oder ist es etwas, das die Bibliothek noch nicht unterstützt?

public class CommandLineOptions : CommandLineOptionsBase 
{ 
    [Option(null, "gui", Required = false, HelpText = "Launch the GUI", MutuallyExclusiveSet = "Gui")] 
    public bool Gui { get; set; } 

    [Option(null, "opt1", HelpText = "Option 1", MutuallyExclusiveSet = "CommandLine", Required = true)] 
    public string Option1 { get; set; } 

    [Option(null, "opt2", HelpText = "Option 2", MutuallyExclusiveSet = "CommandLine", Required = true)] 
    public string Option2 { get; set; } 
} 
+0

Wie es gegenüberliegenden funktionierten, was Sie erwartet, was das tatsächliche Verhalten? –

+1

Die Bibliothek konnte die Argumente nicht analysieren, wenn ich nur "gui" mit einem Fehler übergebe, der angibt, dass "opt1" erforderlich ist. Ich würde erwarten, dass es funktioniert, da "gui" in einem anderen MutualExclusiveSet ist. –

Antwort

34

Alle Optionen, die zu einem sich gegenseitig ausschließenden Satz gehören, schließen sich gegenseitig aus. Folgen Sie diesem Beispiel:

class Options { 
    [Option("a", null, MutuallyExclusiveSet="zero")] 
    public string OptionA { get; set; } 
    [Option("b", null, MutuallyExclusiveSet="zero")] 
    public string OptionB { get; set; } 
    [Option("c", null, MutuallyExclusiveSet="one")] 
    public string OptionC { get; set; } 
    [Option("d", null, MutuallyExclusiveSet="one")] 
    public string OptionD { get; set; } 
} 

Mit diesen Regeln folgenden Befehlszeilen gültig:

$ app -a foo -c bar 
$ app -a foo -d bar 
$ app -b foo -c bar 
$ app -b foo -d bar 

und diese sind nicht:

$ app -a foo -b bar 
$ app -c foo -d bar 
$ app -a foo -b bar -c foo1 -d foo2 

Wie Sie Sie nicht angeben können, sehen Optionen zusammen, die zu demselben Set gehören. Denken Sie auch daran, dass vorgefertigte Singleton (CommandLineParser.Default) nicht mit MutualliyExclusiveSet Attribut arbeiten. Sie benötigen einen Parser, indem Sie Ihre eigenen verkleiden:

if (new CommandLineParser(new CommandLineParserSettings { 
          MutuallyExclusive = true, 
          CaseSensitive = true, 
          HelpWriter = Console.Error}).ParseArguments(args, opts) { 
    // consume values here 
    Console.WriteLine(opts.OptionA); 
} 

Dies ist die Art und Weise gegenseitig ausschließende Optionen in Command Line Parser-Bibliothek arbeiten. Um Ihr spezifisches Problem zu lösen, empfehle ich Ihnen, alle Optionen so zu definieren, wie Sie es in einer normalen Konsolenanwendung tun würden. Fügen Sie dann den booleschen Schalter Gui hinzu. Wenn diese Option angegeben ist, ignorieren Sie andere. Wenn Sie sich nicht wie eine normale Konsolenanwendung verhalten.

(Eine andere Sache: in einer späteren Version eine Funktion namens „Subbefehle“ wird, dass Sie mehrere Optionen Typen verwalten lassen, dies vielleicht der richtige Fall für diese kommende Funktion.)

EDIT 2015- 08-30:

Die in 1.9.x stable implementierte Funktion verursachte immer Verwirrung, war standardmäßig deaktiviert und musste vom Entwickler über Einstellungsinstanzen aktiviert werden.

Version 2.0.x, wo der Kernel komplett neu geschrieben wurde, ist die Funktion immer aktiv, und ich werde versuchen, ein einfaches Beispiel zu zeigen, (denken Sie daran, dass die öffentliche API geändert wird seit 2.0.x ein Major-Release-Update).


class Options { 
    [Option(SetName = "web")] 
    public string WebUrl { get; set; } 
    [Option(SetName = "web")] 
    public int MaxLinks { get; set; } 

    [Option(SetName = "ftp")] 
    public string FtpUrl { get; set; } 
    [Option(SetName = "ftp")] 
    public int MaxFiles { get; set; } 

    [Option] 
    public bool Verbose { get; set; } 
} 

Set von ftp Sets ist nicht kompatibel mit denen von web, --verbose (die zu einem Satz gehören nicht, oder besser gehören zur Standard eines "" sind neutral und kann nach Belieben gemischt werden). Gültig:


$ app --weburl http://stackoverflow.com --maxlinks 99 
$ app --ftpurl ftp://ftp.myoffice.files.com --maxfiles 1234 
$ app --verbose --weburl http://twitter.com --maxlinks 777 
$ app --ftpurl ftp://ftp.xyz.org --maxfiles 44 --verbose 
$ app --verbose 

Nicht gültig:


$ app --weburl http://stackoverflow.com --maxlinks 99 --ftpurl ftp://ftp.xyz.org 
$ app --ftpurl ftp://ftp.myoffice.files.com --maxfiles 1234 --maxlinks 777 
$ app --verbose --weburl http://twitter.com --maxfiles 44 
$ app --maxfiles 44 --maxlinks 99 
+0

Vielen Dank für die ausführliche Antwort! Ich hatte das Gefühl, dass ich das Konzept missverstanden habe ... Ich habe meiner Optionsklasse eine Validate-Funktion hinzugefügt, um die Argumente zu überprüfen. Das wird ausreichen, bis ein zukünftiges Feature diesen Fall adressiert. –

+4

Dies ist das genaue Gegenteil von dem, wie [das Wiki] (https://github.com/gsscoder/commandline/wiki/Mutually-Exclusive-Options) sagt, es funktioniert, aber es scheint so zu funktionieren. – Rawling

+0

Ist es möglich, den Befehlszeilen-Parser zu verwenden, um zu verlangen, dass nur einer von -a oder -b angegeben wird? Gerade jetzt scheint es, dass das Verhalten höchstens eines von -a oder -b erfordert. –

Verwandte Themen