Skip to content

Commit ee94ba3

Browse files
committed
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
1 parent 641aee4 commit ee94ba3

File tree

5 files changed

+51
-9
lines changed

5 files changed

+51
-9
lines changed

spring-shell-core/src/main/java/org/springframework/shell/command/CommandContext.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 the original author or authors.
2+
* Copyright 2022-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -148,8 +148,9 @@ private Optional<CommandParserResult> find(String name) {
148148
return results.results().stream()
149149
.filter(r -> {
150150
Stream<String> l = Arrays.asList(r.option().getLongNames()).stream();
151+
Stream<String> lm = Arrays.asList(r.option().getLongNamesModified()).stream();
151152
Stream<String> s = Arrays.asList(r.option().getShortNames()).stream().map(n -> Character.toString(n));
152-
return Stream.concat(l, s)
153+
return Stream.concat(Stream.concat(l, lm), s)
153154
.filter(o -> ObjectUtils.nullSafeEquals(o, name))
154155
.findFirst()
155156
.isPresent();

spring-shell-core/src/main/java/org/springframework/shell/command/CommandExecution.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@ else if (targetInfo.getTargetType() == TargetType.METHOD) {
198198
messageBuilder.setHeader(ArgumentHeaderMethodArgumentResolver.ARGUMENT_PREFIX + n, r.value());
199199
paramValues.put(n, r.value());
200200
}
201+
// need to provide backmapping for orinal names which were modified
202+
for (String n : r.option().getLongNamesModified()) {
203+
messageBuilder.setHeader(ArgumentHeaderMethodArgumentResolver.ARGUMENT_PREFIX + n, r.value());
204+
paramValues.put(n, r.value());
205+
}
201206
}
202207
if (r.option().getShortNames() != null) {
203208
for (Character n : r.option().getShortNames()) {

spring-shell-core/src/main/java/org/springframework/shell/command/CommandOption.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 the original author or authors.
2+
* Copyright 2022-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -32,6 +32,14 @@ public interface CommandOption {
3232
*/
3333
String[] getLongNames();
3434

35+
/**
36+
* Gets a modified long names of an option. Set within a command registration if
37+
* option name modifier were used to have an info about original names.
38+
*
39+
* @return modified long names of an option
40+
*/
41+
String[] getLongNamesModified();
42+
3543
/**
3644
* Gets a short names of an option.
3745
*
@@ -111,7 +119,7 @@ public interface CommandOption {
111119
* @return default command option
112120
*/
113121
public static CommandOption of(String[] longNames, Character[] shortNames, String description) {
114-
return of(longNames, shortNames, description, null, false, null, null, null, null, null, null);
122+
return of(longNames, null, shortNames, description, null, false, null, null, null, null, null, null);
115123
}
116124

117125
/**
@@ -125,13 +133,14 @@ public static CommandOption of(String[] longNames, Character[] shortNames, Strin
125133
*/
126134
public static CommandOption of(String[] longNames, Character[] shortNames, String description,
127135
ResolvableType type) {
128-
return of(longNames, shortNames, description, type, false, null, null, null, null, null, null);
136+
return of(longNames, null, shortNames, description, type, false, null, null, null, null, null, null);
129137
}
130138

131139
/**
132140
* Gets an instance of a default {@link CommandOption}.
133141
*
134142
* @param longNames the long names
143+
* @param longNamesModified the modified long names
135144
* @param shortNames the short names
136145
* @param description the description
137146
* @param type the type
@@ -144,10 +153,10 @@ public static CommandOption of(String[] longNames, Character[] shortNames, Strin
144153
* @param completion the completion
145154
* @return default command option
146155
*/
147-
public static CommandOption of(String[] longNames, Character[] shortNames, String description,
156+
public static CommandOption of(String[] longNames, String[] longNamesModified, Character[] shortNames, String description,
148157
ResolvableType type, boolean required, String defaultValue, Integer position, Integer arityMin,
149158
Integer arityMax, String label, CompletionResolver completion) {
150-
return new DefaultCommandOption(longNames, shortNames, description, type, required, defaultValue, position,
159+
return new DefaultCommandOption(longNames, longNamesModified, shortNames, description, type, required, defaultValue, position,
151160
arityMin, arityMax, label, completion);
152161
}
153162

@@ -157,6 +166,7 @@ public static CommandOption of(String[] longNames, Character[] shortNames, Strin
157166
public static class DefaultCommandOption implements CommandOption {
158167

159168
private String[] longNames;
169+
private String[] longNamesModified;
160170
private Character[] shortNames;
161171
private String description;
162172
private ResolvableType type;
@@ -168,11 +178,12 @@ public static class DefaultCommandOption implements CommandOption {
168178
private String label;
169179
private CompletionResolver completion;
170180

171-
public DefaultCommandOption(String[] longNames, Character[] shortNames, String description,
181+
public DefaultCommandOption(String[] longNames, String[] longNamesModified, Character[] shortNames, String description,
172182
ResolvableType type, boolean required, String defaultValue, Integer position,
173183
Integer arityMin, Integer arityMax, String label,
174184
CompletionResolver completion) {
175185
this.longNames = longNames != null ? longNames : new String[0];
186+
this.longNamesModified = longNamesModified != null ? longNamesModified : new String[0];
176187
this.shortNames = shortNames != null ? shortNames : new Character[0];
177188
this.description = description;
178189
this.type = type;
@@ -190,6 +201,11 @@ public String[] getLongNames() {
190201
return longNames;
191202
}
192203

204+
@Override
205+
public String[] getLongNamesModified() {
206+
return longNamesModified;
207+
}
208+
193209
@Override
194210
public Character[] getShortNames() {
195211
return shortNames;

spring-shell-core/src/main/java/org/springframework/shell/command/CommandRegistration.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1245,11 +1245,13 @@ public List<CommandOption> getOptions() {
12451245
options = optionSpecs.stream()
12461246
.map(o -> {
12471247
String[] longNames = o.getLongNames();
1248+
String[] longNamesModified = null;
12481249
Function<String, String> modifier = o.getOptionNameModifier();
12491250
if (modifier != null) {
1251+
longNamesModified = Arrays.copyOf(longNames, longNames.length);
12501252
longNames = Arrays.stream(longNames).map(modifier).toArray(String[]::new);
12511253
}
1252-
return CommandOption.of(longNames, o.getShortNames(), o.getDescription(), o.getType(),
1254+
return CommandOption.of(longNames, longNamesModified, o.getShortNames(), o.getDescription(), o.getType(),
12531255
o.isRequired(), o.getDefaultValue(), o.getPosition(), o.getArityMin(), o.getArityMax(),
12541256
o.getLabel(), o.getCompletion());
12551257
})

spring-shell-core/src/test/java/org/springframework/shell/command/CommandExecutionTests.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,4 +564,22 @@ public void testCommandNotAvailable() {
564564
Object result = execution.evaluate(new String[] { "command1", "--arg1", "myarg1value" });
565565
assertThat(result).isInstanceOf(CommandNotCurrentlyAvailable.class);
566566
}
567+
568+
@Test
569+
public void testExecutionWithModifiedLongOption() {
570+
CommandRegistration r1 = CommandRegistration.builder()
571+
.command("command1")
572+
.withOption()
573+
.longNames("arg1")
574+
.nameModifier(orig -> "x" + orig)
575+
.and()
576+
.withTarget()
577+
.function(function1)
578+
.and()
579+
.build();
580+
commandCatalog.register(r1);
581+
Object result = execution.evaluate(new String[] { "command1", "--xarg1", "myarg1value" });
582+
assertThat(result).isEqualTo("himyarg1value");
583+
}
584+
567585
}

0 commit comments

Comments
 (0)