Add dynamic command availability

Introduce availability concept on MethodTarget (with reason if not available)
Add bridge to @CliAvailabilityIndicator to Legacy registrar

Fixes #138

Add help for unavailable commands

Add standard API for availability
This commit is contained in:
Eric Bottard
2017-08-22 18:22:51 +02:00
parent 6c231a072c
commit 1eea04ad2f
16 changed files with 658 additions and 45 deletions

View File

@@ -31,15 +31,11 @@ import org.jline.utils.AttributedStringBuilder;
import org.jline.utils.AttributedStyle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.shell.MethodTarget;
import org.springframework.shell.ParameterDescription;
import org.springframework.shell.ParameterResolver;
import org.springframework.shell.CommandRegistry;
import org.springframework.shell.*;
import org.springframework.shell.standard.CommandValueProvider;
import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;
import org.springframework.shell.standard.ShellOption;
import org.springframework.shell.Utils;
/**
* A command to display help about all available commands.
@@ -204,6 +200,14 @@ public class Help {
}
}
Availability availability = methodTarget.getAvailability();
if (!availability.isAvailable()) {
result.append("CURRENTLY UNAVAILABLE", AttributedStyle.BOLD).append("\n");
result.append('\t').append("This command is currently not available because ")
.append(availability.getReason())
.append(".\n");
}
result.append("\n");
return result;
}
@@ -223,12 +227,18 @@ public class Help {
groupedByMethodTarget.entrySet().stream()
.sorted(sortByFirstElement())
.forEach(e -> result.append("\t")
.forEach(e -> result.append(isAvailable(e) ? " " : " * ")
.append(e.getValue().stream().collect(Collectors.joining(", ")), AttributedStyle.BOLD)
.append(": ")
.append(e.getKey())
.append('\n')
);
groupedByMethodTarget.entrySet().stream()
.filter(e -> !isAvailable(e))
.findAny()
.ifPresent(e -> result.append("\nCommands marked with (*) are currently unavailable.\nType `help <command>` to learn more.\n"));
return result.append("\n");
}
@@ -236,6 +246,11 @@ public class Help {
return Comparator.comparing(e -> e.getValue().iterator().next());
}
private boolean isAvailable(Map.Entry<String, Set<String>> entry) {
String commandName = entry.getValue().iterator().next();
return commandRegistry.listCommands().get(commandName).getAvailability().isAvailable();
}
private void appendUnderlinedFormal(AttributedStringBuilder result, ParameterDescription description) {
for (char c : description.formal().toCharArray()) {
if (c != ' ') {

View File

@@ -96,18 +96,15 @@ public class HelpTest {
public CommandRegistry shell() {
return () -> {
Map<String, MethodTarget> result = new HashMap<>();
Method method = ReflectionUtils.findMethod(Commands.class, "firstCommand", boolean.class, boolean.class, int.class, float[].class);
MethodTarget methodTarget = new MethodTarget(method, commands(), "A rather extensive description of some command.");
MethodTarget methodTarget = MethodTarget.of("firstCommand", commands(), "A rather extensive description of some command.");
result.put("first-command", methodTarget);
result.put("1st-command", methodTarget);
method = ReflectionUtils.findMethod(Commands.class, "secondCommand");
methodTarget = new MethodTarget(method, commands(), "The second command. This one is known under several aliases as well.");
methodTarget = MethodTarget.of("secondCommand", commands(), "The second command. This one is known under several aliases as well.");
result.put("second-command", methodTarget);
result.put("yet-another-command", methodTarget);
method = ReflectionUtils.findMethod(Commands.class, "thirdCommand");
methodTarget = new MethodTarget(method, commands(), "The last command.");
methodTarget = MethodTarget.of("thirdCommand", commands(), "The last command.");
result.put("third-command", methodTarget);
return result;

View File

@@ -1,6 +1,6 @@
AVAILABLE COMMANDS&
&
1st-command, first-command: A rather extensive description of some command.&
second-command, yet-another-command: The second command. This one is known under several aliases as well.&
third-command: The last command.&
1st-command, first-command: A rather extensive description of some command.&
second-command, yet-another-command: The second command. This one is known under several aliases as well.&
third-command: The last command.&
&