I am currently trying to make an cli app with Spring Shell.
I want the user to able to fast pick one of 2-3 options. My current code works fine in eclipse but when I sta
I use TextIO for this to do something similar. More specifically, I use the read
method on [IntInputReader][2]
which is handy as according to its docs:
Reads a value of type T. It repeatedly prompts the users to enter the value, until they provide a valid input string.
As I've needed this functionality many times in my Spring Shell application (for users to select from different types of objects), I wrote a generic method which
Presents the user with a list of items of a given type {@code T} and prompts them to select one or more. Optionally, once selection is complete, the user is presented with a summary of their selection for their confirmation.
Unfortunately StackOverflow is playing havoc with my Javadoc, so I've created a Gist with the full documented method.
public List cliObjectSelector(List items, boolean allowMultiple,
boolean requireConfirmation, @Nullable String customPromptMessage,
Function f) throws OperationCancelledException {
if(items == null || items.isEmpty()) {
textIO.getTextTerminal().print("No items found. Cannot continue");
throw new OperationCancelledException("The provided list of items is empty");
}
String userPrompt = (customPromptMessage != null) ? customPromptMessage + ":\n" :
String.format("Please select one of the %d items from the list:\n", items.size());
List optionsList = items.stream()
.map(item -> {
return String.format("[%d] - %s", items.indexOf(item), f.apply(item));
}).collect(Collectors.toList());
List selectedItems = new ArrayList<>();
optionsList.add(0, userPrompt);
while(true) {
textIO.getTextTerminal().println(optionsList);
T selected = items.get(
textIO.newIntInputReader()
.withMinVal(0)
.withMaxVal(items.size() - 1)
.read("Option number"));
selectedItems.add(selected);
if(allowMultiple == false) {
break;
}
if( ! askYesNo("Select another item?")) {
break;
}
}
if(requireConfirmation == false) {
return selectedItems;
}
if(confirmSelection(selectedItems.stream()
.map(item -> f.apply(item))
.collect(Collectors.toList()))) {
return selectedItems;
} else {
throw new OperationCancelledException();
}
}
Sample usage:
@ShellMethod(
key = "select-something",
value = "Select something")
public void select() {
Instance selected = cliObjectSelector(instances, false, requireConfirmation,
"Please select one of the " + instances.size() + " instances from the list",
instance -> instance.getX().getName()).get(0);
}