Skip to content

Commit c3aa978

Browse files
Support main callback with ref parameter
1 parent 6e8ff28 commit c3aa978

File tree

2 files changed

+64
-6
lines changed

2 files changed

+64
-6
lines changed

source/argparse/api/cli.d

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ template CLI(Config config, COMMAND)
6262
return res;
6363
}
6464

65-
static int parseArgs(alias newMain)(string[] args, COMMAND initialValue = COMMAND.init)
66-
if(__traits(compiles, { newMain(COMMAND.init); }))
65+
static int parseArgs(alias newMain)(string[] args, auto ref COMMAND initialValue = COMMAND.init)
66+
if(__traits(compiles, { newMain(initialValue); }))
6767
{
6868
alias value = initialValue;
6969

@@ -80,8 +80,8 @@ template CLI(Config config, COMMAND)
8080
}
8181
}
8282

83-
static int parseArgs(alias newMain)(string[] args, COMMAND initialValue = COMMAND.init)
84-
if(__traits(compiles, { newMain(COMMAND.init, string[].init); }))
83+
static int parseArgs(alias newMain)(string[] args, auto ref COMMAND initialValue = COMMAND.init)
84+
if(__traits(compiles, { newMain(initialValue, string[].init); }))
8585
{
8686
alias value = initialValue;
8787

@@ -153,4 +153,61 @@ template CLI(Config config, COMMAND)
153153
}
154154
}
155155

156-
alias CLI(COMMANDS...) = CLI!(Config.init, COMMANDS);
156+
alias CLI(COMMANDS...) = CLI!(Config.init, COMMANDS);
157+
158+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
159+
160+
unittest
161+
{
162+
static struct Args {}
163+
164+
Args initValue;
165+
166+
enum cfg = Config.init;
167+
168+
assert(CLI!(cfg, Args).parseArgs!((_ ){})([]) == 0);
169+
assert(CLI!(cfg, Args).parseArgs!((_, string[] unknown){})([]) == 0);
170+
assert(CLI!(cfg, Args).parseArgs!((_ ){ return 123; })([]) == 123);
171+
assert(CLI!(cfg, Args).parseArgs!((_, string[] unknown){ return 123; })([]) == 123);
172+
173+
assert(CLI!(cfg, Args).parseArgs!((_ ){})([], initValue) == 0);
174+
assert(CLI!(cfg, Args).parseArgs!((_, string[] unknown){})([], initValue) == 0);
175+
assert(CLI!(cfg, Args).parseArgs!((_ ){ return 123; })([], initValue) == 123);
176+
assert(CLI!(cfg, Args).parseArgs!((_, string[] unknown){ return 123; })([], initValue) == 123);
177+
178+
// Ensure that CLI.main is compilable
179+
{ mixin CLI!(cfg, Args).main!((_ ){}); }
180+
{ mixin CLI!(cfg, Args).main!((_, string[] unknown){}); }
181+
{ mixin CLI!(cfg, Args).main!((_ ){ return 123; }); }
182+
{ mixin CLI!(cfg, Args).main!((_, string[] unknown){ return 123; }); }
183+
}
184+
185+
// Ensure that CLI works with non-copyable structs
186+
unittest
187+
{
188+
static struct Args {
189+
@disable this(ref Args);
190+
this(int) {}
191+
}
192+
193+
//Args initValue;
194+
auto initValue = Args(0);
195+
196+
enum cfg = Config.init;
197+
198+
assert(CLI!(cfg, Args).parseArgs!((ref _ ){})([]) == 0);
199+
assert(CLI!(cfg, Args).parseArgs!((ref _, string[] unknown){})([]) == 0);
200+
assert(CLI!(cfg, Args).parseArgs!((ref _ ){ return 123; })([]) == 123);
201+
assert(CLI!(cfg, Args).parseArgs!((ref _, string[] unknown){ return 123; })([]) == 123);
202+
203+
assert(CLI!(cfg, Args).parseArgs!((ref _ ){})([], initValue) == 0);
204+
assert(CLI!(cfg, Args).parseArgs!((ref _, string[] unknown){})([], initValue) == 0);
205+
assert(CLI!(cfg, Args).parseArgs!((ref _ ){ return 123; })([], initValue) == 123);
206+
assert(CLI!(cfg, Args).parseArgs!((ref _, string[] unknown){ return 123; })([], initValue) == 123);
207+
208+
// Ensure that CLI.main is compilable
209+
{ mixin CLI!(cfg, Args).main!((ref _ ){}); }
210+
{ mixin CLI!(cfg, Args).main!((ref _, string[] unknown){}); }
211+
{ mixin CLI!(cfg, Args).main!((ref _ ){ return 123; }); }
212+
{ mixin CLI!(cfg, Args).main!((ref _, string[] unknown){ return 123; }); }
213+
}

source/argparse/internal/command.d

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ private enum hasNoMembersWithUDA(COMMAND) = getSymbolsByUDA!(COMMAND, ArgumentUD
107107
getSymbolsByUDA!(COMMAND, SubCommands ).length == 0;
108108

109109
private enum isOpFunction(alias mem) = is(typeof(mem) == function) && __traits(identifier, mem).length > 2 && __traits(identifier, mem)[0..2] == "op";
110+
private enum isConstructor(alias mem) = is(typeof(mem) == function) && __traits(identifier, mem) == "__ctor";
110111

111112
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
112113

@@ -122,7 +123,7 @@ private template iterateArguments(TYPE)
122123
enum filter = !is(mem) && (
123124
hasUDA!(mem, ArgumentUDA) ||
124125
hasUDA!(mem, NamedArgument) ||
125-
hasNoMembersWithUDA!TYPE && !isOpFunction!mem && !isSumType!(typeof(mem)));
126+
hasNoMembersWithUDA!TYPE && !isOpFunction!mem && !isConstructor!mem && !isSumType!(typeof(mem)));
126127
}
127128

128129
alias iterateArguments = Filter!(filter, __traits(allMembers, TYPE));

0 commit comments

Comments
 (0)