Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,19 @@
*/
package org.springframework.shell.core.command;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import jakarta.validation.Path;

import org.jspecify.annotations.Nullable;

import org.springframework.shell.core.ParameterValidationException;
import org.springframework.shell.core.command.availability.Availability;
import org.springframework.shell.core.command.availability.AvailabilityProvider;
import org.springframework.shell.core.command.completion.CompletionProvider;
import org.springframework.shell.core.command.completion.DefaultCompletionProvider;
import org.springframework.shell.core.command.exit.ExitStatusExceptionMapper;
import org.springframework.shell.core.command.completion.CompletionProvider;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
* Base class helping to build shell commands.
Expand Down Expand Up @@ -58,6 +56,8 @@ public abstract class AbstractCommand implements Command {

private List<CommandOption> options = new ArrayList<>();

private List<CommandArgument> arguments = new ArrayList<>();

private List<String> aliases = new ArrayList<>();

public AbstractCommand(String name, String description) {
Expand Down Expand Up @@ -123,6 +123,15 @@ public void setOptions(List<CommandOption> options) {
this.options = options;
}

@Override
public List<CommandArgument> getArguments() {
return arguments;
}

public void setArguments(List<CommandArgument> arguments) {
this.arguments = arguments;
}

@Override
public AvailabilityProvider getAvailabilityProvider() {
return availabilityProvider;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,22 @@
*/
package org.springframework.shell.core.command;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

import org.jspecify.annotations.Nullable;

import org.springframework.shell.core.command.adapter.ConsumerCommandAdapter;
import org.springframework.shell.core.command.adapter.FunctionCommandAdapter;
import org.springframework.shell.core.command.availability.AvailabilityProvider;
import org.springframework.shell.core.command.completion.CompletionProvider;
import org.springframework.shell.core.command.completion.DefaultCompletionProvider;
import org.springframework.shell.core.command.exit.ExitStatusExceptionMapper;
import org.springframework.shell.core.command.completion.CompletionProvider;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

/**
* @author Eric Bottard
* @author Piotr Olaszewski
Expand Down Expand Up @@ -96,6 +95,14 @@ default List<CommandOption> getOptions() {
return Collections.emptyList();
}

/**
* Get the arguments of the command.
* @return the arguments of the command
*/
default List<CommandArgument> getArguments() {
return Collections.emptyList();
}

/**
* Get the availability provider of the command. Defaults to always available.
* @return the availability provider of the command
Expand Down Expand Up @@ -156,6 +163,8 @@ final class Builder {

private List<CommandOption> options = new ArrayList<>();

private List<CommandArgument> arguments = new ArrayList<>();

public Builder name(String name) {
this.name = name;
return this;
Expand Down Expand Up @@ -206,6 +215,11 @@ public Builder options(CommandOption... options) {
return this;
}

public Builder arguments(CommandArgument... arguments) {
this.arguments = Arrays.asList(arguments);
return this;
}

public AbstractCommand execute(Consumer<CommandContext> commandExecutor) {
Assert.hasText(name, "'name' must be specified");

Expand All @@ -229,6 +243,7 @@ public AbstractCommand execute(Function<CommandContext, String> commandExecutor)
private void init(AbstractCommand command) {
command.setAliases(aliases);
command.setOptions(options);
command.setArguments(arguments);
command.setAvailabilityProvider(availabilityProvider);
command.setCompletionProvider(completionProvider);
if (exitStatusExceptionMapper != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,62 @@
*/
package org.springframework.shell.core.command;

import org.jspecify.annotations.Nullable;

/**
* Record representing a runtime argument to a command.
* Record representing the definition as well as the runtime information about a command
* argument.
*
* @author Mahmoud Ben Hassine
* @since 4.0.0
*/
public record CommandArgument(int index, String value) {
public record CommandArgument(int index, @Nullable String description, @Nullable String defaultValue,
@Nullable String value, Class<?> type) {

public static CommandArgument.Builder with() {
return new CommandArgument.Builder();
}

public static class Builder {

private int index = 0;

private @Nullable String description;

private @Nullable String defaultValue;

private @Nullable String value;

private Class<?> type = Object.class;

public CommandArgument.Builder index(int index) {
this.index = index;
return this;
}

public CommandArgument.Builder description(String description) {
this.description = description;
return this;
}

public CommandArgument.Builder defaultValue(String defaultValue) {
this.defaultValue = defaultValue;
return this;
}

public CommandArgument.Builder value(String value) {
this.value = value;
return this;
}

public CommandArgument.Builder type(Class<?> type) {
this.type = type;
return this;
}

public CommandArgument build() {
return new CommandArgument(index, description, defaultValue, value, type);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
*/
package org.springframework.shell.core.command;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.Collections;
import java.util.List;
import java.util.Optional;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* Default implementation of {@link CommandParser}. Supports options in the long form of
* --key=value or --key value as well in the short form of -k=value or -k value. Options
Expand Down Expand Up @@ -180,7 +180,7 @@ else if (word.startsWith("-")) {
}

private CommandArgument parseArgument(int index, String word) {
return new CommandArgument(index, unquoteAndUnescapeQuoted(word));
return CommandArgument.with().index(index).value(unquoteAndUnescapeQuoted(word)).build();
}

private String unquoteAndUnescapeQuoted(String s) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
*/
package org.springframework.shell.core.command;

import org.springframework.shell.core.utils.Utils;
import org.springframework.util.StringUtils;

import java.io.PrintWriter;
import java.util.List;

import org.springframework.shell.core.utils.Utils;

/**
* A command to display help about all available commands.
*
Expand Down Expand Up @@ -67,6 +68,7 @@ private String getHelpMessageForCommand(Command command) {
appendName(command, helpMessageBuilder);
appendSynopsis(command, helpMessageBuilder);
appendOptions(command, helpMessageBuilder);
appendArguments(command, helpMessageBuilder);
appendAliases(command, helpMessageBuilder);
return helpMessageBuilder.toString();
}
Expand All @@ -82,9 +84,11 @@ private void appendName(Command command, StringBuilder helpMessageBuilder) {

private void appendSynopsis(Command command, StringBuilder helpMessageBuilder) {
List<CommandOption> options = command.getOptions();
helpMessageBuilder.append("SYNOPSIS\n").append("\t").append(command.getName()).append(" ");
List<CommandArgument> arguments = command.getArguments();
helpMessageBuilder.append("SYNOPSIS\n").append("\t").append(command.getName());
if (!options.isEmpty()) {
for (CommandOption option : options) {
helpMessageBuilder.append(" ");
if (option.required()) {
helpMessageBuilder.append("[");
}
Expand All @@ -96,14 +100,24 @@ private void appendSynopsis(Command command, StringBuilder helpMessageBuilder) {
}
helpMessageBuilder.append(" ").append(option.type().getSimpleName());
if (option.required()) {
helpMessageBuilder.append("] ");
helpMessageBuilder.append("]");
}
else {
helpMessageBuilder.append(" ");
}
}
if (!arguments.isEmpty()) {
for (CommandArgument argument : arguments) {
helpMessageBuilder.append(" ");
boolean hasDefaultValue = StringUtils.hasText(argument.defaultValue());
if (hasDefaultValue) {
helpMessageBuilder.append("[");
}
helpMessageBuilder.append("(").append(argument.type().getSimpleName()).append(")");
if (hasDefaultValue) {
helpMessageBuilder.append("]");
}
}
}
helpMessageBuilder.append("--help\n\n");
helpMessageBuilder.append(" ").append("--help\n\n");
}

private void appendOptions(Command command, StringBuilder helpMessageBuilder) {
Expand Down Expand Up @@ -139,6 +153,27 @@ private void appendOptions(Command command, StringBuilder helpMessageBuilder) {
helpMessageBuilder.append("\t").append("[Optional]").append("\n").append("\n");
}

private void appendArguments(Command command, StringBuilder helpMessageBuilder) {
List<CommandArgument> arguments = command.getArguments();
if (!arguments.isEmpty()) {
helpMessageBuilder.append("ARGUMENTS [Positional]\n");
int index = 0;
for (CommandArgument argument : arguments) {
helpMessageBuilder.append("\t");
helpMessageBuilder.append("[Index ").append(index++).append("]");
helpMessageBuilder.append(" ").append(argument.type().getSimpleName()).append("\n");
helpMessageBuilder.append("\t").append(argument.description()).append("\n");
String defaultValue = argument.defaultValue();
helpMessageBuilder.append("\t").append("[default = ");
Class<?> optionType = argument.type();
if (defaultValue == null && optionType.isPrimitive()) {
defaultValue = Utils.getDefaultValueForPrimitiveType(optionType).toString();
}
helpMessageBuilder.append(defaultValue).append("]\n\n");
}
}
}

private static void appendAliases(Command command, StringBuilder helpMessageBuilder) {
List<String> aliases = command.getAliases();
if (!aliases.isEmpty()) {
Expand Down
Loading
Loading