web-dev-qa-db-ja.com

相互に排他的な必須パラメーターを持つコマンドラインパーサー

GUIとコマンドラインの両方を実行するツールに CommandLine Parser Library を使い始めました。 GUIの起動は、コマンドラインオプションを介して行われます。

したがって、プログラムがコマンドラインモードで実行されている場合に必要なオプションが必要です。基本的に、オプション「Gui」が設定されていない場合は、オプション1とオプション2が必要になります。

以下に示すように、MutuallyExclusiveSet属性とRequired属性を組み合わせようとしましたが、思ったとおりに機能しません。 「MutuallyExclusiveSet」の概念を誤解しましたか、それとも単に誤用しましたか?それとも、図書館がまだサポートしていないものですか?

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; }
}
23
Julien Jacobs

相互に排他的なセットに属するすべてのオプションは、それらの間で相互に排他的です。この例に従ってください:

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

これらのルールでは、次のコマンドラインが有効です。

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

そして、これらはそうではありません:

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

ご覧のとおり、同じセットに属するオプションを一緒に指定することはできません。ビルド済みのシングルトン(CommandLineParser.Default)はMutualliyExclusiveSet属性では機能しないことにも注意してください。パーサーを自分でドレスアップする必要があります。

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

これは、コマンドラインパーサーライブラリで相互に排他的なオプションが機能する方法です。とにかく、特定の問題を解決するには、通常のコンソールアプリケーションで行うのと同じようにすべてのオプションを定義することをお勧めします。次に、Guiブールスイッチを追加します。このオプションが指定されている場合、他のオプションは無視してください。通常のコンソールアプリとして動作しない場合。

(別のこと:次のバージョンでは、複数のオプションタイプを管理できる「サブコマンド」と呼ばれる機能があります。これは、この今後の機能に適している可能性があります。)

2015年8月30日編集:

1.9.x安定版に実装されている機能は常に混乱を招き、デフォルトでは無効になっており、開発者は設定インスタンスを介してアクティブ化する必要がありました。

カーネルが完全に書き直されたバージョン2.0.xでは、この機能は常にアクティブであり、簡単な例を示します(2.0.xはメジャーリリースアップデートであるため、パブリックAPIが変更されていることに注意してください)。


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

ftpセットからのセットは、web--verbose(セットに属していないか、デフォルトの""に属している方がよい)のセットと互換性がありません。ニュートラルであり、自由に混合できます)。有効:


$ 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

有効ではありません:


$ 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
44
gsscoder