Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix for issue #22 #23

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
45 changes: 25 additions & 20 deletions src/main/java/io/airlift/command/Cli.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import io.airlift.command.model.ArgumentsMetadata;
import io.airlift.command.model.CommandGroupMetadata;
import io.airlift.command.model.CommandMetadata;
import io.airlift.command.model.GlobalMetadata;
import io.airlift.command.model.MetadataLoader;
import io.airlift.command.model.OptionMetadata;
import io.airlift.command.model.*;

import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -129,6 +124,7 @@ public C parse(Iterable<String> args)
private void validate(ParseState state)
{
CommandMetadata command = state.getCommand();

if (command == null) {
List<String> unparsedInput = state.getUnparsedInput();
if (unparsedInput.isEmpty()) {
Expand All @@ -139,23 +135,32 @@ private void validate(ParseState state)
}
}

ArgumentsMetadata arguments = command.getArguments();
if (state.getParsedArguments().isEmpty() && arguments != null && arguments.isRequired()) {
throw new ParseArgumentsMissingException(arguments.getTitle());
}

if (!state.getUnparsedInput().isEmpty()) {
throw new ParseArgumentsUnexpectedException(state.getUnparsedInput());
}
try{
ArgumentsMetadata arguments = command.getArguments();
if (state.getParsedArguments().isEmpty() && arguments != null && arguments.isRequired()) {
throw new ParseArgumentsMissingException(arguments.getTitle());
}

if (state.getLocation() == Context.OPTION) {
throw new ParseOptionMissingValueException(state.getCurrentOption().getTitle());
}
if (!state.getUnparsedInput().isEmpty()) {
throw new ParseArgumentsUnexpectedException(state.getUnparsedInput());
}

for (OptionMetadata option : command.getAllOptions()) {
if (option.isRequired() && !state.getParsedOptions().containsKey(option)) {
throw new ParseOptionMissingException(option.getOptions().iterator().next());
if (state.getLocation() == Context.OPTION) {
throw new ParseOptionMissingValueException(state.getCurrentOption().getTitle());
}

for (OptionMetadata option : command.getAllOptions()) {
if (option.isRequired() && !state.getParsedOptions().containsKey(option)) {
throw new ParseOptionMissingException(option.getOptions().iterator().next());
}
}
}catch(ParseException e){
if(command.isShowHelpOnError()){
System.out.println(e.getMessage());
System.out.println("Usage:");
Help.help(command);
}
throw e;
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/main/java/io/airlift/command/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,9 @@
* If true, this command won't appear in the usage().
*/
boolean hidden() default false;

/**
* If true, the help will be shown if the command line arguments cannot be parsed correctly.
*/
boolean showHelpOnError() default true;
}
44 changes: 27 additions & 17 deletions src/main/java/io/airlift/command/SingleCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ public C parse(String... args)
{
return parse(ImmutableList.copyOf(args));
}

public C parse(Iterable<String> args)
{
checkNotNull(args, "args is null");

Parser parser = new Parser();
ParseState state = parser.parseCommand(commandMetadata, args);
validate(state);
Expand All @@ -74,10 +74,11 @@ public C parse(Iterable<String> args)
command.getMetadataInjections(),
ImmutableMap.<Class<?>, Object>of(CommandMetadata.class, commandMetadata));
}

private void validate(ParseState state)
{
CommandMetadata command = state.getCommand();

if (command == null) {
List<String> unparsedInput = state.getUnparsedInput();
if (unparsedInput.isEmpty()) {
Expand All @@ -88,23 +89,32 @@ private void validate(ParseState state)
}
}

ArgumentsMetadata arguments = command.getArguments();
if (state.getParsedArguments().isEmpty() && arguments != null && arguments.isRequired()) {
throw new ParseArgumentsMissingException(arguments.getTitle());
}

if (!state.getUnparsedInput().isEmpty()) {
throw new ParseArgumentsUnexpectedException(state.getUnparsedInput());
}
try{
ArgumentsMetadata arguments = command.getArguments();
if (state.getParsedArguments().isEmpty() && arguments != null && arguments.isRequired()) {
throw new ParseArgumentsMissingException(arguments.getTitle());
}

if (state.getLocation() == Context.OPTION) {
throw new ParseOptionMissingValueException(state.getCurrentOption().getTitle());
}
if (!state.getUnparsedInput().isEmpty()) {
throw new ParseArgumentsUnexpectedException(state.getUnparsedInput());
}

for (OptionMetadata option : command.getAllOptions()) {
if (option.isRequired() && !state.getParsedOptions().containsKey(option)) {
throw new ParseOptionMissingException(option.getOptions().iterator().next());
if (state.getLocation() == Context.OPTION) {
throw new ParseOptionMissingValueException(state.getCurrentOption().getTitle());
}

for (OptionMetadata option : command.getAllOptions()) {
if (option.isRequired() && !state.getParsedOptions().containsKey(option)) {
throw new ParseOptionMissingException(option.getOptions().iterator().next());
}
}
}catch(ParseException e){
if(command.isShowHelpOnError()){
System.out.println(e.getMessage());
System.out.println("Usage:");
Help.help(command);
}
throw e;
}
}
}
9 changes: 7 additions & 2 deletions src/main/java/io/airlift/command/model/CommandMetadata.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.google.common.collect.ImmutableList;
import io.airlift.command.Accessor;

import javax.annotation.Nullable;
import java.util.List;

public class CommandMetadata
Expand All @@ -18,6 +17,7 @@ public class CommandMetadata
private final ArgumentsMetadata arguments;
private final List<Accessor> metadataInjections;
private final Class<?> type;
private final boolean showHelpOnError;

public CommandMetadata(String name,
String description,
Expand All @@ -26,7 +26,7 @@ public CommandMetadata(String name,
Iterable<OptionMetadata> commandOptions,
ArgumentsMetadata arguments,
Iterable<Accessor> metadataInjections,
Class<?> type)
Class<?> type, boolean showHelpOnError)
{
this.name = name;
this.description = description;
Expand All @@ -37,6 +37,7 @@ public CommandMetadata(String name,
this.arguments = arguments;
this.metadataInjections = ImmutableList.copyOf(metadataInjections);
this.type = type;
this.showHelpOnError = showHelpOnError;
}

public String getName()
Expand Down Expand Up @@ -117,4 +118,8 @@ public String apply(CommandMetadata input)
}
};
}

public boolean isShowHelpOnError() {
return showHelpOnError;
}
}
10 changes: 3 additions & 7 deletions src/main/java/io/airlift/command/model/MetadataLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import io.airlift.command.Accessor;
import io.airlift.command.Arguments;
import io.airlift.command.Command;
import io.airlift.command.Option;
import io.airlift.command.OptionType;
import io.airlift.command.Suggester;
import io.airlift.command.*;

