Skip to content

Commit

Permalink
feat: support eager execution
Browse files Browse the repository at this point in the history
  • Loading branch information
entrypointkr committed May 24, 2022
1 parent 35d310e commit 451d04a
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 49 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {

allprojects {
group 'io.typecraft'
version '0.1.1'
version '0.2.0'
def moduleName = name.substring(name.indexOf('-') + 1)
ext.registerPublish = {
publishing {
Expand Down
70 changes: 26 additions & 44 deletions core/src/main/java/io/typecraft/command/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import io.typecraft.command.i18n.MessageId;
import io.vavr.*;
import io.vavr.control.Either;
import io.vavr.control.Option;
import lombok.Data;
import lombok.With;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -42,36 +43,15 @@ public Optional<Command<A>> getFallback() {
}
}

@Data
@With
class Present<A> implements Command<A> {
private final A value;
private final MessageId descriptionId;

private Present(A value, MessageId descriptionId) {
this.value = value;
this.descriptionId = descriptionId;
}

public Present<A> withDescription(String description) {
return withDescriptionId(MessageId.of("").withMessage(description));
}

@Override
public <B> Present<B> map(Function<? super A, ? extends B> f) {
return new Present<>(f.apply(value), getDescriptionId());
}
}

@Data
@With
class Parser<A> implements Command<A> {
private final Function<List<String>, Tuple2<Optional<A>, List<String>>> parser;
private final Function<List<String>, Tuple2<Option<A>, List<String>>> parser;
private final List<Supplier<List<String>>> tabCompleters;
private final List<MessageId> names;
private final MessageId descriptionId;

private Parser(Function<List<String>, Tuple2<Optional<A>, List<String>>> parser, List<Supplier<List<String>>> tabCompleters, List<MessageId> names, MessageId descriptionId) {
private Parser(Function<List<String>, Tuple2<Option<A>, List<String>>> parser, List<Supplier<List<String>>> tabCompleters, List<MessageId> names, MessageId descriptionId) {
this.parser = parser;
this.tabCompleters = tabCompleters;
this.names = names;
Expand Down Expand Up @@ -103,13 +83,22 @@ static <A> Mapping<A> mapping(Tuple2<String, Command<? extends A>>... entries) {
return new Mapping<>(map, null);
}

static <A> Present<A> present(A value) {
return new Present<>(value, MessageId.of(""));
static <A> Parser<A> present(A value) {
return argument(() -> value);
}

static <T> Parser<T> argument(Supplier<T> f) {
return new Parser<>(
args -> new Tuple2<>(Option.some(f.get()), args),
Collections.emptyList(),
Collections.singletonList(MessageId.of("")),
MessageId.ofEmpty()
);
}

static <T, A> Parser<T> argument(Function<? super A, ? extends T> f, Argument<A> argument) {
return new Parser<>(
args -> argument.getParser().apply(args).map1(aO -> aO.map(f)),
args -> argument.getParser().apply(args).map1(aO -> Option.ofOptional(aO).map(f)),
argument.getTabCompleters(),
argument.getIds(),
MessageId.of("")
Expand Down Expand Up @@ -167,15 +156,18 @@ static <A> Either<CommandFailure<A>, CommandSuccess<A>> parseWithIndex(int index
? parseWithIndex(index + 1, args, subCommand)
: Either.left(new CommandFailure.UnknownSubCommand<>(args, index, mapCommand));
}
} else if (command instanceof Present) {
Present<A> present = (Present<A>) command;
return Either.right(new CommandSuccess<>(args, index, present.getValue()));
} else if (command instanceof Parser) {
Parser<A> parser = (Parser<A>) command;
List<String> list = new ArrayList<>(Arrays.asList(Arrays.copyOfRange(args, index, args.length)));
A a = parser.getParser().apply(list)._1.orElse(null);
return a != null
? Either.right(new CommandSuccess<>(new String[0], args.length, a))
List<String> list = index <= args.length
? new ArrayList<>(Arrays.asList(Arrays.copyOfRange(args, index, args.length)))
: Collections.emptyList();
Tuple2<Option<A>, List<String>> result = parser.getParser().apply(list);
Option<A> aO = result._1;
List<String> remainList = result._2;
A a = aO.getOrNull();
int currentIndex = index + list.size() - remainList.size();
return aO.isDefined()
? Either.right(new CommandSuccess<>(args, currentIndex, a))
: Either.left(new CommandFailure.ParsingFailure<>(parser.getNames(), parser));
}
throw new UnsupportedOperationException();
Expand All @@ -202,10 +194,6 @@ static <A> CommandTabResult<A> tabCompleteWithIndex(int index, String[] args, Co
? tabCompleteWithIndex(index + 1, args, subCommand)
: CommandTabResult.suggestion(Collections.emptyList());
}
} else if (command instanceof Present) {
Present<A> present = (Present<A>) command;
String[] newArgs = Arrays.copyOfRange(args, index, args.length);
return CommandTabResult.present(newArgs, present.getValue());
} else if (command instanceof Parser) {
Parser<A> parser = (Parser<A>) command;
int pos = args.length - index - 1;
Expand Down Expand Up @@ -247,13 +235,7 @@ static <A> List<Map.Entry<List<String>, Command<A>>> getEntries(Command<A> cmd)
}

static <A> CommandSpec getSpec(Command<A> cmd) {
if (cmd instanceof Command.Present) {
Present<A> present = (Present<A>) cmd;
return CommandSpec.of(
Collections.emptyList(),
present.getDescriptionId()
);
} else if (cmd instanceof Command.Parser) {
if (cmd instanceof Command.Parser) {
Parser<A> parser = (Parser<A>) cmd;
return CommandSpec.of(
parser.getNames(),
Expand Down
9 changes: 8 additions & 1 deletion core/src/main/java/io/typecraft/command/i18n/MessageId.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import lombok.Data;
import lombok.With;

import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

@With
@Data
Expand All @@ -30,6 +33,10 @@ public static MessageId of(String id) {
return new MessageId(id, "");
}

public static MessageId ofEmpty() {
return new MessageId("", "");
}

public String getMessage(Map<String, String> messages) {
return messages.getOrDefault(getId(), getMessage().isEmpty() ? getId() : getMessage());
}
Expand Down
7 changes: 4 additions & 3 deletions core/src/test/java/io/typecraft/command/CommandTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ public class CommandTest {
// strArg: Argument<String>
pair("add", Command.argument(AddItem::new, intArg, strArg)),
pair("remove", Command.argument(RemoveItem::new, intArg)),
pair("page", Command.argument(PageItem::new, intTabArg))
pair("page", Command.argument(PageItem::new, intTabArg)),
pair("lazy", Command.argument(() -> null))
);
private static final Command.Mapping<MyCommand> itemCommandWithFallback =
itemCommand.withFallback(Command.present(new FallbackItem()));
Expand Down Expand Up @@ -145,7 +146,7 @@ public void argument() {
String name = "someName";
String[] args = new String[]{"item", "add", String.valueOf(index), name};
assertEquals(
Either.right(new CommandSuccess<>(new String[0], args.length, new AddItem(index, name))),
Either.right(new CommandSuccess<>(args, args.length, new AddItem(index, name))),
Command.parse(args, rootCommand)
);
}
Expand Down Expand Up @@ -210,7 +211,7 @@ public void tabUnit() {
public void tabSub() {
String[] args = new String[]{"item", ""};
assertEquals(
CommandTabResult.suggestion(Arrays.asList("open", "add", "remove", "page")),
CommandTabResult.suggestion(Arrays.asList("open", "add", "remove", "page", "lazy")),
Command.tabComplete(args, rootCommand)
);
}
Expand Down

0 comments on commit 451d04a

Please sign in to comment.