Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor #183

Merged
merged 2 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 39 additions & 30 deletions source/argparse/internal/arguments.d
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module argparse.internal.arguments;
import argparse.internal.lazystring;

import argparse.config;
import argparse.param;
import argparse.result;

import std.typecons: Nullable;
Expand Down Expand Up @@ -36,23 +37,23 @@ package(argparse) struct ArgumentInfo
Nullable!size_t minValuesCount;
Nullable!size_t maxValuesCount;

auto checkValuesCount(const Config config, string argName, size_t count) const
auto checkValuesCount(const ref RawParam param) const
{
immutable min = minValuesCount.get;
immutable max = maxValuesCount.get;

// override for boolean flags
if(isBooleanFlag && count == 1)
if(isBooleanFlag && param.value.length == 1)
return Result.Success;

if(min == max && count != min)
return Result.Error("Argument '",config.styling.argumentName(argName),"': expected ",min,min == 1 ? " value" : " values");
if(min == max && param.value.length != min)
return Result.Error("Argument '",param.config.styling.argumentName(param.name),"': expected ",min,min == 1 ? " value" : " values");

if(count < min)
return Result.Error("Argument '",config.styling.argumentName(argName),"': expected at least ",min,min == 1 ? " value" : " values");
if(param.value.length < min)
return Result.Error("Argument '",param.config.styling.argumentName(param.name),"': expected at least ",min,min == 1 ? " value" : " values");

if(count > max)
return Result.Error("Argument '",config.styling.argumentName(argName),"': expected at most ",max,max == 1 ? " value" : " values");
if(param.value.length > max)
return Result.Error("Argument '",param.config.styling.argumentName(param.name),"': expected at most ",max,max == 1 ? " value" : " values");

return Result.Success;
}
Expand All @@ -70,28 +71,36 @@ unittest
return info;
}

assert(info(2,4).checkValuesCount(Config.init, "", 1).isError("expected at least 2 values"));
assert(info(2,4).checkValuesCount(Config.init, "", 2));
assert(info(2,4).checkValuesCount(Config.init, "", 3));
assert(info(2,4).checkValuesCount(Config.init, "", 4));
assert(info(2,4).checkValuesCount(Config.init, "", 5).isError("expected at most 4 values"));

assert(info(2,2).checkValuesCount(Config.init, "", 1).isError("expected 2 values"));
assert(info(2,2).checkValuesCount(Config.init, "", 2));
assert(info(2,2).checkValuesCount(Config.init, "", 3).isError("expected 2 values"));

assert(info(1,1).checkValuesCount(Config.init, "", 0).isError("expected 1 value"));
assert(info(1,1).checkValuesCount(Config.init, "", 1));
assert(info(1,1).checkValuesCount(Config.init, "", 2).isError("expected 1 value"));

assert(info(0,1).checkValuesCount(Config.init, "", 0));
assert(info(0,1).checkValuesCount(Config.init, "", 1));
assert(info(0,1).checkValuesCount(Config.init, "", 2).isError("expected at most 1 value"));

assert(info(1,2).checkValuesCount(Config.init, "", 0).isError("expected at least 1 value"));
assert(info(1,2).checkValuesCount(Config.init, "", 1));
assert(info(1,2).checkValuesCount(Config.init, "", 2));
assert(info(1,2).checkValuesCount(Config.init, "", 3).isError("expected at most 2 values"));
Config config;
auto p0 = RawParam(&config, "", []);
auto p1 = RawParam(&config, "", ["",]);
auto p2 = RawParam(&config, "", ["","",]);
auto p3 = RawParam(&config, "", ["","","",]);
auto p4 = RawParam(&config, "", ["","","","",]);
auto p5 = RawParam(&config, "", ["","","","","",]);

assert(info(2,4).checkValuesCount(p1).isError("expected at least 2 values"));
assert(info(2,4).checkValuesCount(p2));
assert(info(2,4).checkValuesCount(p3));
assert(info(2,4).checkValuesCount(p4));
assert(info(2,4).checkValuesCount(p5).isError("expected at most 4 values"));

assert(info(2,2).checkValuesCount(p1).isError("expected 2 values"));
assert(info(2,2).checkValuesCount(p2));
assert(info(2,2).checkValuesCount(p3).isError("expected 2 values"));

assert(info(1,1).checkValuesCount(p0).isError("expected 1 value"));
assert(info(1,1).checkValuesCount(p1));
assert(info(1,1).checkValuesCount(p2).isError("expected 1 value"));

assert(info(0,1).checkValuesCount(p0));
assert(info(0,1).checkValuesCount(p1));
assert(info(0,1).checkValuesCount(p2).isError("expected at most 1 value"));

assert(info(1,2).checkValuesCount(p0).isError("expected at least 1 value"));
assert(info(1,2).checkValuesCount(p1));
assert(info(1,2).checkValuesCount(p2));
assert(info(1,2).checkValuesCount(p3).isError("expected at most 2 values"));
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
8 changes: 4 additions & 4 deletions source/argparse/internal/argumentuda.d
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@ package(argparse) struct ArgumentUDA(ValueParser)

package(argparse) ValueParser valueParser;

