org.aya.repl.CommandArg Maven / Gradle / Ivy
// Copyright (c) 2020-2023 Tesla (Yinsen) Zhang.
// Use of this source code is governed by the MIT license that can be found in the LICENSE.md file.
package org.aya.repl;
import kala.collection.Seq;
import kala.collection.mutable.MutableList;
import kala.control.Either;
import kala.control.Try;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jline.reader.Completer;
import org.jline.reader.impl.completer.AggregateCompleter;
import java.util.function.Function;
public interface CommandArg {
@NotNull Class> type();
@NotNull Object parse(@NotNull String input) throws IllegalArgumentException;
@Nullable Completer completer();
/**
* Affects the repl parser behavior of the argument.
*
* @return true to parse the argument with the default parser,
* otherwise to parse with the antlr-based parser.
* @see ReplParser
*/
boolean shellLike();
record CommandArgImpl(
@Override @NotNull Class extends R> type,
@Override @Nullable Completer completer,
@Override boolean shellLike,
@NotNull Function f
) implements CommandArg {
@Override public @NotNull R parse(@NotNull String input) throws IllegalArgumentException {
return f.apply(input);
}
}
private static CommandArgImpl from(@NotNull Class extends R> type, boolean shellLike, @Nullable Completer completer, @NotNull Function f) {
return new CommandArgImpl<>(type, completer, shellLike, f);
}
static CommandArgImpl from(@NotNull Class extends R> type, @Nullable Completer completer, @NotNull Function f) {
return from(type, false, completer, f);
}
static CommandArgImpl shellLike(@NotNull Class extends R> type, @Nullable Completer completer, @NotNull Function f) {
return from(type, true, completer, f);
}
static > CommandArgImpl fromEnum(@NotNull Class enumClass) {
return from(enumClass, false, new ReplCompleters.EnumCompleter<>(enumClass),
input -> chooseEnum(enumClass, input));
}
static > CommandArgImpl fromEither(
@NotNull Class type,
@NotNull CommandArgImpl leftArg,
@NotNull CommandArgImpl rightArg,
@NotNull Function createLeft,
@NotNull Function createRight
) {
var completer = MutableList.create();
if (leftArg.completer() != null) completer.append(leftArg.completer());
if (rightArg.completer() != null) completer.append(rightArg.completer());
return from(type, leftArg.shellLike || rightArg.shellLike,
new AggregateCompleter(completer.asJava()),
input -> {
if (input.trim().isEmpty()) throw new IllegalArgumentException("Empty input");
try {
return createLeft.apply(leftArg.parse(input));
} catch (IllegalArgumentException ignored) {
return createRight.apply(rightArg.parse(input));
}
});
}
private static > @NotNull T chooseEnum(@NotNull Class enumClass, @NotNull String name) {
var trimName = name.trim();
if (trimName.isEmpty()) throw new IllegalArgumentException("Empty enum value");
try {
return Enum.valueOf(enumClass, trimName);
} catch (IllegalArgumentException ignored) {
var one = Seq.of(enumClass.getEnumConstants())
.findFirst(n -> n.name().toLowerCase().startsWith(trimName.toLowerCase()));
if (one.isEmpty()) throw new IllegalArgumentException("No such enum constant: " + name);
return one.get();
}
}
interface ArgEither {
@NotNull Either value();
}
@NotNull CommandArg STRING = from(String.class, null, Function.identity());
@NotNull CommandArg STRICT_INT = from(Integer.class, null, input ->
Try.of(() -> Integer.parseInt(input)).getOrThrow(IllegalArgumentException::new));
@NotNull CommandArg STRICT_BOOLEAN = from(Boolean.class, ReplCompleters.BOOL, s -> {
if (s.equalsIgnoreCase("true")) return true;
if (s.equalsIgnoreCase("false")) return false;
if (s.equalsIgnoreCase("yes")) return true;
if (s.equalsIgnoreCase("no")) return false;
throw new IllegalArgumentException("not an boolean value");
});
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy