Skip to content

Commit

Permalink
devonfw#834 : support for --help (devonfw#876)
Browse files Browse the repository at this point in the history
  • Loading branch information
hohwille authored Dec 9, 2024
1 parent b8c6705 commit f19f360
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,13 @@ protected void add(Commandlet commandlet) {
KeywordProperty keyword = commandlet.getFirstKeyword();
if (keyword != null) {
String name = keyword.getName();
this.firstKeywordMap.putIfAbsent(name, commandlet);
registerKeyword(name, commandlet);
if (name.startsWith("--")) {
this.firstKeywordMap.putIfAbsent(name.substring(2), commandlet);
registerKeyword(name.substring(2), commandlet);
}
String alias = keyword.getAlias();
if (alias != null) {
this.firstKeywordMap.putIfAbsent(alias, commandlet);
registerKeyword(alias, commandlet);
}
}
for (int i = 0; i < propertyCount; i++) {
Expand All @@ -160,6 +160,14 @@ protected void add(Commandlet commandlet) {
}
}

private void registerKeyword(String keyword, Commandlet commandlet) {

Commandlet duplicate = this.firstKeywordMap.putIfAbsent(keyword, commandlet);
if (duplicate != null) {
this.context.debug("Duplicate keyword {} already used by {} so it cannot be associated also with {}", keyword, duplicate, commandlet);
}
}

@Override
public Collection<Commandlet> getCommandlets() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public final class HelpCommandlet extends Commandlet {
public HelpCommandlet(IdeContext context) {

super(context);
addKeyword(getName());
addKeyword("--help", "-h");
this.commandlet = add(new CommandletProperty("", false, "commandlet"));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ public class VersionCommandlet extends Commandlet {
public VersionCommandlet(IdeContext context) {

super(context);
addKeyword(getName(), "-v");
addKeyword("--version", "-v");
}

@Override
public String getName() {

return "--version";
return "version";
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
*/
public class KeywordProperty extends BooleanProperty {

private final String optionName;

/**
* The constructor.
*
Expand All @@ -19,8 +21,17 @@ public class KeywordProperty extends BooleanProperty {
*/
public KeywordProperty(String name, boolean required, String alias) {

super(name, required, alias);
super(getNormalizedName(name), required, alias);
this.optionName = name;
}

private static String getNormalizedName(String name) {

assert !name.isEmpty();
if (name.startsWith("--")) {
return name.substring(2);
}
return name;
}

@Override
Expand All @@ -35,6 +46,25 @@ public boolean isExpectValue() {
return false;
}

@Override
public boolean matches(String nameOrAlias) {

if (super.matches(nameOrAlias)) {
return true;
}
return this.optionName.equals(nameOrAlias);
}

@Override
public boolean apply(CliArguments args, IdeContext context, Commandlet commandlet, CompletionCandidateCollector collector) {

String normalizedName = this.name;
if (args.current().isOption()) {
normalizedName = this.optionName;
}
return apply(normalizedName, args, context, commandlet, collector);
}

@Override
protected boolean applyValue(String argValue, boolean lookahead, CliArguments args, IdeContext context, Commandlet commandlet,
CompletionCandidateCollector collector) {
Expand Down
35 changes: 27 additions & 8 deletions cli/src/main/java/com/devonfw/tools/ide/property/Property.java
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,10 @@ public void clearValue() {
this.value.clear();
}

/**
* @param value the value to add to the {@link List} of values.
* @see #isMultiValued()
*/
public void addValue(V value) {

if (!this.multivalued) {
Expand Down Expand Up @@ -331,13 +335,26 @@ protected V getNullValue() {
*/
public boolean apply(CliArguments args, IdeContext context, Commandlet commandlet, CompletionCandidateCollector collector) {

return apply(this.name, args, context, commandlet, collector);
}

/**
* @param normalizedName the {@link #getName() name} or potentially a normalized form of it (see {@link KeywordProperty}).
* @param args the {@link CliArguments} already {@link CliArguments#current() pointing} the {@link CliArgument} to apply.
* @param context the {@link IdeContext}.
* @param commandlet the {@link Commandlet} owning this property.
* @param collector the {@link CompletionCandidateCollector}.
* @return {@code true} if it matches, {@code false} otherwise.
*/
protected boolean apply(String normalizedName, CliArguments args, IdeContext context, Commandlet commandlet, CompletionCandidateCollector collector) {

CliArgument argument = args.current();
if (argument.isCompletion()) {
int size = collector.getCandidates().size();
complete(argument, args, context, commandlet, collector);
complete(normalizedName, argument, args, context, commandlet, collector);
return (collector.getCandidates().size() > size);
}
boolean option = isOption();
boolean option = normalizedName.startsWith("-");
if (option && !argument.isOption()) {
return false;
}
Expand All @@ -346,7 +363,7 @@ public boolean apply(CliArguments args, IdeContext context, Commandlet commandle
}
String argValue = null;
boolean lookahead = false;
if (this.name.isEmpty()) {
if (normalizedName.isEmpty()) {
argValue = argument.get();
} else {
if (!matches(argument.getKey())) {
Expand Down Expand Up @@ -398,25 +415,27 @@ protected boolean applyValue(String argValue, boolean lookahead, CliArguments ar
/**
* Performs auto-completion for the {@code arg}.
*
* @param normalizedName the {@link #getName() name} or potentially a normalized form of it (see {@link KeywordProperty}).
* @param argument the {@link CliArgument CLI argument}.
* @param args the {@link CliArguments}.
* @param context the {@link IdeContext}.
* @param commandlet the {@link Commandlet} owning this {@link Property}.
* @param collector the {@link CompletionCandidateCollector}.
*/
protected void complete(CliArgument argument, CliArguments args, IdeContext context, Commandlet commandlet, CompletionCandidateCollector collector) {
protected void complete(String normalizedName, CliArgument argument, CliArguments args, IdeContext context, Commandlet commandlet,
CompletionCandidateCollector collector) {

String arg = argument.get();
if (this.name.isEmpty()) {
if (normalizedName.isEmpty()) {
int count = collector.getCandidates().size();
completeValue(arg, context, commandlet, collector);
if (collector.getCandidates().size() > count) {
args.next();
}
return;
}
if (this.name.startsWith(arg)) {
collector.add(this.name, null, this, commandlet);
if (normalizedName.startsWith(arg)) {
collector.add(normalizedName, null, this, commandlet);
}
if (this.alias != null) {
if (this.alias.startsWith(arg)) {
Expand All @@ -431,7 +450,7 @@ protected void complete(CliArgument argument, CliArguments args, IdeContext cont
String value = argument.getValue();
if (value != null) {
String key = argument.getKey();
if (this.name.equals(key) || Objects.equals(this.alias, key)) {
if (normalizedName.equals(key) || Objects.equals(this.alias, key)) {
completeValue(value, context, commandlet, new CompletionCandidateCollectorAdapter(key + "=", collector));
}
}
Expand Down
4 changes: 2 additions & 2 deletions cli/src/main/resources/nls/Help.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
cmd.--version=Print the version of IDEasy.
cmd.--version.detail=To print the current version of IDEasy simply type: 'ide --version'.
cmd.android-studio=Tool commandlet for Android Studio (IDE).
cmd.android-studio.detail=The android-studio commandlet allows to install, configure, and launch Android Studio. To launch Android Studio for your current workspace and IDEasy installation, simply run: ide android-studio. Detailed documentation can be found at https://developer.android.com/studio/.
cmd.aws=Tool commandlet for AWS CLI.
Expand Down Expand Up @@ -110,6 +108,8 @@ cmd.uninstall-plugin.detail=Plugins can be only installed or uninstalled for too
cmd.uninstall.detail=Can be used to uninstall any tool e.g. to uninstall java simply type: 'uninstall java'.
cmd.update=Pull your settings and apply updates (software, configuration and repositories).
cmd.update.detail=To update your IDE (if instructed by your ide-admin), you only need to run the following command: 'ide update'.
cmd.version=Print the version of IDEasy.
cmd.version.detail=To print the current version of IDEasy simply type: 'ide --version'.
cmd.vscode=Tool commandlet for Visual Studio Code (IDE).
cmd.vscode.detail=Visual Studio Code (VS Code) is a popular code editor developed by Microsoft. Detailed documentation can be found at https://code.visualstudio.com/docs/
commandlets=Available commandlets:
Expand Down
4 changes: 2 additions & 2 deletions cli/src/main/resources/nls/Help_de.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
cmd.--version=Gibt die Version von IDEasy aus.
cmd.--version.detail=Um die aktuelle Version von IDEasy auszugeben, brauchen Sie einfach nur 'ide --version' in die Konsole eingeben.
cmd.android-studio=Werkzeug Kommando für Android Studio (IDE).
cmd.android-studio.detail=Das android-studio Kommando ermöglicht die Installation, Konfiguration und den Start von Android Studio. Um Android Studio für Ihren aktuellen Arbeitsbereich und die IDEasy-Installation zu starten, führen Sie einfach: 'ide android-studio' aus. Detaillierte Dokumentation finden Sie unter https://developer.android.com/studio/.
cmd.aws=Werkzeug Kommando für AWS Kommandoschnittstelle.
Expand Down Expand Up @@ -110,6 +108,8 @@ cmd.uninstall-plugin.detail=Erweiterung können nur für Werkzeuge installiert u
cmd.uninstall.detail=Wird dazu verwendet um jedwedes Werkzeug zu deinstallieren. Um z.B. Java zu deinstallieren geben Sie einfach 'uninstall java' in die Konsole ein.
cmd.update=Updatet die Settings, Software und Repositories.
cmd.update.detail=Um die IDE auf den neuesten Stand zu bringen (falls von Ihrem Admin angewiesen) geben Sie einfach 'ide update' in die Konsole ein.
cmd.version=Gibt die Version von IDEasy aus.
cmd.version.detail=Um die aktuelle Version von IDEasy auszugeben, brauchen Sie einfach nur 'ide --version' in die Konsole eingeben.
cmd.vscode=Werkzeug Kommando für Visual Studio Code (IDE).
cmd.vscode.detail=Visual Studio Code (VS Code) ist ein beliebter Code-Editor, der von Microsoft entwickelt wurde. Detaillierte Dokumentation ist zu finden unter https://code.visualstudio.com/docs/
commandlets=Verfügbare Kommandos:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.devonfw.tools.ide.commandlet.ContextCommandlet;
import com.devonfw.tools.ide.context.AbstractIdeContext;
import com.devonfw.tools.ide.context.IdeContextTest;
import com.devonfw.tools.ide.property.KeywordProperty;
import com.devonfw.tools.ide.property.Property;

/**
Expand Down Expand Up @@ -92,7 +93,7 @@ public void testCompleteShortOptsCombined() {
// act
List<CompletionCandidate> candidates = context.complete(args, true);
// assert
assertThat(candidates.stream().map(CompletionCandidate::text)).containsExactly("-f", "-fb", "-fd", "-fo", "-fq",
assertThat(candidates.stream().map(CompletionCandidate::text)).containsExactly("-f", "-fb", "-fd", "-fh", "-fo", "-fq",
"-ft", "-fv");
}

Expand All @@ -106,7 +107,7 @@ public void testCompleteShortOptsCombinedAllButVersion() {
// act
List<CompletionCandidate> candidates = context.complete(args, true);
// assert
assertThat(candidates.stream().map(CompletionCandidate::text)).containsExactly("-fbdoqt", "-fbdoqtv");
assertThat(candidates.stream().map(CompletionCandidate::text)).containsExactly("-fbdoqt", "-fbdoqth", "-fbdoqtv");
}

/** Test of {@link AbstractIdeContext#complete(CliArguments, boolean) auto-completion} for input "help", "". */
Expand Down Expand Up @@ -151,7 +152,7 @@ public void testCompleteCommandletOption() {
}

private static List<String> getExpectedCandidates(AbstractIdeContext context, boolean commandlets,
boolean ctxOptions, boolean addVersionAlias) {
boolean ctxOptions, boolean addAlias) {

List<String> expectedCandidates = new ArrayList<>();
if (ctxOptions) {
Expand All @@ -167,9 +168,14 @@ private static List<String> getExpectedCandidates(AbstractIdeContext context, bo
if (commandlets) {
for (Commandlet cmd : context.getCommandletManager().getCommandlets()) {
expectedCandidates.add(cmd.getName());
}
if (addVersionAlias) {
expectedCandidates.add("-v"); // alias for VersionCommandlet (--version)
if (addAlias) {
Property<?> firstProperty = cmd.getValues().get(0);
assert (firstProperty instanceof KeywordProperty);
String alias = firstProperty.getAlias();
if (alias != null) {
expectedCandidates.add(alias);
}
}
}
}
Collections.sort(expectedCandidates);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,31 @@ class CommandletPropertyTest {

@Test
public void testCompleteValue() {

// arrange
IdeContext context = IdeTestContextMock.get();
String[] expectedCandidates = { "help", "helm" };
String input = "he";
CompletionCandidateCollector collector = new CompletionCandidateCollectorDefault(context);

CommandletProperty cmdProp = new CommandletProperty("", false, "");

// act
cmdProp.completeValue(input, context, new ContextCommandlet(), collector);

// assert
assertThat(collector.getCandidates().stream().map(CompletionCandidate::text)).containsExactlyInAnyOrder(expectedCandidates);
}

@Test
public void testParse() {

// arrange
IdeContext context = IdeTestContextMock.get();

// act
CommandletProperty cmdProp = new CommandletProperty("", false, "");

// act + assert
assertThat(cmdProp.parse("help", context)).isInstanceOf(HelpCommandlet.class);
assertThat(cmdProp.parse("helm", context)).isInstanceOf(Helm.class);
assertThat(cmdProp.parse("intellij", context)).isInstanceOf(Intellij.class);
Expand Down

0 comments on commit f19f360

Please sign in to comment.