org.deephacks.tools4j.cli.GNUishParser Maven / Gradle / Ivy
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.deephacks.tools4j.cli;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
/**
* GNUishParser is responsible for parsing the command line arguments more or less
* according to the GNU Argument Syntax:
*
* http://www.gnu.org/s/hello/manual/libc/Argument-Syntax.html.
*
* Inspiration from http://commons.apache.org/cli
*/
final class GNUishParser {
private final Map shortOpts = new HashMap();
private final Map longOpts = new HashMap();
private final List arguments = new ArrayList();
private String command;
private static String VERBOSE_LONG_OPT = "verbose";
private static String DEBUG_LONG_OPT = "debug";
private static String HELP_LONG_OPT = "help";
private GNUishParser() {
}
static GNUishParser parse(String[] terminalArgs) {
final GNUishParser p = new GNUishParser();
if (terminalArgs == null || terminalArgs.length == 0) {
return p;
}
p.command = terminalArgs[0].trim();
terminalArgs = Arrays.copyOfRange(terminalArgs, 1, terminalArgs.length);
// we strip opts after parsing
terminalArgs = p.parseOpts(terminalArgs);
// arguments is what's left
p.arguments.addAll(Arrays.asList(terminalArgs));
return p;
}
/**
* Parse the options for the command.
*
* @param args includes the options and arguments, command word have been stripped.
* @return the remaining terminal args, if any
*/
private String[] parseOpts(String[] args) {
if (args == null || args.length == 0) {
return new String[0];
}
final List remainingArgs = new ArrayList();
final List argsList = Arrays.asList(args);
final ListIterator argsIt = argsList.listIterator();
while (argsIt.hasNext()) {
String word = argsIt.next();
if (word.startsWith("--")) {
// long option --foo
final String option = stripLeadingHyphens(word);
if (VERBOSE_LONG_OPT.equals(option)) {
longOpts.put(option, "true");
} else if (DEBUG_LONG_OPT.equals(option)) {
longOpts.put(option, "true");
} else if (HELP_LONG_OPT.equals(option)) {
longOpts.put(option, "true");
} else {
final String arg = parseOptionArg(option, argsIt);
longOpts.put(option, arg);
}
} else if (word.startsWith("-")) {
String options = stripLeadingHyphens(word);
// single short option -f
if (options.length() == 1) {
// only slurp argument if option is argumented
final String arg = parseOptionArg(options, argsIt);
shortOpts.put(options, arg);
continue;
}
// multiple short options -fxy,
// treat as non-argumented java.lang.Boolean variables, no slurp
for (int i = 0; i < options.length(); i++) {
final String option = Character.toString(options.charAt(i));
shortOpts.put(option, "true");
}
} else {
remainingArgs.add(word);
}
}
return remainingArgs.toArray(new String[0]);
}
private String parseOptionArg(String option, ListIterator argsIt) {
if (!argsIt.hasNext()) {
// no argument. assume boolean opt
return "true";
}
String arg = argsIt.next();
// the token following the option is a new option (not an argument)
if (arg.startsWith("-")) {
// arg was the next opt, take one step back
argsIt.previous();
// assume argument for opt is a boolean
arg = "true";
}
return arg;
}
private static String stripLeadingHyphens(String str) {
if (str == null) {
return null;
}
if (str.startsWith("--")) {
return str.substring(2, str.length());
} else if (str.startsWith("-")) {
return str.substring(1, str.length());
}
return str;
}
String getCommand() {
return command;
}
List getArgs() {
return arguments;
}
Map getShortOpts() {
return shortOpts;
}
String getShortOpt(String id) {
return shortOpts.get(id);
}
Map getLongOpts() {
return longOpts;
}
String getLongOpt(String id) {
return longOpts.get(id);
}
public static List getReservedNonArgumentOptions() {
return Arrays.asList(VERBOSE_LONG_OPT, DEBUG_LONG_OPT, HELP_LONG_OPT);
}
public boolean verbose() {
if (getLongOpt(VERBOSE_LONG_OPT) != null) {
return true;
}
return false;
}
public boolean debug() {
if (getLongOpt(DEBUG_LONG_OPT) != null) {
return true;
}
return false;
}
public boolean help() {
if (getLongOpt(HELP_LONG_OPT) != null) {
return true;
}
return false;
}
}