diff --git a/README.md b/README.md index 14bfa52..a46dd63 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ void main(string[] argv) .parse(argv); auto parts = args.argument("string").split(args.option("separator")); - if (args.flag("first")) + if (args.hasFlag("first")) writeln(parts[0]); else writeln(parts); @@ -108,9 +108,9 @@ if (args.hasOption("--config")) { } // Check boolean flags -if (args.flag("verbose")) +if (args.hasFlag("verbose")) writeln("Verbose mode enabled"); -const bool quiet = args.flag("-q"); +const bool quiet = args.hasFlag("-q"); ``` You can access options using: @@ -119,7 +119,7 @@ You can access options using: - `option("-t")` - access by short name (explicit) - `option("--target")` - access by long name (explicit, stylistic) -(also applies for `hasOption()`, `flag()`, etc.) +(also applies for `hasOption()`, `hasFlag()`, etc.) ## Arguments @@ -190,7 +190,7 @@ void main(string[] args) .option("--excited", "Add excitement to the greeting") .action((args) { auto msg = "Hello, " ~ args.argument("name"); - if (args.flag("excited")) + if (args.hasFlag("excited")) msg ~= "!!!"; writeln(msg); return 0; @@ -238,7 +238,7 @@ class GreetCommand : Command private int execute(ParsedArgs args) { auto msg = "Hello, " ~ args.argument("name"); - if (args.flag("excited")) + if (args.hasFlag("excited")) msg ~= "!!!"; writeln(msg); return 0; diff --git a/examples/modular.d b/examples/modular.d index 7b459c3..6351122 100644 --- a/examples/modular.d +++ b/examples/modular.d @@ -19,7 +19,7 @@ class GreetCommand : Command private int execute(ParsedArgs args) { auto msg = "Hello, " ~ args.argument("name"); - if (args.flag("excited")) + if (args.hasFlag("excited")) msg ~= "!!!"; writeln(msg); return 0; diff --git a/examples/split.d b/examples/split.d index 62e96f5..943eaec 100644 --- a/examples/split.d +++ b/examples/split.d @@ -16,7 +16,7 @@ void main(string[] argv) .parse(argv); auto parts = args.argument("string").split(args.option("separator")); - if (args.flag("first")) + if (args.hasFlag("first")) writeln(parts[0]); else writeln(parts); diff --git a/examples/subcommands.d b/examples/subcommands.d index cf93fbe..ec43a51 100644 --- a/examples/subcommands.d +++ b/examples/subcommands.d @@ -26,7 +26,7 @@ void main(string[] args) .option("--excited", "Add excitement to the greeting") .action((args) { auto msg = "Hello, " ~ args.argument("name"); - if (args.flag("excited")) + if (args.hasFlag("excited")) msg ~= "!!!"; writeln(msg); return 0; diff --git a/src/cmd/command.d b/src/cmd/command.d index 7bd4a88..ffaca0e 100644 --- a/src/cmd/command.d +++ b/src/cmd/command.d @@ -321,6 +321,7 @@ public class Command { string[][const(Option)] parsedOptions = new string[][Option]; string[] variadic = []; + uint[const(Flag)] parsedFlags = new uint[Flag]; for (size_t i = 0; i < args.length; ++i) { string arg = args[i]; @@ -335,7 +336,7 @@ public class Command { const shortArg = "-" ~ c; const(Flag) f = findFlag(shortArg); if (f !is null) { - parsedArgs.setFlag(f); + parsedFlags[f] = parsedFlags.get(f, 0) + 1; continue; } const(Option) opt = findOption(shortArg); @@ -348,7 +349,7 @@ public class Command { const(Flag) flag = findFlag(arg); if (flag !is null) { - parsedArgs.setFlag(flag); + parsedFlags[flag] = parsedFlags.get(flag, 0) + 1; continue; } @@ -391,6 +392,10 @@ public class Command { if (!variadic.empty()) parsedArgs.setArgumentList(variadic); + foreach (flag, count; parsedFlags) { + parsedArgs.setFlag(flag, count); + } + foreach (opt, value; parsedOptions) { parsedArgs.setOption(opt, value); } diff --git a/src/cmd/parsed_args.d b/src/cmd/parsed_args.d index c6cf304..1332fec 100644 --- a/src/cmd/parsed_args.d +++ b/src/cmd/parsed_args.d @@ -16,7 +16,7 @@ public final class ParsedArgs { /** Program associated with the parsed arguments. */ public const(Program) program; - private bool[string] flags; + private uint[string] flags; private string[][string] options; private string[string] arguments; package string[] variadic; @@ -27,15 +27,31 @@ public final class ParsedArgs { } /** Checks whether the given flag name is present. */ - public bool flag(string name) const nothrow @safe { + public bool hasFlag(string name) const nothrow @safe { foreach (prefix; ["", "-", "--"]) if (auto p = prefix ~ name in flags) - return *p; + return *p > 0; return false; } /** Checks whether the given flag is present. */ - public bool flag(Flag flag) const nothrow @safe { + public bool hasFlag(Flag flag) const nothrow @safe { + if (flag.longName !is null) + return this.hasFlag("--" ~ flag.longName); + return this.hasFlag("-" ~ flag.shortName); + } + + /** Returns the number of times the flag with the given name was passed. */ + public uint flag(string name) const nothrow @safe { + foreach (prefix; ["", "-", "--"]) { + if (auto p = prefix ~ name in flags) + return *p; + } + return 0; + } + + /** Returns the number of times the given flag was passed. */ + public uint flag(const(Flag) flag) const nothrow @safe { if (flag.longName !is null) return this.flag("--" ~ flag.longName); return this.flag("-" ~ flag.shortName); @@ -122,11 +138,11 @@ public final class ParsedArgs { options["-" ~ option.shortName] = values; } - package void setFlag(const(Flag) flag, bool value = true) nothrow @safe { + package void setFlag(const(Flag) flag, uint count) nothrow @safe { if (flag.longName !is null) - flags["--" ~ flag.longName] = value; + flags["--" ~ flag.longName] = count; if (flag.shortName !is null) - flags["-" ~ flag.shortName] = value; + flags["-" ~ flag.shortName] = count; } package void setArgument(const(Argument) argument, string value) @safe {