Skip to content

Commit cbd9969

Browse files
#2192-support-for-auto-completion-synonyms (#2204)
Co-authored-by: Jörg Hohwiller <hohwille@users.noreply.github.com>
1 parent 8708ee9 commit cbd9969

11 files changed

Lines changed: 246 additions & 59 deletions

File tree

CHANGELOG.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Release with new features and bugfixes:
1919
* https://github.com/devonfw/IDEasy/issues/1784[#1784]: GUI now supports displaying progress bars
2020
* https://github.com/devonfw/IDEasy/issues/1917[#1917]: Allow the creation of a desktop shortcut for the GUI
2121
* https://github.com/devonfw/IDEasy/issues/2134[#2134]: Add auto-completion for icd command
22+
* https://github.com/devonfw/IDEasy/issues/2192[#2192]: Added support for auto-completion synonyms
2223
* https://github.com/devonfw/IDEasy/issues/1953[#1953]: Implement base functionality of cleanup commandlet
2324
* https://github.com/devonfw/IDEAsy/issues/2181[#2181]: Merged the VsCode and VsCodium plugin folder and added excluded-editions as an option for plugins
2425
* https://github.com/devonfw/IDEasy/issues/2145[#2145]: Improve documentation on symlink regarding ide ln

cli/src/main/java/com/devonfw/tools/ide/commandlet/CompleteCommandlet.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package com.devonfw.tools.ide.commandlet;
22

3+
import java.util.HashSet;
34
import java.util.List;
5+
import java.util.Set;
46