package Result parse(COMMAND_STACK, RECEIVER)(const Config config, const COMMAND_STACK cmdStack, ref RECEIVER receiver, string argName, string[] rawValues)
package Result parse(COMMAND_STACK, RECEIVER)(const COMMAND_STACK cmdStack, ref RECEIVER receiver, RawParam param)
{
try
{
auto res = info.checkValuesCount(config, argName, rawValues.length);
auto res = info.checkValuesCount(param);
if(!res)
return res;

return valueParser.parseParameter(receiver, RawParam(&config, argName, rawValues));
return valueParser.parseParameter(receiver, param);
}
catch(Exception e)
{
return Result.Error("Argument '", config.styling.argumentName(argName), ": ", e.msg);
return Result.Error("Argument '", param.config.styling.argumentName(param.name), ": ", e.msg);
}
}

Expand Down
37 changes: 20 additions & 17 deletions source/argparse/internal/command.d
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,24 @@ package struct SubCommands

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

private Result ArgumentParsingFunction(Config config, alias uda, RECEIVER)(const Command[] cmdStack,
ref RECEIVER receiver,
string argName,
string[] rawValues)
private Result ArgumentParsingFunction(alias uda, RECEIVER)(const Command[] cmdStack,
ref RECEIVER receiver,
ref RawParam param)
{
static if(uda.info.memberSymbol)
auto target = &__traits(getMember, receiver, uda.info.memberSymbol);
else
auto target = null;

return uda.parse(config, cmdStack, target, argName, rawValues);
return uda.parse(cmdStack, target, param);
}

private Result ArgumentCompleteFunction(Config config, alias uda, RECEIVER)(const Command[] cmdStack,
ref RECEIVER receiver,
string argName,
string[] rawValues)
private alias getArgumentParsingFunction1(alias uda) =
(const Command[] cmdStack, ref RawParam param) => ArgumentParsingFunction!uda(cmdStack, receiver, param);

private Result ArgumentCompleteFunction(alias uda, RECEIVER)(const Command[] cmdStack,
ref RECEIVER receiver,
ref RawParam param)
{
return Result.Success;
}
Expand All @@ -70,10 +71,12 @@ unittest
auto test(string[] values)
{
T t;
Config cfg;
auto param = RawParam(&cfg, "a", values);

enum uda = getMemberArgumentUDA!(T, "a")(Config.init);

return ArgumentParsingFunction!(Config.init, uda)([], t, "a", values);
return ArgumentParsingFunction!uda([], t, param);
}

assert(test(["raw-value"]));
Expand All @@ -88,19 +91,21 @@ unittest
}

T t;
Config cfg;
auto param = RawParam(&cfg, "func", []);

enum uda = getMemberArgumentUDA!(T, "func")(Config.init);

auto res = ArgumentParsingFunction!(Config.init, uda)([], t, "func", []);
auto res = ArgumentParsingFunction!uda([], t, param);

assert(res.isError(Config.init.styling.argumentName("func")~": My Message."));
assert(res.isError("func",": My Message."));
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

package struct Command
{
alias Parse = Result delegate(const Command[] cmdStack, string argName, string[] argValue);
alias Parse = Result delegate(const Command[] cmdStack,ref RawParam param);

struct Argument
{
Expand Down Expand Up @@ -351,14 +356,12 @@ package(argparse) Command createCommand(Config config, COMMAND_TYPE)(ref COMMAND
res.restrictions.add!(COMMAND_TYPE, [typeTraits.argumentInfos])(config);

enum getArgumentParsingFunction(alias uda) =
(const Command[] cmdStack, string argName, string[] argValue)
=> ArgumentParsingFunction!(config, uda)(cmdStack, receiver, argName, argValue);
(const Command[] cmdStack, ref RawParam param) => ArgumentParsingFunction!uda(cmdStack, receiver, param);

res.parseFuncs = [staticMap!(getArgumentParsingFunction, typeTraits.argumentUDAs)];

enum getArgumentCompleteFunction(alias uda) =
(const Command[] cmdStack, string argName, string[] argValue)
=> ArgumentCompleteFunction!(config, uda)(cmdStack, receiver, argName, argValue);
(const Command[] cmdStack, ref RawParam param) => ArgumentCompleteFunction!uda(cmdStack, receiver, param);

res.completeFuncs = [staticMap!(getArgumentCompleteFunction, typeTraits.argumentUDAs)];

Expand Down
5 changes: 3 additions & 2 deletions source/argparse/internal/help.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module argparse.internal.help;

import argparse.ansi;
import argparse.config;
import argparse.param;
import argparse.result;
import argparse.api.ansi: ansiStylingArgument;
import argparse.internal.lazystring;
Expand Down Expand Up @@ -154,7 +155,7 @@ package struct HelpArgumentUDA
return info;
}();

Result parse(COMMAND_STACK, RECEIVER)(const Config config, const COMMAND_STACK cmdStack, ref RECEIVER, string argName, string[] rawValues)
Result parse(COMMAND_STACK, RECEIVER)(const COMMAND_STACK cmdStack, ref RECEIVER receiver, RawParam param)
{
import std.stdio: stdout;
import std.algorithm: map;
Expand All @@ -165,7 +166,7 @@ package struct HelpArgumentUDA
auto args = cmdStack.map!((ref _) => &_.arguments).array;

auto output = stdout.lockingTextWriter();
printHelp(_ => output.put(_), config, cmdStack[$-1], args, progName);
printHelp(_ => output.put(_), *param.config, cmdStack[$-1], args, progName);

return Result.Error(0, ""); // hack to force-exit (to be removed)
}
Expand Down
Loading