Add better support for modified option names

- Longnames in a command option if modified via
  name modifier didn't provide enough backmapping
  info for command execution experience being accurate.
- Add new getLongNamesModified() into CommandOption
  which is populated if name modifier is used.
- Add more hints in CommandExecution for modified
  option names.
- This should bring annotation, legacy annotation
  and programmatic commands up to date.
- Backport #777
- Fixes #783
This commit is contained in:
Janne Valkealahti
2023-06-19 12:30:29 +01:00
parent 641aee4411
commit ee94ba37ef
5 changed files with 51 additions and 9 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2022 the original author or authors.
* Copyright 2022-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -148,8 +148,9 @@ public interface CommandContext {
return results.results().stream()
.filter(r -> {
Stream<String> l = Arrays.asList(r.option().getLongNames()).stream();
Stream<String> lm = Arrays.asList(r.option().getLongNamesModified()).stream();
Stream<String> s = Arrays.asList(r.option().getShortNames()).stream().map(n -> Character.toString(n));
return Stream.concat(l, s)
return Stream.concat(Stream.concat(l, lm), s)
.filter(o -> ObjectUtils.nullSafeEquals(o, name))
.findFirst()
.isPresent();

View File

@@ -198,6 +198,11 @@ public interface CommandExecution {
messageBuilder.setHeader(ArgumentHeaderMethodArgumentResolver.ARGUMENT_PREFIX + n, r.value());
paramValues.put(n, r.value());
}
// need to provide backmapping for orinal names which were modified
for (String n : r.option().getLongNamesModified()) {
messageBuilder.setHeader(ArgumentHeaderMethodArgumentResolver.ARGUMENT_PREFIX + n, r.value());
paramValues.put(n, r.value());
}
}
if (r.option().getShortNames() != null) {
for (Character n : r.option().getShortNames()) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2022 the original author or authors.
* Copyright 2022-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,6 +32,14 @@ public interface CommandOption {
*/
String[] getLongNames();
/**
* Gets a modified long names of an option. Set within a command registration if
* option name modifier were used to have an info about original names.
*
* @return modified long names of an option
*/
String[] getLongNamesModified();
/**
* Gets a short names of an option.
*
@@ -111,7 +119,7 @@ public interface CommandOption {
* @return default command option
*/
public static CommandOption of(String[] longNames, Character[] shortNames, String description) {
return of(longNames, shortNames, description, null, false, null, null, null, null, null, null);
return of(longNames, null, shortNames, description, null, false, null, null, null, null, null, null);
}
/**
@@ -125,13 +133,14 @@ public interface CommandOption {
*/
public static CommandOption of(String[] longNames, Character[] shortNames, String description,
ResolvableType type) {
return of(longNames, shortNames, description, type, false, null, null, null, null, null, null);
return of(longNames, null, shortNames, description, type, false, null, null, null, null, null, null);
}
/**
* Gets an instance of a default {@link CommandOption}.
*
* @param longNames the long names
* @param longNamesModified the modified long names
* @param shortNames the short names
* @param description the description
* @param type the type
@@ -144,10 +153,10 @@ public interface CommandOption {
* @param completion the completion
* @return default command option
*/
public static CommandOption of(String[] longNames, Character[] shortNames, String description,
public static CommandOption of(String[] longNames, String[] longNamesModified, Character[] shortNames, String description,
ResolvableType type, boolean required, String defaultValue, Integer position, Integer arityMin,
Integer arityMax, String label, CompletionResolver completion) {
return new DefaultCommandOption(longNames, shortNames, description, type, required, defaultValue, position,
return new DefaultCommandOption(longNames, longNamesModified, shortNames, description, type, required, defaultValue, position,
arityMin, arityMax, label, completion);
}
@@ -157,6 +166,7 @@ public interface CommandOption {
public static class DefaultCommandOption implements CommandOption {
private String[] longNames;
private String[] longNamesModified;
private Character[] shortNames;
private String description;
private ResolvableType type;
@@ -168,11 +178,12 @@ public interface CommandOption {
private String label;
private CompletionResolver completion;
public DefaultCommandOption(String[] longNames, Character[] shortNames, String description,
public DefaultCommandOption(String[] longNames, String[] longNamesModified, Character[] shortNames, String description,
ResolvableType type, boolean required, String defaultValue, Integer position,
Integer arityMin, Integer arityMax, String label,
CompletionResolver completion) {
this.longNames = longNames != null ? longNames : new String[0];
this.longNamesModified = longNamesModified != null ? longNamesModified : new String[0];
this.shortNames = shortNames != null ? shortNames : new Character[0];
this.description = description;
this.type = type;
@@ -190,6 +201,11 @@ public interface CommandOption {
return longNames;
}
@Override
public String[] getLongNamesModified() {
return longNamesModified;
}
@Override
public Character[] getShortNames() {
return shortNames;

View File

@@ -1245,11 +1245,13 @@ public interface CommandRegistration {
options = optionSpecs.stream()
.map(o -> {
String[] longNames = o.getLongNames();
String[] longNamesModified = null;
Function<String, String> modifier = o.getOptionNameModifier();
if (modifier != null) {
longNamesModified = Arrays.copyOf(longNames, longNames.length);
longNames = Arrays.stream(longNames).map(modifier).toArray(String[]::new);
}
return CommandOption.of(longNames, o.getShortNames(), o.getDescription(), o.getType(),
return CommandOption.of(longNames, longNamesModified, o.getShortNames(), o.getDescription(), o.getType(),
o.isRequired(), o.getDefaultValue(), o.getPosition(), o.getArityMin(), o.getArityMax(),
o.getLabel(), o.getCompletion());
})

View File

@@ -564,4 +564,22 @@ public class CommandExecutionTests extends AbstractCommandTests {
Object result = execution.evaluate(new String[] { "command1", "--arg1", "myarg1value" });
assertThat(result).isInstanceOf(CommandNotCurrentlyAvailable.class);
}
@Test
public void testExecutionWithModifiedLongOption() {
CommandRegistration r1 = CommandRegistration.builder()
.command("command1")
.withOption()
.longNames("arg1")
.nameModifier(orig -> "x" + orig)
.and()
.withTarget()
.function(function1)
.and()
.build();
commandCatalog.register(r1);
Object result = execution.evaluate(new String[] { "command1", "--xarg1", "myarg1value" });
assertThat(result).isEqualTo("himyarg1value");
}
}