|
12 | 12 |
|
13 | 13 | import java.util.*; |
14 | 14 | import java.util.stream.Collectors; |
| 15 | +import java.util.stream.Stream; |
15 | 16 |
|
16 | 17 | /** |
17 | 18 | * CommandInvoker is responsible for invoking and suggesting commands. |
@@ -107,21 +108,53 @@ public boolean invoke(S source, String base, String[] rawArgs) { |
107 | 108 | */ |
108 | 109 | public List<String> suggest(S source, String base, String[] args) { |
109 | 110 | Optional<MatchResult<T, S>> found = manager.getCommands().findNode(base, args); |
110 | | - if (!found.isPresent()) return Collections.emptyList(); |
111 | | - MatchResult<T, S> result = found.get(); |
112 | | - CommandTree.CommandNode<T, S> node = result.node; |
113 | | - String[] rawArgs = result.args; |
114 | | - String label = node.getFullLabel() != null ? node.getFullLabel() : base; |
115 | | - Map<Integer, TabCompleter<S>> map = manager.getCompleters().get(label); |
116 | | - if (map != null && map.containsKey(args.length)) { |
117 | | - return map.get(args.length) |
118 | | - .onCompletion(source, Arrays.asList(rawArgs)) |
119 | | - .stream() |
120 | | - .filter(opt -> allowedSuggestion(source, label, opt)) |
121 | | - .filter(opt -> matchesPrefix(opt, args[args.length - 1])) |
122 | | - .collect(Collectors.toList()); |
| 111 | + String lastArg = args.length > 0 ? args[args.length - 1] : ""; |
| 112 | + if (found.isPresent()) { |
| 113 | + MatchResult<T, S> result = found.get(); |
| 114 | + CommandTree.CommandNode<T, S> node = result.node; |
| 115 | + String[] rawArgs = result.args; |
| 116 | + String label = Optional.ofNullable(node.getFullLabel()).orElse(base); |
| 117 | + Map<Integer, TabCompleter<S>> map = manager.getCompleters().get(label); |
| 118 | + if (map != null) { |
| 119 | + TabCompleter<S> completer = map.get(args.length); |
| 120 | + if (completer != null) { |
| 121 | + return completer.onCompletion(source, Arrays.asList(rawArgs)).stream() |
| 122 | + .filter(opt -> allowedSuggestion(source, label, opt)) |
| 123 | + .filter(opt -> matchesPrefix(opt, lastArg)) |
| 124 | + .collect(Collectors.toList()); |
| 125 | + } |
| 126 | + } |
| 127 | + } |
| 128 | + |
| 129 | + CommandTree.CommandNode<T, S> current = manager.getCommands().getRoot().getChildren().get(base.toLowerCase()); |
| 130 | + if (current == null) return Collections.emptyList(); |
| 131 | + |
| 132 | + current = traverseNode(current, args); |
| 133 | + String parentLabel = current.getFullLabel(); |
| 134 | + |
| 135 | + Stream<String> children = current.getChildren().keySet().stream(); |
| 136 | + if (args.length > 0 && current.getChildren().containsKey(lastArg.toLowerCase())) { |
| 137 | + children = children.filter(opt -> matchesPrefix(opt, lastArg)); |
| 138 | + } |
| 139 | + |
| 140 | + return children |
| 141 | + .filter(opt -> allowedSuggestion(source, parentLabel, opt)) |
| 142 | + .collect(Collectors.toList()); |
| 143 | + } |
| 144 | + |
| 145 | + private CommandTree.CommandNode<T, S> traverseNode(CommandTree.CommandNode<T, S> node, String[] args) { |
| 146 | + int index = 0; |
| 147 | + while (index < args.length - 1) { |
| 148 | + String arg = args[index].toLowerCase(); |
| 149 | + CommandTree.CommandNode<T, S> child = node.getChildren().get(arg); |
| 150 | + if (child != null) { |
| 151 | + node = child; |
| 152 | + index++; |
| 153 | + } else { |
| 154 | + break; |
| 155 | + } |
123 | 156 | } |
124 | | - return Collections.emptyList(); |
| 157 | + return node; |
125 | 158 | } |
126 | 159 |
|
127 | 160 | private boolean matchesPrefix(String candidate, String current) { |
|
0 commit comments