From eae760e473205d9cd6b3bc1f4e55012355034c00 Mon Sep 17 00:00:00 2001 From: czpilar Date: Fri, 26 Dec 2025 12:38:25 +0100 Subject: [PATCH 1/2] Fixed completion only for particular command option (#1246) Signed-off-by: czpilar --- .../shell/jline/CommandCompleter.java | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/spring-shell-jline/src/main/java/org/springframework/shell/jline/CommandCompleter.java b/spring-shell-jline/src/main/java/org/springframework/shell/jline/CommandCompleter.java index e2858f531..4aae72150 100644 --- a/spring-shell-jline/src/main/java/org/springframework/shell/jline/CommandCompleter.java +++ b/spring-shell-jline/src/main/java/org/springframework/shell/jline/CommandCompleter.java @@ -12,12 +12,15 @@ import org.springframework.shell.core.command.completion.CompletionProposal; import org.springframework.shell.core.command.completion.CompletionProvider; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** * A JLine {@link Completer} that completes command names from a {@link CommandRegistry}. * * @author Mahmoud Ben Hassine + * @author David Pilar * @since 4.0.0 */ public class CommandCompleter implements Completer { @@ -46,10 +49,11 @@ public void complete(LineReader reader, ParsedLine line, List candida candidates.add(new Candidate("-" + option.shortName())); } } + CommandOption commandOption = findOptionByWords(line.words(), options); // add custom completions from the command's completion provider CompletionProvider completionProvider = commandByName.getCompletionProvider(); - CompletionContext context = new CompletionContext(line.words(), line.wordIndex(), line.wordCursor(), null, - null); + CompletionContext context = new CompletionContext(line.words(), line.wordIndex(), line.wordCursor(), + commandByName, commandOption); List proposals = completionProvider.apply(context); for (CompletionProposal proposal : proposals) { candidates.add(new Candidate(proposal.value())); @@ -74,4 +78,18 @@ public void complete(LineReader reader, ParsedLine line, List candida return this.commandRegistry.getCommandByName(commandName.toString().trim()); } + @Nullable private CommandOption findOptionByWords(List words, List options) { + List reversed = new ArrayList<>(words); + Collections.reverse(reversed); + String optionName = reversed.stream().filter(word -> !word.trim().isEmpty()).findFirst().orElse(""); + + for (CommandOption option : options) { + if (option.longName() != null && optionName.equals("--" + option.longName()) + || option.shortName() != ' ' && optionName.equals("-" + option.shortName())) { + return option; + } + } + return null; + } + } From 29f89858dc4d23208d3e407f14eac859d9f2641a Mon Sep 17 00:00:00 2001 From: czpilar Date: Fri, 26 Dec 2025 13:18:55 +0100 Subject: [PATCH 2/2] Fixed completion only for particular command option (#1246) Signed-off-by: czpilar --- .../shell/jline/CommandCompleter.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/spring-shell-jline/src/main/java/org/springframework/shell/jline/CommandCompleter.java b/spring-shell-jline/src/main/java/org/springframework/shell/jline/CommandCompleter.java index 4aae72150..705e26813 100644 --- a/spring-shell-jline/src/main/java/org/springframework/shell/jline/CommandCompleter.java +++ b/spring-shell-jline/src/main/java/org/springframework/shell/jline/CommandCompleter.java @@ -39,17 +39,20 @@ public CommandCompleter(CommandRegistry commandRegistry) { public void complete(LineReader reader, ParsedLine line, List candidates) { Command commandByName = findCommandByWords(line.words()); if (commandByName != null) { - // add option completions for the command List options = commandByName.getOptions(); - for (CommandOption option : options) { - if (option.longName() != null && !line.line().contains("--" + option.longName())) { - candidates.add(new Candidate("--" + option.longName())); - } - if (option.shortName() != ' ' && !line.line().contains("-" + option.shortName())) { - candidates.add(new Candidate("-" + option.shortName())); + CommandOption commandOption = findOptionByWords(line.words(), options); + if (commandOption == null) { + // add option completions for the command + for (CommandOption option : options) { + boolean present = isOptionPresent(line, option); + if (option.longName() != null && !present) { + candidates.add(new Candidate("--" + option.longName())); + } + if (option.shortName() != ' ' && !present) { + candidates.add(new Candidate("-" + option.shortName())); + } } } - CommandOption commandOption = findOptionByWords(line.words(), options); // add custom completions from the command's completion provider CompletionProvider completionProvider = commandByName.getCompletionProvider(); CompletionContext context = new CompletionContext(line.words(), line.wordIndex(), line.wordCursor(), @@ -67,6 +70,11 @@ public void complete(LineReader reader, ParsedLine line, List candida } } + private boolean isOptionPresent(ParsedLine line, CommandOption option) { + return option.longName() != null && line.line().contains(" --" + option.longName() + " ") + || option.shortName() != ' ' && line.line().contains(" -" + option.shortName() + " "); + } + @Nullable private Command findCommandByWords(List words) { StringBuilder commandName = new StringBuilder(); for (String word : words) {