import javax.annotation.Nullable;
import javax.inject.Inject;
Expand Down Expand Up @@ -82,6 +77,7 @@ public static CommandMetadata loadCommand(Class<?> commandType)
String name = command.name();
String description = command.description().isEmpty() ? null : command.description();
boolean hidden = command.hidden();
boolean showHelpOnError = command.showHelpOnError();

InjectionMetadata injectionMetadata = loadInjectionMetadata(commandType);

Expand All @@ -93,7 +89,7 @@ public static CommandMetadata loadCommand(Class<?> commandType)
injectionMetadata.commandOptions,
Iterables.getFirst(injectionMetadata.arguments, null),
injectionMetadata.metadataInjections,
commandType);
commandType, showHelpOnError);

return commandMetadata;

Expand Down
33 changes: 33 additions & 0 deletions src/test/java/io/airlift/command/PingWithRequiredOption.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.airlift.command;

import javax.inject.Inject;

@Command(name = "ping", description = "network test utility")
public class PingWithRequiredOption
{
@Inject
public HelpOption helpOption;

@Option(name = {"-c", "--count"}, required=true, description = "Send count packets")
public int count = 1;

public static void main(String... args)
{
try{
PingWithRequiredOption ping = SingleCommand.singleCommand(PingWithRequiredOption.class).parse(args);
if (ping.helpOption.showHelpIfRequested()) {
return;
}

ping.run();
}catch(ParseException e){
System.out.println(e.getMessage());
return;
}
}

public void run()
{
System.out.println("Ping count: " + count);
}
}
21 changes: 21 additions & 0 deletions src/test/java/io/airlift/command/PingWithRequiredOptionTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.airlift.command;

import com.google.common.base.Joiner;
import org.testng.annotations.Test;

public class PingWithRequiredOptionTest {

@Test
public void test()
{
// missing parameter => show help
ping();
}

private void ping(String... args)
{
System.out.println("$ ping " + Joiner.on(' ').join(args));
PingWithRequiredOption.main(args);
System.out.println();
}
}