2012-05-17 6 views
20

Zacząłem używać CommandLine Parser Library dla narzędzia, które będzie miało zarówno GUI, jak i wykonanie wiersza poleceń. Uruchomienie GUI odbywa się za pomocą opcji wiersza poleceń.Parser wiersza komend z wzajemnie wykluczającymi się wymaganymi parametrami

Chciałbym zatem mieć wymagane opcje na wypadek, gdyby program wykonywał się w trybie linii poleceń. Zasadniczo chciałbym, aby opcja 1 i opcja 2 były wymagane, jeśli opcja "Gui" nie jest ustawiona.

Próbowałem połączyć atrybuty MutuallyExclusiveSet i Required, jak pokazano poniżej, ale to nie działa tak jak myślałem. Czy źle zrozumiałem koncepcję "MutuallyExclusiveSet" lub po prostu nadużyłem jej? Czy jest to coś, czego biblioteka jeszcze nie wspiera?

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

Jak to działa w opozycji do tego, co oczekiwano, co było rzeczywiste zachowanie? –

+1

Biblioteka nie przetworzyła argumentów, jeśli przekazuję tylko "gui" z błędem wskazującym, że "opt1" jest wymagany. Spodziewam się, że działa tak jak "gui" w innym MutuallyExclusiveSet. –

Odpowiedz

34

Wszystkie opcje należące do wzajemnie wykluczającego się zestawu wzajemnie się wykluczają. Śledź ten przykład:

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; } 
} 

tych zasad następujących linii poleceń są ważne:

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

i nie są to:

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

Jak widać nie można określić opcje razem, które należą do tego samego zestawu. Pamiętaj również, że wstępnie skompilowany singleton (CommandLineParser.Default) nie działa z atrybutem MutualliyExclusiveSet. Musisz samodzielnie uformować parser:

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

W ten sposób wzajemnie wykluczające się opcje działają w Bibliotece parsera wiersza poleceń. W każdym razie, aby rozwiązać twój konkretny problem, proponuję zdefiniowanie wszystkich opcji, tak jak w zwykłej aplikacji konsolowej. Następnie dodaj przełącznik boolowski Gui. Jeśli ta opcja jest określona, ​​zignoruj ​​inne. Jeśli nie zachowujesz się jak normalna aplikacja konsolowa.

(Inna sprawa: w następnej wersji będzie funkcja o nazwie „podpoleceniami”, który pozwoli Ci zarządzać wieloma typy wariantów; to może prawo przypadku nadchodzącej funkcji.)

EDIT 2015- 08-30:

Funkcja zaimplementowana w stabilnej wersji 1.9.x zawsze powodowała zamieszanie, była domyślnie wyłączona i wymagała od programisty aktywacji jej za pomocą instancji ustawień.

Wersja 2.0.x, gdzie jądro zostało przepisane całkowicie, funkcja jest zawsze aktywna i spróbuję pokazać prosty przykład (pamiętaj, że publiczny interfejs API został zmieniony, ponieważ 2.0.x jest główną aktualizacją wydania).


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; } 
} 

Ustaw z ftp zestawu nie są zgodne z tymi, od web, --verbose (który nie należy do zestawu, albo lepiej należącej do domyślnego jeden "" jest neutralny i mogą być mieszane w dowolnym momencie). Ważny:


$ 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 

Nie ważne:


$ 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

Dziękuję bardzo za szczegółową odpowiedź! Miałem wrażenie, że źle zrozumiałem tę koncepcję ... W efekcie dodałem funkcję Validate do mojej klasy opcji, aby sprawdzić argumenty. To wystarczy, dopóki przyszły obiekt potencjalnie nie rozwiąże problemu. –

+4

Jest to dokładne przeciwieństwo tego, jak [wiki] (https://github.com/gsscoder/commandline/wiki/Mutually-Exclusive-Options) mówi, że działa, ale wygląda na to, że działa. – Rawling

+0

Czy można użyć parsera wiersza poleceń, aby wymagać podania jednego i tylko jednego z -a lub -b. Obecnie wydaje się, że zachowanie wymaga co najwyżej jednego z -a lub -b. –