Skip to content

Commit

Permalink
feat: added interactive search mode
Browse files Browse the repository at this point in the history
  • Loading branch information
quintesse committed Jul 12, 2024
1 parent ac37101 commit 89f175e
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 9 deletions.
2 changes: 2 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"eu.maveniverse.maven.mima.runtime:standalone-static": "2.4.15",
"eu.maveniverse.maven.mima:context": "2.4.15",
"info.picocli:picocli": "4.7.6",
"org.jline:jline-console-ui": "3.26.2",
"org.jline:jline-terminal-jni": "3.26.2",
"org.slf4j:slf4j-api": "2.0.13",
"org.slf4j:slf4j-log4j12": "2.0.13",
"org.slf4j:slf4j-simple": "2.0.13"
Expand Down
11 changes: 11 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
<version.mima>2.4.15</version.mima>
<version.picocli>4.7.6</version.picocli>
<version.gson>2.11.0</version.gson>
<version.jline>3.26.3-SNAPSHOT</version.jline>
<version.slf4j>2.0.13</version.slf4j>
<version.spotless>2.43.0</version.spotless>
<version.google-java-format>1.22.0</version.google-java-format>
Expand All @@ -61,6 +62,16 @@
<artifactId>gson</artifactId>
<version>${version.gson}</version>
</dependency>
<dependency>
<groupId>org.jline</groupId>
<artifactId>jline-console-ui</artifactId>
<version>${version.jline}</version>
</dependency>
<dependency>
<groupId>org.jline</groupId>
<artifactId>jline-terminal-jni</artifactId>
<version>${version.jline}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
Expand Down
145 changes: 136 additions & 9 deletions src/main/java/org/codejive/jpm/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//DEPS eu.maveniverse.maven.mima:context:2.4.15 eu.maveniverse.maven.mima.runtime:standalone-static:2.4.15
//DEPS info.picocli:picocli:4.7.6
//DEPS com.google.code.gson:gson:2.11.0
//DEPS org.jline:jline-console-ui:3.26.2 org.jline:jline-terminal-jni:3.26.2
//DEPS org.slf4j:slf4j-api:2.0.13 org.slf4j:slf4j-simple:2.0.13
//SOURCES Jpm.java json/AppInfo.java util/FileUtils.java util/ResolverUtils.java util/SearchUtils.java
//SOURCES util/SearchResult.java util/SyncStats.java util/Version.java
Expand All @@ -16,6 +17,13 @@
import java.util.stream.Collectors;
import org.codejive.jpm.util.SyncStats;
import org.codejive.jpm.util.Version;
import org.jline.consoleui.prompt.ConsolePrompt;
import org.jline.consoleui.prompt.ListResult;
import org.jline.consoleui.prompt.PromptResultItemIF;
import org.jline.consoleui.prompt.builder.ListPromptBuilder;
import org.jline.consoleui.prompt.builder.PromptBuilder;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Mixin;
Expand Down Expand Up @@ -74,6 +82,12 @@ static class Sync implements Callable<Integer> {
@Mixin QuietMixin quietMixin;
@Mixin CopyMixin copyMixin;

@Option(
names = {"-i", "--interactive"},
description = "Interactively search and select artifacts to install",
defaultValue = "false")
private boolean interactive;

@Option(
names = {"-m", "--max"},
description = "Maximum number of results to return",
Expand All @@ -82,22 +96,135 @@ static class Sync implements Callable<Integer> {

@Parameters(
paramLabel = "artifactPattern",
description = "Partial or full artifact name to search for.")
description = "Partial or full artifact name to search for.",
defaultValue = "")
private String artifactPattern;

@Override
public Integer call() throws Exception {
String[] artifactNames =
Jpm.builder()
.directory(copyMixin.directory)
.noLinks(copyMixin.noLinks)
.build()
.search(artifactPattern, Math.min(max, 200));
if (artifactNames.length > 0) {
Arrays.stream(artifactNames).forEach(System.out::println);
if (interactive || artifactPattern == null || artifactPattern.isEmpty()) {
try (Terminal terminal = TerminalBuilder.builder().build()) {
while (true) {
ConsolePrompt prompt = new ConsolePrompt(terminal);
if (artifactPattern == null || artifactPattern.isEmpty()) {
artifactPattern = askString(prompt, "Search for:");
}
String[] artifactNames = search(artifactPattern);
PromptBuilder promptBuilder = prompt.getPromptBuilder();
addSelectItem(promptBuilder, "Select artifact:", artifactNames);
addSelectArtifactAction(promptBuilder);
Map<String, PromptResultItemIF> result =
prompt.prompt(promptBuilder.build());
String selectedArtifact = getSelectedId(result, "item");
String artifactAction = getSelectedId(result, "action");
if ("install".equals(artifactAction)) {
SyncStats stats =
Jpm.builder()
.directory(copyMixin.directory)
.noLinks(copyMixin.noLinks)
.build()
.install(new String[] {selectedArtifact});
if (!quietMixin.quiet) {
printStats(stats);
}
} else if ("copy".equals(artifactAction)) {
SyncStats stats =
Jpm.builder()
.directory(copyMixin.directory)
.noLinks(copyMixin.noLinks)
.build()
.copy(new String[] {selectedArtifact}, false);
if (!quietMixin.quiet) {
printStats(stats);
}
} else if ("version".equals(artifactAction)) {
artifactPattern = selectedArtifact;
continue;
} else { // quit
break;
}
String finalAction = selectFinalAction(prompt);
if ("quit".equals(finalAction)) {
break;
}
artifactPattern = null;
}
}
} else {
String[] artifactNames = search(artifactPattern);
if (artifactNames.length > 0) {
Arrays.stream(artifactNames).forEach(System.out::println);
}
}
return 0;
}

String[] search(String artifactPattern) throws IOException {
return Jpm.builder()
.directory(copyMixin.directory)
.noLinks(copyMixin.noLinks)
.build()
.search(artifactPattern, Math.min(max, 200));
}

String askString(ConsolePrompt prompt, String message) throws IOException {
PromptBuilder promptBuilder = prompt.getPromptBuilder();
promptBuilder.createInputPrompt().name("input").message(message).addPrompt();
Map<String, PromptResultItemIF> result = prompt.prompt(promptBuilder.build());
return result.get("input").getResult();
}

void addSelectItem(PromptBuilder promptBuilder, String message, String[] items)
throws IOException {
ListPromptBuilder artifactsList =
promptBuilder.createListPrompt().name("item").message(message).pageSize(10);
for (String artifactName : items) {
artifactsList.newItem(artifactName).text(artifactName).add();
}
artifactsList.addPrompt();
}

void addSelectArtifactAction(PromptBuilder promptBuilder) throws IOException {
promptBuilder
.createListPrompt()
.name("action")
.message("What to do:")
.newItem("install")
.text("Install artifact")
.add()
.newItem("copy")
.text("Copy artifact")
.add()
.newItem("version")
.text("Select different version")
.add()
.newItem("quit")
.text("Quit")
.add()
.addPrompt();
}

String selectFinalAction(ConsolePrompt prompt) throws IOException {
PromptBuilder promptBuilder = prompt.getPromptBuilder();
promptBuilder
.createListPrompt()
.name("action")
.message("What to do:")
.newItem("again")
.text("Search again")
.add()
.newItem("quit")
.text("Quit")
.add()
.addPrompt();
Map<String, PromptResultItemIF> result = prompt.prompt(promptBuilder.build());
return getSelectedId(result, "action");
}

private static String getSelectedId(
Map<String, PromptResultItemIF> result, String itemName) {
return ((ListResult) result.get(itemName)).getSelectedId();
}
}

@Command(
Expand Down

0 comments on commit 89f175e

Please sign in to comment.