Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 2 additions & 3 deletions src/main/java/com/github/sttk/cliargs/CliArgs.java
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,6 @@ public Result parse() {
* <p>
* This method basically allows only options declared in option
* configurations.
* An option configuration has fields: {@code storeKey}, {@code names},
* {@code hasArg}, {@code isArray}, {@code type}, {@code defaults},
* {@code desc}, {@code argInHelp}, and {@code converter}.
* When an option in command line arguments matches one of the {@code names}
* in an option configuration, the option is registered into {@code Cmd} with
* {@code storeKey}.
Expand All @@ -212,6 +209,8 @@ public Result parse() {
* converted with the {@code converter}.
* If {@code type} is specified but {@code converter} is not specified,
* a converter which converts a string to the specified type value is set.
* If {@code postparser} is specified, it processes option arguments or
* default values after parsing.
* <p>
* If options not declared in option configurations are given in command line
* arguments, this method basically throws a {@link ReasonedException} with
Expand Down
67 changes: 56 additions & 11 deletions src/main/java/com/github/sttk/cliargs/OptCfg.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ public class OptCfg {
*/
public final Converter<?> converter;

/**
* Is the function interface that is executed after parsing command line
* arguments.
*/
public final Postparser<?> postparser;

/**
* Is the constructor that takes the all field values as parameters.
* <p>
Expand All @@ -120,8 +126,10 @@ public class OptCfg {
* @param defaults The default value(s).
* @param desc The description of the option.
* @param argInHelp The display of the option argument.
* @param converter The converter to convert the option argument string to
* the specified type value.
* @param converter The {@link Converter} object to convert the option
* argument string to the specified type value.
* @param postparser The {@link Postparser} object that is executed after
* parsing command line arguments.
*/
public <T> OptCfg(
String storeKey,
Expand All @@ -132,7 +140,8 @@ public <T> OptCfg(
List<T> defaults,
String desc,
String argInHelp,
Converter<T> converter
Converter<T> converter,
Postparser<T> postparser
) {
var init = new Init<T>();
init.storeKey = storeKey;
Expand All @@ -144,6 +153,7 @@ public <T> OptCfg(
init.desc = desc;
init.argInHelp = argInHelp;
init.converter = converter;
init.postparser = postparser;

fillmissing(init);

Expand All @@ -156,6 +166,7 @@ public <T> OptCfg(
this.desc = init.desc;
this.argInHelp = init.argInHelp;
this.converter = init.converter;
this.postparser = init.postparser;
}

/**
Expand Down Expand Up @@ -194,6 +205,7 @@ public <T> OptCfg(NamedParam<T> ...params) {
this.desc = init.desc;
this.argInHelp = init.argInHelp;
this.converter = init.converter;
this.postparser = init.postparser;
}

@SuppressWarnings("unchecked")
Expand All @@ -217,21 +229,22 @@ private void fillmissing(Init<?> init) {
}

if (init.type != null && init.converter == null) {
if (init.type.equals(Integer.class)) {
var type = init.type;
if (type.equals(int.class) || type.equals(Integer.class)) {
init.converter = (Converter)new IntConverter();
} else if (init.type.equals(Double.class)) {
} else if (type.equals(double.class) || type.equals(Double.class)) {
init.converter = (Converter)new DoubleConverter();
} else if (init.type.equals(Long.class)) {
} else if (type.equals(long.class) || type.equals(Long.class)) {
init.converter = (Converter)new LongConverter();
} else if (init.type.equals(BigDecimal.class)) {
} else if (type.equals(BigDecimal.class)) {
init.converter = (Converter)new BigDecimalConverter();
} else if (init.type.equals(BigInteger.class)) {
} else if (type.equals(BigInteger.class)) {
init.converter = (Converter)new BigIntConverter();
} else if (init.type.equals(Float.class)) {
} else if (type.equals(float.class) || type.equals(Float.class)) {
init.converter = (Converter)new FloatConverter();
} else if (init.type.equals(Short.class)) {
} else if (type.equals(short.class) || type.equals(Short.class)) {
init.converter = (Converter)new ShortConverter();
} else if (init.type.equals(Byte.class)) {
} else if (type.equals(byte.class) || type.equals(Byte.class)) {
init.converter = (Converter)new ByteConverter();
}
}
Expand All @@ -247,6 +260,7 @@ private static class Init<T> {
String desc;
String argInHelp;
Converter<T> converter;
Postparser<T> postparser;
}

/**
Expand Down Expand Up @@ -412,5 +426,36 @@ static <T> NamedParam<T> argInHelp(String argInHelp) {
static <T> NamedParam<T> converter(Converter<T> converter) {
return init -> ((Init<T>)init).converter = converter;
}

/**
* Is the static method to set the {@code postparser} field like a named
* parameter.
*
* @param <T> The type of the option argument value.
*
* @param postparser The value of the {@code postparser} field.
* @return The {@link NamedParam} object for {@code postparser} field.
*/
static <T> NamedParam<T> postparser(Postparser<T> postparser) {
return init -> ((Init<T>)init).postparser = postparser;
}
}

/**
* Is the functional interface to process option arguments after parsing
* command line arguments.
*
* @param <T> The type of the option argument value.
*/
@SuppressWarnings("unchecked")
@FunctionalInterface
public interface Postparser<T> {
/**
* Processes the option arguments.
*
* @param optArgs The variadic parameters of the option arguments.
* @throws ReasonedException If an abnormality occurs during processing.
*/
void process(List<T> optArgs) throws ReasonedException;
}
}
21 changes: 19 additions & 2 deletions src/main/java/com/github/sttk/cliargs/ParseWith.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ static Result parse(OptCfg[] optCfgs, String cmdName, String ...cliArgs) {
CmdArgCollector collectArgs = str -> {
args.add(str);
};

OptArgCollector collectOpts = (name, arg) -> {
var i = cfgMap.get(name);
if (i == null) {
Expand Down Expand Up @@ -175,9 +176,10 @@ static Result parse(OptCfg[] optCfgs, String cmdName, String ...cliArgs) {
}

for (var cfg : optCfgs) {
@SuppressWarnings("unchecked")
var list = (List<Object>)opts.get(cfg.storeKey);

if (! isEmpty(cfg.defaults)) {
@SuppressWarnings("unchecked")
var list = (List<Object>)opts.get(cfg.storeKey);
if (list == null) {
list = new ArrayList<>();
opts.put(cfg.storeKey, list);
Expand All @@ -186,9 +188,24 @@ static Result parse(OptCfg[] optCfgs, String cmdName, String ...cliArgs) {
list.addAll(cfg.defaults);
}
}

if (cfg.postparser != null && list != null) {
try {
postprocess(cfg, list);
} catch (ReasonedException e) {
if (exc == null) {
exc = e;
}
}
}
}

var cmd = new Cmd(cmdName, args, opts);
return new Result(cmd, optCfgs, exc);
}

@SuppressWarnings({"unchecked", "rawtypes"})
static void postprocess(OptCfg c, List<Object> l) throws ReasonedException {
c.postparser.process((List)l);
}
}
Loading