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:
@@ -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 != ' ') {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.&
|
||||
&
|
||||
|
||||
Reference in New Issue
Block a user