Skip to content

Commit 4def472

Browse files
committed
add options parseOrExitMethodAcceptsList and enableAtFileExpansion
1 parent 7655e95 commit 4def472

9 files changed

Lines changed: 131 additions & 31 deletions

File tree

compiler/src/main/java/net/jbock/processor/SourceElement.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,18 @@ boolean isSkipGeneratingParseOrExitMethod() {
9292
SuperCommand::skipGeneratingParseOrExitMethod);
9393
}
9494

95+
boolean isParseOrExitMethodAcceptsList() {
96+
return command.fold(
97+
Command::parseOrExitMethodAcceptsList,
98+
SuperCommand::parseOrExitMethodAcceptsList);
99+
}
100+
101+
boolean isEnableAtFileExpansion() {
102+
return command.fold(
103+
Command::enableAtFileExpansion,
104+
SuperCommand::enableAtFileExpansion);
105+
}
106+
95107
String[] getDescription() {
96108
return command.fold(
97109
Command::description,
@@ -150,4 +162,12 @@ public List<String> description() {
150162
public boolean skipGeneratingParseOrExitMethod() {
151163
return command.isSkipGeneratingParseOrExitMethod();
152164
}
165+
166+
public boolean parseOrExitMethodAcceptsList() {
167+
return command.isParseOrExitMethodAcceptsList();
168+
}
169+
170+
public boolean enableAtFileExpansion() {
171+
return command.isEnableAtFileExpansion();
172+
}
153173
}

compiler/src/main/java/net/jbock/writing/HasCommandRepresentation.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,12 @@ final List<Mapping<?>> allMappings() {
5050
final boolean isSuperCommand() {
5151
return commandRepresentation.sourceElement().isSuperCommand();
5252
}
53+
54+
final boolean parseOrExitMethodAcceptsList() {
55+
return commandRepresentation.sourceElement().parseOrExitMethodAcceptsList();
56+
}
57+
58+
final boolean enableAtFileExpansion() {
59+
return commandRepresentation.sourceElement().enableAtFileExpansion();
60+
}
5361
}

compiler/src/main/java/net/jbock/writing/ParseOrExitMethod.java

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
import net.jbock.util.AtFileError;
1010
import net.jbock.util.ParseRequest;
1111

12+
import java.util.List;
13+
1214
import static io.jbock.javapoet.MethodSpec.methodBuilder;
1315
import static io.jbock.javapoet.ParameterSpec.builder;
16+
import static net.jbock.common.Constants.LIST_OF_STRING;
1417
import static net.jbock.common.Constants.STRING;
1518

1619
final class ParseOrExitMethod extends HasCommandRepresentation {
@@ -33,26 +36,44 @@ final class ParseOrExitMethod extends HasCommandRepresentation {
3336

3437
MethodSpec define() {
3538

36-
ParameterSpec args = builder(ArrayTypeName.of(STRING), "args").build();
39+
ParameterSpec args = parseOrExitMethodAcceptsList() ?
40+
builder(LIST_OF_STRING, "args").build() :
41+
builder(ArrayTypeName.of(STRING), "args").build();
3742
ParameterSpec notSuccess = builder(generatedTypes.parseResultType(), "failure").build();
3843
ParameterSpec err = builder(AtFileError.class, "err").build();
3944

4045
CodeBlock.Builder code = CodeBlock.builder();
41-
code.beginControlFlow("if ($1N.length > 0 && $2S.equals($1N[0]))", args, "--help")
42-
.add("$T.builder().build()\n", StandardErrorHandler.class).indent()
46+
if (parseOrExitMethodAcceptsList()) {
47+
code.beginControlFlow("if (!$1N.isEmpty() && $2S.equals($1N.get(0)))", args, "--help");
48+
} else {
49+
code.beginControlFlow("if ($1N.length > 0 && $2S.equals($1N[0]))", args, "--help");
50+
}
51+
code.add("$T.builder().build()\n", StandardErrorHandler.class).indent()
4352
.add(".printUsageDocumentation($N());\n", createModelMethod.get()).unindent()
4453
.addStatement("$T.exit(0)", System.class)
4554
.endControlFlow();
4655

47-
code.add("return $T.from($N).expand()\n", ParseRequest.class, args).indent()
48-
.add(".mapLeft($1N -> $1N.addModel($2N()))\n", err, createModelMethod.get())
49-
.add(".flatMap(this::$N)\n", parseMethod.get())
50-
.add(".orElseThrow($N -> {\n", notSuccess).indent()
51-
.addStatement("$T.builder().build().printErrorMessage($N)",
52-
StandardErrorHandler.class, notSuccess)
53-
.addStatement("$T.exit(1)", System.class)
54-
.addStatement("return new $T()", RuntimeException.class).unindent()
55-
.addStatement("})").unindent();
56+
if (enableAtFileExpansion()) {
57+
code.add("return $T.from($N).expand()\n", ParseRequest.class, args).indent()
58+
.add(".mapLeft($1N -> $1N.addModel($2N()))\n", err, createModelMethod.get())
59+
.add(".flatMap(this::$N)\n", parseMethod.get())
60+
.add(".orElseThrow($N -> {\n", notSuccess).indent()
61+
.addStatement("$T.builder().build().printErrorMessage($N)",
62+
StandardErrorHandler.class, notSuccess)
63+
.addStatement("$T.exit(1)", System.class)
64+
.addStatement("return new $T()", RuntimeException.class).unindent()
65+
.addStatement("})").unindent();
66+
} else {
67+
CodeBlock pArgs = parseOrExitMethodAcceptsList() ?
68+
CodeBlock.of("$N", args) :
69+
CodeBlock.of("$T.of($N)", List.class, args);
70+
code.add("return parse($L).orElseThrow($N -> {\n", pArgs, notSuccess).indent()
71+
.addStatement("$T.builder().build().printErrorMessage($N)",
72+
StandardErrorHandler.class, notSuccess)
73+
.addStatement("$T.exit(1)", System.class)
74+
.addStatement("return new $T()", RuntimeException.class).unindent()
75+
.addStatement("})");
76+
}
5677
return methodBuilder("parseOrExit").addParameter(args)
5778
.addModifiers(sourceElement().accessModifiers())
5879
.returns(generatedTypes.sourceElement().typeName())

compiler/src/test/java/net/jbock/processor/ParseOrExitFullTest.java

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ void testBasicGenerated() {
3838
"import net.jbock.parse.VarargsParameterParser;",
3939
"import net.jbock.util.ExConvert;",
4040
"import net.jbock.util.ExFailure;",
41-
"import net.jbock.util.ParseRequest;",
4241
"import net.jbock.util.ParsingFailed;",
4342
"",
4443
"@Generated(",
@@ -62,14 +61,11 @@ void testBasicGenerated() {
6261
" .printUsageDocumentation(createModel());",
6362
" System.exit(0);",
6463
" }",
65-
" return ParseRequest.from(args).expand()",
66-
" .mapLeft(err -> err.addModel(createModel()))",
67-
" .flatMap(this::parse)",
68-
" .orElseThrow(failure -> {",
69-
" StandardErrorHandler.builder().build().printErrorMessage(failure);",
70-
" System.exit(1);",
71-
" return new RuntimeException();",
72-
" });",
64+
" return parse(List.of(args)).orElseThrow(failure -> {",
65+
" StandardErrorHandler.builder().build().printErrorMessage(failure);",
66+
" System.exit(1);",
67+
" return new RuntimeException();",
68+
" });",
7369
" }",
7470
"",
7571
" CommandModel createModel() {",
@@ -130,7 +126,6 @@ void testPublicParser() {
130126
"import net.jbock.parse.VarargsParameterParser;",
131127
"import net.jbock.util.ExConvert;",
132128
"import net.jbock.util.ExFailure;",
133-
"import net.jbock.util.ParseRequest;",
134129
"import net.jbock.util.ParsingFailed;",
135130
"",
136131
"@Generated(",
@@ -154,14 +149,11 @@ void testPublicParser() {
154149
" .printUsageDocumentation(createModel());",
155150
" System.exit(0);",
156151
" }",
157-
" return ParseRequest.from(args).expand()",
158-
" .mapLeft(err -> err.addModel(createModel()))",
159-
" .flatMap(this::parse)",
160-
" .orElseThrow(failure -> {",
161-
" StandardErrorHandler.builder().build().printErrorMessage(failure);",
162-
" System.exit(1);",
163-
" return new RuntimeException();",
164-
" });",
152+
" return parse(List.of(args)).orElseThrow(failure -> {",
153+
" StandardErrorHandler.builder().build().printErrorMessage(failure);",
154+
" System.exit(1);",
155+
" return new RuntimeException();",
156+
" });",
165157
" }",
166158
"",
167159
" public CommandModel createModel() {",

examples/src/main/java/net/jbock/examples/GitCommand.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ interface GitCommand {
1414

1515
@Command(
1616
name = "git-add",
17-
description = "Add file contents to the index")
17+
description = "Add file contents to the index",
18+
parseOrExitMethodAcceptsList = true)
1819
interface AddCommand {
1920
@VarargsParameter
2021
List<String> pathspec();

jbock/src/main/java/net/jbock/Command.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,17 @@
5656
*/
5757
boolean skipGeneratingParseOrExitMethod() default false;
5858

59+
/**
60+
* If {@code true}, the generated {@code parseOrExit} method
61+
* will accept {@code List<String>} instead of {@code String[]}.
62+
*/
63+
boolean parseOrExitMethodAcceptsList() default false;
64+
65+
/**
66+
* Set to {@code true} to enable at-file expansion.
67+
*/
68+
boolean enableAtFileExpansion() default false;
69+
5970
/**
6071
* If {@code true}, the generated parser class will be
6172
* {@code public}. Otherwise, it will be package-private.

jbock/src/main/java/net/jbock/SuperCommand.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,17 @@
5252
*/
5353
boolean skipGeneratingParseOrExitMethod() default false;
5454

55+
/**
56+
* If {@code true}, the generated {@code parseOrExit} method
57+
* will accept {@code List<String>} instead of {@code String[]}.
58+
*/
59+
boolean parseOrExitMethodAcceptsList() default false;
60+
61+
/**
62+
* Set to {@code true} to enable at-file expansion.
63+
*/
64+
boolean enableAtFileExpansion() default false;
65+
5566
/**
5667
* @return {@code true} if public parser should be generated
5768
* @see Command#publicParser()

jbock/src/main/java/net/jbock/util/ParseRequest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@ public static ParseRequest from(String[] args) {
3232
return new ParseRequestSimple(List.of(args));
3333
}
3434

35+
public static ParseRequest from(List<String> args) {
36+
if (args.size() >= 1
37+
&& args.get(0).length() >= 2
38+
&& args.get(0).startsWith("@")) {
39+
String fileName = args.get(0).substring(1);
40+
List<String> rest = args.subList(1, args.size());
41+
return new ParseRequestExpand(Paths.get(fileName), rest);
42+
}
43+
return new ParseRequestSimple(args);
44+
}
45+
3546
/**
3647
* Returns a Right containing the result of {@code @-file} expansion.
3748
* If an error occurs during {@code @-file} reading, returns a Left containing
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package net.jbock.util;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import java.util.List;
6+
7+
import static org.junit.jupiter.api.Assertions.assertEquals;
8+
import static org.junit.jupiter.api.Assertions.assertTrue;
9+
10+
class ParseRequestTest {
11+
12+
@Test
13+
void testParseList() {
14+
ParseRequest parseRequest = ParseRequest.from(List.of("a"));
15+
assertTrue(parseRequest.expand().isRight());
16+
assertEquals(parseRequest.expand().getRight().orElseThrow(), List.of("a"));
17+
}
18+
19+
@Test
20+
void testParseArray() {
21+
ParseRequest parseRequest = ParseRequest.from(new String[]{"a"});
22+
assertTrue(parseRequest.expand().isRight());
23+
assertEquals(parseRequest.expand().getRight().orElseThrow(), List.of("a"));
24+
}
25+
}

0 commit comments

Comments
 (0)