2012-05-17 31 views
20

Tôi bắt đầu sử dụng CommandLine Parser Library cho một công cụ sẽ có cả GUI và thực thi dòng lệnh. Việc khởi chạy GUI được thực hiện thông qua tùy chọn dòng lệnh.Trình phân tích cú pháp dòng lệnh với các thông số bắt buộc loại trừ lẫn nhau

Do đó, tôi muốn có các tùy chọn bắt buộc trong trường hợp chương trình đang thực hiện ở chế độ dòng lệnh. Về cơ bản, tôi sẽ muốn Option 1 và Option 2 được yêu cầu nếu tùy chọn "Gui" không được thiết lập.

Tôi đã cố gắng kết hợp các thuộc tính MutuallyExclusiveSet và Required như được hiển thị bên dưới, nhưng nó không hoạt động như tôi nghĩ. Tôi đã hiểu nhầm khái niệm "MutualExclusiveSet" hay chỉ đơn giản là lạm dụng nó? Hay là thư viện chưa hỗ trợ?

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

Làm sao cho nó hoạt động trái ngược với những gì bạn mong đợi, là những gì các hành vi thực tế? –

+1

Thư viện không thể phân tích các đối số nếu tôi chỉ chuyển "gui" với lỗi cho biết "opt1" là bắt buộc. Tôi hy vọng rằng nó hoạt động như "gui" là trong một MutuallyExclusiveSet khác nhau. –

Trả lời

34

Tất cả các tùy chọn thuộc về tập hợp lẫn nhau đều loại trừ lẫn nhau. theo ví dụ này:

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

Với những quy tắc sau đây dòng lệnh có hiệu lực:

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

và đây không phải là:

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

Như bạn thấy bạn không thể xác định các tùy chọn cùng thuộc về cùng một tập hợp. Cũng nên nhớ rằng singleton đã được dựng sẵn (CommandLineParser.Default) không hoạt động với thuộc tính MutualliyExclusiveSet. Bạn cần phải tự mình tạo một trình phân tích cú pháp:

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

Đây là cách các tùy chọn loại trừ lẫn nhau hoạt động trong Thư viện trình phân tích cú pháp dòng lệnh. Dù sao để giải quyết vấn đề cụ thể của bạn, tôi đề nghị bạn xác định tất cả các tùy chọn như bạn sẽ làm trong một ứng dụng giao diện điều khiển bình thường. Sau đó, thêm công tắc Gui boolean. Nếu tùy chọn này được chỉ định, hãy bỏ qua những tùy chọn khác. Nếu không hoạt động như một ứng dụng giao diện điều khiển thông thường.

(Một điều: trong một phiên bản tiếp theo sẽ được một tính năng gọi là "lệnh con" mà sẽ cho phép bạn quản lý tùy chọn nhiều loại, điều này có lẽ là trường hợp phù hợp với tính năng sắp tới này.)

EDIT 2015- 08-30:

Tính năng được thực hiện trong sự cố ổn định luôn luôn tạo ra 1.9.x, đã bị tắt theo mặc định và yêu cầu nhà phát triển kích hoạt nó thông qua cài đặt thể hiện.

Phiên bản 2.0.x, nơi hạt nhân được viết lại hoàn toàn, tính năng luôn hoạt động và tôi sẽ cố gắng hiển thị một ví dụ đơn giản (nhớ rằng API công khai được thay đổi kể từ 2.0.x là bản cập nhật chính).


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 từ ftp bộ không tương thích với những người từ web, --verbose (mà không thuộc về một bộ, hoặc tốt hơn thuộc về mặc định một "" là trung lập và có thể được trộn lẫn theo ý muốn). hợp lệ:


$ 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 

Không áp dụng:


$ 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

Cảm ơn bạn rất nhiều vì câu trả lời chi tiết! Tôi có cảm giác rằng tôi đã hiểu nhầm khái niệm ... Tôi đã kết thúc việc thêm hàm Validate vào lớp tùy chọn của tôi để kiểm tra các đối số. Điều đó sẽ thực hiện thủ thuật cho đến khi một tính năng trong tương lai có khả năng giải quyết trường hợp này. –

+4

Điều này hoàn toàn trái ngược với cách [wiki] (https://github.com/gsscoder/commandline/wiki/Mutually-Exclusive-Options) nói rằng nó hoạt động, nhưng nó hoạt động như thế nào. – Rawling

+0

Có thể sử dụng trình phân tích cú pháp dòng lệnh để yêu cầu một và chỉ một -a hoặc -b được chỉ định. Ngay bây giờ có vẻ như hành vi yêu cầu nhiều nhất một -a hoặc -b. –

Các vấn đề liên quan