57
import com.devonfw.tools.ide.cli.CliArguments;
68
import com.devonfw.tools.ide.completion.CompletionCandidate;
9+
import com.devonfw.tools.ide.completion.CompletionCandidateCollector;
10+
import com.devonfw.tools.ide.completion.CompletionCandidateCollectorDefault;
711
import com.devonfw.tools.ide.context.AbstractIdeContext;
812
import com.devonfw.tools.ide.context.IdeContext;
913
import com.devonfw.tools.ide.property.StringProperty;
@@ -51,9 +55,14 @@ public boolean isProcessableOutput() {
5155

5256
@Override
5357
protected void doRun() {
54-
55-
CliArguments arguments = CliArguments.ofCompletion(this.args.asArray());
56-
List<CompletionCandidate> candidates = ((AbstractIdeContext) this.context).complete(arguments, true);
58+
String[] argsArray = this.args.asArray();
59+
CliArguments arguments = CliArguments.ofCompletion(argsArray);
60+
Set<String> alreadyProvided = new HashSet<>();
61+
for (int i = 0; i < argsArray.length - 1; i++) {
62+
alreadyProvided.add(argsArray[i]);
63+
}
64+
CompletionCandidateCollector collector = new CompletionCandidateCollectorDefault(this.context, alreadyProvided);
65+
List<CompletionCandidate> candidates = ((AbstractIdeContext) this.context).complete(arguments, collector, true);
5766
for (CompletionCandidate candidate : candidates) {
5867
System.out.print(candidate.text()); // checkstyle:ignore SystemOut - completion output must reach stdout even when logging is disabled
5968
System.out.print('\n'); // checkstyle:ignore SystemOut - raw newline (not println) avoids a CR char in bash completion on Windows

cli/src/main/java/com/devonfw/tools/ide/completion/AutoCompletionRegistry.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class AutoCompletionRegistry {
1515
/**
1616
* The registered completion candidates.
1717
*/
18-
private final List<String> candidates = new ArrayList<>();
18+
private final List<CompletionEntry> entries = new ArrayList<>();
1919

2020

2121
/**
@@ -24,7 +24,7 @@ public class AutoCompletionRegistry {
2424
* @param candidate the candidate to add.
2525
*/
2626
public void add(String candidate) {
27-
this.candidates.add(candidate);
27+
this.entries.add(new CompletionEntry(candidate));
2828
}
2929

3030
/**
@@ -34,8 +34,9 @@ public void add(String candidate) {
3434
* @param synonym to add a long with the candidate
3535
*/
3636
public void add(String candidate, String synonym) {
37-
add(candidate);
38-
add(synonym);
37+
CompletionEntry entry = new CompletionEntry(candidate);
38+
entry.addSynonym(synonym);
39+
this.entries.add(entry);
3940
}
4041

4142

@@ -50,10 +51,8 @@ public void add(String candidate, String synonym) {
5051
public void complete(String arg, CompletionCandidateCollector collector,
5152
Property<?> property, Commandlet commandlet) {
5253

53-
for (String candidate : this.candidates) {
54-
if (candidate.startsWith(arg)) {
55-
collector.add(candidate, "", property, commandlet);
56-
}
54+
for (CompletionEntry entry : this.entries) {
55+
entry.complete(arg, collector, property, commandlet);
5756
}
5857
}
5958

cli/src/main/java/com/devonfw/tools/ide/completion/CompletionCandidateCollector.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.Arrays;
44
import java.util.List;
5+
import java.util.Set;
56
import java.util.stream.Collectors;
67

78
import com.devonfw.tools.ide.commandlet.Commandlet;
@@ -85,4 +86,9 @@ default void clear() {
8586
*/
8687
List<CompletionCandidate> getSortedCandidates();
8788

89+
/**
90+
* @return the set of already-provided arguments, or {@code null} if not set.
91+
*/
92+
Set<String> getAlreadyProvided();
93+
8894
}

cli/src/main/java/com/devonfw/tools/ide/completion/CompletionCandidateCollectorAdapter.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.devonfw.tools.ide.completion;
22

33
import java.util.List;
4+
import java.util.Set;
45

56
import com.devonfw.tools.ide.commandlet.Commandlet;
67
import com.devonfw.tools.ide.property.Property;
@@ -50,4 +51,10 @@ public void disableSorting() {
5051

5152
this.delegate.disableSorting();
5253
}
54+
55+
@Override
56+
public Set<String> getAlreadyProvided() {
57+
58+
return this.delegate.getAlreadyProvided();
59+
}
5360
}

cli/src/main/java/com/devonfw/tools/ide/completion/CompletionCandidateCollectorDefault.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import java.util.ArrayList;
44
import java.util.Collections;
5+
import java.util.HashSet;
56
import java.util.List;
7+
import java.util.Set;
68

79
import org.slf4j.Logger;
810
import org.slf4j.LoggerFactory;
@@ -24,14 +26,30 @@ public class CompletionCandidateCollectorDefault implements CompletionCandidateC
2426

2527
private boolean sortCandidates;
2628

29+
/**
30+
* The set of arguments that have already been provided on the command line.
31+
*/
32+
private final Set<String> alreadyProvided;
33+
2734
/**
2835
* The constructor.
2936
*
3037
* @param context the {@link IdeContext}.
3138
*/
3239
public CompletionCandidateCollectorDefault(IdeContext context) {
40+
this(context, new HashSet<>());
41+
}
42+
43+
/**
44+
* The constructor.
45+
*
46+
* @param context the {@link IdeContext}.
47+
* @param alreadyProvided the {@link Set} of arguments already provided before the completion argument.
48+
*/
49+
public CompletionCandidateCollectorDefault(IdeContext context, Set<String> alreadyProvided) {
3350

3451
super();
52+
this.alreadyProvided = Collections.unmodifiableSet(alreadyProvided);
3553
this.candidates = new ArrayList<>();
3654
this.context = context;
3755
this.sortCandidates = true;
@@ -74,6 +92,12 @@ public void disableSorting() {
7492
this.sortCandidates = false;
7593
}
7694

95+
@Override
96+
public Set<String> getAlreadyProvided() {
97+
98+
return this.alreadyProvided;
99+
}
100+
77101
@Override
78102
public String toString() {
79103

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.devonfw.tools.ide.completion;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.Set;
6+
7+
import com.devonfw.tools.ide.commandlet.Commandlet;
8+
import com.devonfw.tools.ide.property.Property;
9+
10+
/**
11+
* A completion candidate that may have one or more synonyms. When any one of the candidate or its synonyms has already been provided on the command line, none
12+
* of them will be suggested again.
13+
*/
14+
public class CompletionEntry {
15+
16+
/** The primary candidate string. */
17+
private String candidate;
18+
19+
/** List of synonym strings for this candidate. */
20+
private List<String> synonyms = new ArrayList<>();
21+
22+
/**
23+
* The constructor.
24+
*
25+
* @param candidate the primary candidate to add.
26+
*/
27+
public CompletionEntry(String candidate) {
28+
this.candidate = candidate;
29+
}
30+
31+
/**
32+
* Adds a synonym for this candidate.
33+
*
34+
* @param synonym the synonym to add.
35+
*/
36+
public void addSynonym(String synonym) {
37+
this.synonyms.add(synonym);
38+
}
39+
40+
/**
41+
* Performs auto-completion for this entry, skipping it entirely if the candidate or any of its synonyms has already been provided on the command line.
42+
*
43+
* @param arg the current argument being completed.
44+
* @param collector the {@link CompletionCandidateCollector} to add matching candidates to.
45+
* @param property the {@link Property} that triggered completion.
46+
* @param commandlet the {@link Commandlet} owning the property.
47+
*/
48+
public void complete(String arg, CompletionCandidateCollector collector, Property<?> property, Commandlet commandlet) {
49+
50+
Set<String> alreadyProvided = collector.getAlreadyProvided();
51+
if (alreadyProvided != null && (alreadyProvided.contains(this.candidate) || synonyms.stream().anyMatch(alreadyProvided::contains))) {
52+
return;
53+
}
54+
55+
if (candidate.startsWith(arg)) {
56+
collector.add(candidate, "", property, commandlet);
57+
}
58+
59+
for (String synonym : synonyms) {
60+
if (synonym.startsWith(arg)) {
61+
collector.add(synonym, "", property, commandlet);
62+
}
63+
}
64+
}
65+
66+
}

cli/src/main/java/com/devonfw/tools/ide/completion/IdeCompleter.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.devonfw.tools.ide.completion;
22

3+
import java.util.HashSet;
34
import java.util.List;
5+
import java.util.Set;
46

57
import org.jline.reader.Candidate;
68
import org.jline.reader.Completer;
@@ -41,8 +43,14 @@ public void complete(LineReader reader, ParsedLine commandLine, List<Candidate>
4143
}
4244

4345
List<String> words = commandLine.words();
44-
CliArguments args = CliArguments.ofCompletion(words.toArray(String[]::new));
45-
List<CompletionCandidate> completion = this.context.complete(args, true);
46+
String[] argsArray = words.toArray(String[]::new);
47+
CliArguments args = CliArguments.ofCompletion(argsArray);
48+
Set<String> alreadyProvided = new HashSet<>();
49+
for (int i = 0; i < argsArray.length - 1; i++) {
50+
alreadyProvided.add(argsArray[i]);
51+
}
52+
CompletionCandidateCollector collector = new CompletionCandidateCollectorDefault(this.context, alreadyProvided);
53+
List<CompletionCandidate> completion = this.context.complete(args, collector, true);
4654
int i = 0;
4755
for (CompletionCandidate candidate : completion) {
4856

cli/src/main/java/com/devonfw/tools/ide/context/AbstractIdeContext.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
import com.devonfw.tools.ide.common.SystemPath;
4141
import com.devonfw.tools.ide.completion.CompletionCandidate;
4242
import com.devonfw.tools.ide.completion.CompletionCandidateCollector;
43-
import com.devonfw.tools.ide.completion.CompletionCandidateCollectorDefault;
4443
import com.devonfw.tools.ide.environment.AbstractEnvironmentVariables;
4544
import com.devonfw.tools.ide.environment.EnvironmentVariables;
4645
import com.devonfw.tools.ide.environment.EnvironmentVariablesType;
@@ -76,9 +75,9 @@
7675
import com.devonfw.tools.ide.tool.mvn.MvnRepository;
7776
import com.devonfw.tools.ide.tool.npm.NpmRepository;
7877
import com.devonfw.tools.ide.tool.pip.PipRepository;
78+
import com.devonfw.tools.ide.tool.python.PythonRepository;
7979
import com.devonfw.tools.ide.tool.repository.DefaultToolRepository;
8080
import com.devonfw.tools.ide.tool.repository.ToolRepository;
81-
import com.devonfw.tools.ide.tool.python.PythonRepository;
8281
import com.devonfw.tools.ide.tool.uv.UvRepository;
8382
import com.devonfw.tools.ide.url.model.UrlMetadata;
8483
import com.devonfw.tools.ide.util.DateTimeUtil;
@@ -1543,9 +1542,8 @@ public void verifyIdeMinVersion(boolean throwException) {
15431542
* @param includeContextOptions to include the options of {@link ContextCommandlet}.
15441543
* @return the {@link List} of {@link CompletionCandidate}s to suggest.
15451544
*/
1546-
public List<CompletionCandidate> complete(CliArguments arguments, boolean includeContextOptions) {
1545+
public List<CompletionCandidate> complete(CliArguments arguments, CompletionCandidateCollector collector, boolean includeContextOptions) {
15471546

1548-
CompletionCandidateCollector collector = new CompletionCandidateCollectorDefault(this);
15491547
if (arguments.current().isStart()) {
15501548
arguments.next();
15511549
}
@@ -1595,6 +1593,7 @@ private Property<?> nextValueProperty(Iterator<Property<?>> valueIterator, CliAr
15951593
private void completeCommandlet(CliArguments arguments, Commandlet cmd, CompletionCandidateCollector collector) {
15961594

15971595
LOG.trace("Trying to match arguments for auto-completion for commandlet {}", cmd.getName());
1596+
15981597
Iterator<Property<?>> valueIterator = cmd.getValues().iterator();
15991598
valueIterator.next(); // skip first property since this is the keyword property that already matched to find the commandlet
16001599
Property<?> currentValueProperty = nextValueProperty(valueIterator, arguments);

cli/src/main/java/com/devonfw/tools/ide/tool/ToolCommandlet.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,9 @@ public ToolInstallation install(ToolInstallRequest request) {
351351
ToolInstallation installation = doInstall(request);
352352
if (installation != null && installation.installedAsynchronously()) {
353353
LOG.warn(
354-
"The installation of {} is currently running in the background!\nYou need to complete the installation, potentially "
355-
+ "reboot and rerun your 'ide' command in a new terminal session after the installation has completed.",
354+
"The installation of {} is currently running in the background!\n"
355+
+ "You need to complete the installation, potentially reboot and rerun your 'ide' command in a new terminal session"
356+
+ " after the installation has completed.",
356357
request.getRequested());
357358
}
358359
return installation;

0 commit comments

Comments
 (0)