Skip to content

Commit d968fda

Browse files
feat: Add MiniCLI.setPositionalArgCount
1 parent dc6cb68 commit d968fda

5 files changed

Lines changed: 94 additions & 3 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package net.marcellperger.mathexpr;
2+
3+
import org.jetbrains.annotations.Nullable;
4+
5+
import java.util.Objects;
6+
7+
public class IntRange {
8+
int lo, hi;
9+
10+
protected IntRange(int min, int max, int ignoredMarker) {
11+
if(min > max) throw new IllegalArgumentException("min must be grater than max");
12+
lo = min;
13+
hi = max;
14+
}
15+
public IntRange(@Nullable Integer min, @Nullable Integer max) {
16+
this(Objects.requireNonNullElse(min, Integer.MIN_VALUE),
17+
Objects.requireNonNullElse(max, Integer.MAX_VALUE), /*marker*/0);
18+
}
19+
public IntRange() {
20+
this(null, null);
21+
}
22+
23+
public int getMin() {
24+
return lo;
25+
}
26+
public int getMax() {
27+
return hi;
28+
}
29+
30+
public boolean includes(int v) {
31+
return lo <= v && v <= hi;
32+
}
33+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package net.marcellperger.mathexpr;
2+
3+
import org.jetbrains.annotations.Contract;
4+
import org.jetbrains.annotations.NotNull;
5+
import org.jetbrains.annotations.Nullable;
6+
7+
import java.util.Objects;
8+
9+
public class UIntRange extends IntRange {
10+
protected UIntRange(int min, int max, int ignoredMarker) {
11+
super(workaround(() -> {
12+
if(min < 0 || max < 0) throw new IllegalArgumentException();
13+
}, min), max, ignoredMarker);
14+
}
15+
16+
public UIntRange(@Nullable Integer min, @Nullable Integer max) {
17+
this(Objects.requireNonNullElse(min, 0),
18+
Objects.requireNonNullElse(max, Integer.MAX_VALUE), /*marker*/0);
19+
}
20+
21+
public UIntRange() {
22+
this(null, null);
23+
}
24+
25+
/**
26+
* Workaround to allow us to run code before super() call.
27+
* This is required because java insists that super() be this first statement!
28+
* So not even static stuff can be ran!
29+
*/
30+
@Contract("_, _ -> param2")
31+
private static <T> T workaround(@NotNull Runnable r, T returnValue) {
32+
r.run();
33+
return returnValue;
34+
}
35+
36+
}

src/main/java/net/marcellperger/mathexpr/cli/minicli/BooleanCLIOption.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import java.util.List;
66

7-
public class BooleanCLIOption extends CLIOption<Boolean> {
7+
class BooleanCLIOption extends CLIOption<Boolean> {
88
public BooleanCLIOption(List<String> optionNames) {
99
super(Boolean.class, optionNames);
1010
}

src/main/java/net/marcellperger/mathexpr/cli/minicli/MiniCLI.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package net.marcellperger.mathexpr.cli.minicli;
22

3+
import net.marcellperger.mathexpr.IntRange;
4+
import net.marcellperger.mathexpr.UIntRange;
35
import net.marcellperger.mathexpr.util.Pair;
46
import net.marcellperger.mathexpr.util.Util;
57
import org.jetbrains.annotations.Contract;
@@ -10,16 +12,29 @@
1012
import java.util.HashMap;
1113
import java.util.List;
1214
import java.util.Map;
15+
import java.util.Objects;
1316
import java.util.function.Function;
1417

1518
public class MiniCLI {
1619
Map<String, CLIOption<?>> options = new HashMap<>();
20+
UIntRange nPositionalArgs = new UIntRange();
1721
List<String> positionalArgs = new ArrayList<>();
1822

1923
public MiniCLI() {
2024

2125
}
2226

27+
public void setPositionalArgCount(UIntRange range) {
28+
nPositionalArgs = range;
29+
}
30+
public void setPositionalArgCount(@Nullable Integer min, @Nullable Integer max) {
31+
setPositionalArgCount(new UIntRange(min, max));
32+
}
33+
public void setPositionalArgCount(@Nullable /*null=any*/ Integer value) {
34+
if(value == null) setPositionalArgCount(new UIntRange());
35+
else setPositionalArgCount(value, value);
36+
}
37+
2338
@Contract("_ -> new")
2439
public CLIOption<String> addStringOption(String @NotNull ... names) {
2540
return addOptionFromFactory(names, StringCLIOption::new);
@@ -89,7 +104,7 @@ public void pumpSingleArg(String arg) {
89104
switch (argT) {
90105
case NORMAL -> {
91106
if (prev != null) flushPrevWithValue(arg);
92-
else positionalArgs.add(arg);
107+
else addPositionalArg(arg);
93108
}
94109
case SINGLE -> {
95110
if(prev != null) flushPrev();
@@ -132,6 +147,13 @@ private void flushPrevWithValue(String value) {
132147
prev.setValueFromString(value);
133148
prev = null;
134149
}
150+
151+
private void addPositionalArg(String arg) {
152+
int newSize = positionalArgs.size() + 1;
153+
int maxArgc = nPositionalArgs.getMax();
154+
if(newSize > maxArgc)
155+
throw new CLIParseException("Too many positional args (expected max %d, got %d)".formatted(maxArgc, newSize));
156+
}
135157
}
136158
private enum ArgType {
137159
NORMAL, SINGLE, DOUBLE;

src/main/java/net/marcellperger/mathexpr/cli/minicli/StringCLIOption.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import java.util.List;
66

7-
public class StringCLIOption extends CLIOption<String> {
7+
class StringCLIOption extends CLIOption<String> {
88
public StringCLIOption(List<String> keys) {
99
super(String.class, keys);
1010
}

0 commit comments

Comments
 (0)