diff options
author | jeremysolarz <jeremy.solarz@gmail.com> | 2017-03-05 16:58:46 +0100 |
---|---|---|
committer | jeremysolarz <jeremy.solarz@gmail.com> | 2017-03-05 16:58:46 +0100 |
commit | 8c25c4b2e63cf09f677813c22b380f480d416dbe (patch) | |
tree | da6f76c0862a20a9b8ff4d1ee7b70ddc793a2174 /src/main/java/com/beust/jcommander/JCommander.java | |
parent | 277dfcbcf823cc658654e04e7e7fec8ab3808fd1 (diff) | |
parent | 4b75f129a2247c8259d2129aa08d8a662af8ca9b (diff) | |
download | jcommander-8c25c4b2e63cf09f677813c22b380f480d416dbe.tar.gz |
Merge remote-tracking branch 'upstream/master' into dash-dash-dash-dash-dash-dash
Diffstat (limited to 'src/main/java/com/beust/jcommander/JCommander.java')
-rw-r--r-- | src/main/java/com/beust/jcommander/JCommander.java | 583 |
1 files changed, 360 insertions, 223 deletions
diff --git a/src/main/java/com/beust/jcommander/JCommander.java b/src/main/java/com/beust/jcommander/JCommander.java index c9c326c..ac28cca 100644 --- a/src/main/java/com/beust/jcommander/JCommander.java +++ b/src/main/java/com/beust/jcommander/JCommander.java @@ -18,42 +18,20 @@ package com.beust.jcommander; +import com.beust.jcommander.FuzzyMap.IKey; +import com.beust.jcommander.converters.*; +import com.beust.jcommander.internal.*; + import java.io.BufferedReader; import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; +import java.lang.reflect.*; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.EnumSet; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; +import java.util.*; import java.util.ResourceBundle; import java.util.concurrent.CopyOnWriteArrayList; -import com.beust.jcommander.FuzzyMap.IKey; -import com.beust.jcommander.converters.DefaultListConverter; -import com.beust.jcommander.converters.EnumConverter; -import com.beust.jcommander.converters.IParameterSplitter; -import com.beust.jcommander.converters.NoConverter; -import com.beust.jcommander.converters.StringConverter; -import com.beust.jcommander.internal.Console; -import com.beust.jcommander.internal.DefaultConsole; -import com.beust.jcommander.internal.DefaultConverterFactory; -import com.beust.jcommander.internal.JDK6Console; -import com.beust.jcommander.internal.Lists; -import com.beust.jcommander.internal.Maps; -import com.beust.jcommander.internal.Nullable; - /** * The main class for JCommander. It's responsible for parsing the object that contains * all the annotated fields, parse the command line and assign the fields with the correct @@ -72,32 +50,32 @@ public class JCommander { /** * A map to look up parameter description per option name. */ - private Map<IKey, ParameterDescription> m_descriptions; + private Map<IKey, ParameterDescription> descriptions; /** * The objects that contain fields annotated with @Parameter. */ - private List<Object> m_objects = Lists.newArrayList(); + private List<Object> objects = Lists.newArrayList(); - private boolean m_firstTimeMainParameter = true; + private boolean firstTimeMainParameter = true; /** * This field/method will contain whatever command line parameter is not an option. * It is expected to be a List<String>. */ - private Parameterized m_mainParameter = null; + private Parameterized mainParameter = null; /** * The object on which we found the main parameter field. */ - private Object m_mainParameterObject; + private Object mainParameterObject; /** * The annotation found on the main parameter field. */ - private Parameter m_mainParameterAnnotation; + private Parameter mainParameterAnnotation; - private ParameterDescription m_mainParameterDescription; + private ParameterDescription mainParameterDescription; /** * A set of all the parameterizeds that are required. During the reflection phase, @@ -107,17 +85,17 @@ public class JCommander { * then some required fields did not receive a value and an exception is * thrown. */ - private Map<Parameterized, ParameterDescription> m_requiredFields = Maps.newHashMap(); + private Map<Parameterized, ParameterDescription> requiredFields = Maps.newHashMap(); /** * A map of all the parameterized fields/methods. */ - private Map<Parameterized, ParameterDescription> m_fields = Maps.newHashMap(); + private Map<Parameterized, ParameterDescription> fields = Maps.newHashMap(); /** * List of commands and their instance. */ - private Map<ProgramName, JCommander> m_commands = Maps.newLinkedHashMap(); + private Map<ProgramName, JCommander> commands = Maps.newLinkedHashMap(); /** * Alias database for reverse lookup @@ -127,21 +105,21 @@ public class JCommander { /** * The name of the command after the parsing has run. */ - private String m_parsedCommand; + private String parsedCommand; /** * The name of command or alias as it was passed to the * command line */ - private String m_parsedAlias; + private String parsedAlias; - private ProgramName m_programName; + private ProgramName programName; - private boolean m_helpWasSpecified; + private boolean helpWasSpecified; - private List<String> m_unknownArgs = Lists.newArrayList(); + private List<String> unknownArgs = Lists.newArrayList(); - private static Console m_console; + private static Console console; private final Options options; @@ -150,32 +128,42 @@ public class JCommander { */ private static class Options { - private ResourceBundle m_bundle; + private ResourceBundle bundle; /** * A default provider returns default values for the parameters. */ - private IDefaultProvider m_defaultProvider; + private IDefaultProvider defaultProvider; - private Comparator<? super ParameterDescription> m_parameterDescriptionComparator + private Comparator<? super ParameterDescription> parameterDescriptionComparator = new Comparator<ParameterDescription>() { @Override public int compare(ParameterDescription p0, ParameterDescription p1) { - return p0.getLongestName().compareTo(p1.getLongestName()); + Parameter a0 = p0.getParameterAnnotation(); + Parameter a1 = p1.getParameterAnnotation(); + if (a0 != null && a0.order() != -1 && a1 != null && a1.order() != -1) { + return Integer.compare(a0.order(), a1.order()); + } else if (a0 != null && a0.order() != -1) { + return -1; + } else if (a1 != null && a1.order() != -1) { + return 1; + } else { + return p0.getLongestName().compareTo(p1.getLongestName()); + } } }; - private int m_columnSize = 79; - private boolean m_acceptUnknownOptions = false; - private boolean m_allowParameterOverwriting = false; + private int columnSize = 79; + private boolean acceptUnknownOptions = false; + private boolean allowParameterOverwriting = false; private boolean expandAtSign = true; - private int m_verbose = 0; - private boolean m_caseSensitiveOptions = true; - private boolean m_allowAbbreviatedOptions = false; + private int verbose = 0; + private boolean caseSensitiveOptions = true; + private boolean allowAbbreviatedOptions = false; /** * The factories used to look up string converters. */ - private final List<IStringConverterInstanceFactory> m_converterInstanceFactories = new CopyOnWriteArrayList<>(); - private Charset m_atFileCharset = Charset.defaultCharset(); + private final List<IStringConverterInstanceFactory> converterInstanceFactories = new CopyOnWriteArrayList<>(); + private Charset atFileCharset = Charset.defaultCharset(); } private JCommander(Options options) { @@ -237,24 +225,24 @@ public class JCommander { /** * Disables expanding {@code @file}. * - * JCommander supports the {@code @file} syntax, which allows you to put all your options into a file and pass this file as parameter - * @param expandAtSign whether to expand {@code @file}. + * JCommander supports the {@code @file} syntax, which allows you to put all your options + * into a file and pass this file as parameter @param expandAtSign whether to expand {@code @file}. */ public void setExpandAtSign(boolean expandAtSign) { options.expandAtSign = expandAtSign; } public static Console getConsole() { - if (m_console == null) { + if (console == null) { try { Method consoleMethod = System.class.getDeclaredMethod("console"); Object console = consoleMethod.invoke(null); - m_console = new JDK6Console(console); + JCommander.console = new JDK6Console(console); } catch (Throwable t) { - m_console = new DefaultConsole(); + console = new DefaultConsole(); } } - return m_console; + return console; } /** @@ -270,16 +258,16 @@ public class JCommander { if (object instanceof Iterable) { // Iterable for (Object o : (Iterable<?>) object) { - m_objects.add(o); + objects.add(o); } } else if (object.getClass().isArray()) { // Array for (Object o : (Object[]) object) { - m_objects.add(o); + objects.add(o); } } else { // Single object - m_objects.add(object); + objects.add(object); } } @@ -289,7 +277,7 @@ public class JCommander { */ // declared final since this is invoked from constructors public final void setDescriptionsBundle(ResourceBundle bundle) { - options.m_bundle = bundle; + options.bundle = bundle; } /** @@ -308,10 +296,10 @@ public class JCommander { private void parse(boolean validate, String... args) { StringBuilder sb = new StringBuilder("Parsing \""); - sb.append(join(args).append("\"\n with:").append(join(m_objects.toArray()))); + sb.append(join(args).append("\"\n with:").append(join(objects.toArray()))); p(sb.toString()); - if (m_descriptions == null) createDescriptions(); + if (descriptions == null) createDescriptions(); initializeDefaultValues(); parseValues(expandArgs(args), validate); if (validate) validateOptions(); @@ -327,12 +315,12 @@ public class JCommander { } private void initializeDefaultValues() { - if (options.m_defaultProvider != null) { - for (ParameterDescription pd : m_descriptions.values()) { + if (options.defaultProvider != null) { + for (ParameterDescription pd : descriptions.values()) { initializeDefaultValue(pd); } - for (Map.Entry<ProgramName, JCommander> entry : m_commands.entrySet()) { + for (Map.Entry<ProgramName, JCommander> entry : commands.entrySet()) { entry.getValue().initializeDefaultValues(); } } @@ -343,25 +331,25 @@ public class JCommander { */ private void validateOptions() { // No validation if we found a help parameter - if (m_helpWasSpecified) { + if (helpWasSpecified) { return; } - if (!m_requiredFields.isEmpty()) { + if (!requiredFields.isEmpty()) { StringBuilder missingFields = new StringBuilder(); - for (ParameterDescription pd : m_requiredFields.values()) { + for (ParameterDescription pd : requiredFields.values()) { missingFields.append(pd.getNames()).append(" "); } throw new ParameterException("The following " - + pluralize(m_requiredFields.size(), "option is required: ", "options are required: ") + + pluralize(requiredFields.size(), "option is required: ", "options are required: ") + missingFields); } - if (m_mainParameterDescription != null) { - if (m_mainParameterDescription.getParameter().required() && - !m_mainParameterDescription.isAssigned()) { + if (mainParameterDescription != null) { + if (mainParameterDescription.getParameter().required() && + !mainParameterDescription.isAssigned()) { throw new ParameterException("Main parameters are required (\"" - + m_mainParameterDescription.getDescription() + "\")"); + + mainParameterDescription.getDescription() + "\")"); } } } @@ -418,7 +406,7 @@ public class JCommander { } private List<String> expandDynamicArg(String arg) { - for (ParameterDescription pd : m_descriptions.values()) { + for (ParameterDescription pd : descriptions.values()) { if (pd.isDynamicParameter()) { for (String name : pd.getParameter().names()) { if (arg.startsWith(name) && !arg.equals(name)) { @@ -431,13 +419,48 @@ public class JCommander { return Arrays.asList(arg); } - private boolean isOption(String arg) { - String prefixes = getOptionPrefixes(arg); - return arg.length() > 0 && prefixes.indexOf(arg.charAt(0)) >= 0; + private boolean matchArg(String arg, IKey key) { + String kn = options.caseSensitiveOptions + ? key.getName() + : key.getName().toLowerCase(); + if (options.allowAbbreviatedOptions) { + if (kn.startsWith(arg)) return true; + } else { + ParameterDescription pd = descriptions.get(key); + if (pd != null) { + // It's an option. If the option has a separator (e.g. -author==foo) then + // we only do a beginsWith match + String separator = getSeparatorFor(arg); + if (! " ".equals(separator)) { + if (arg.startsWith(kn)) return true; + } else { + if (kn.equals(arg)) return true; + } + } else { + // It's a command do a strict equality check + if (kn.equals(arg)) return true; + } + } + return false; + } + + private boolean isOption(String passedArg) { + if (options.acceptUnknownOptions) return true; + + String arg = options.caseSensitiveOptions ? passedArg : passedArg.toLowerCase(); + + for (IKey key : descriptions.keySet()) { + if (matchArg(arg, key)) return true; + } + for (IKey key : commands.keySet()) { + if (matchArg(arg, key)) return true; + } + + return false; } private ParameterDescription getPrefixDescriptionFor(String arg) { - for (Map.Entry<IKey, ParameterDescription> es : m_descriptions.entrySet()) { + for (Map.Entry<IKey, ParameterDescription> es : descriptions.entrySet()) { if (arg.startsWith(es.getKey().getName())) return es.getValue(); } @@ -464,33 +487,6 @@ public class JCommander { return " "; } - private String getOptionPrefixes(String arg) { - ParameterDescription pd = getDescriptionFor(arg); - - // Could be null if only main parameters were passed - if (pd != null) { - Parameters p = pd.getObject().getClass() - .getAnnotation(Parameters.class); - if (p != null) return p.optionPrefixes(); - } - String result = Parameters.DEFAULT_OPTION_PREFIXES; - - // See if any of the objects contains a @Parameters(optionPrefixes) - StringBuilder sb = new StringBuilder(); - for (Object o : m_objects) { - Parameters p = o.getClass().getAnnotation(Parameters.class); - if (p != null && !Parameters.DEFAULT_OPTION_PREFIXES.equals(p.optionPrefixes())) { - sb.append(p.optionPrefixes()); - } - } - - if (!Strings.isStringEmpty(sb.toString())) { - result = sb.toString(); - } - - return result; - } - /** * Reads the file specified by filename and returns the file content as a string. * End of lines are replaced by a space. @@ -501,7 +497,7 @@ public class JCommander { private List<String> readFile(String fileName) { List<String> result = Lists.newArrayList(); - try (BufferedReader bufRead = Files.newBufferedReader(Paths.get(fileName), options.m_atFileCharset)) { + try (BufferedReader bufRead = Files.newBufferedReader(Paths.get(fileName), options.atFileCharset)) { String line; // Read through file one line at time. Print line # and line while ((line = bufRead.readLine()) != null) { @@ -532,9 +528,9 @@ public class JCommander { * Create the ParameterDescriptions for all the \@Parameter found. */ private void createDescriptions() { - m_descriptions = Maps.newHashMap(); + descriptions = Maps.newHashMap(); - for (Object object : m_objects) { + for (Object object : objects) { addDescription(object); } } @@ -553,27 +549,27 @@ public class JCommander { Parameter p = annotation; if (p.names().length == 0) { p("Found main parameter:" + parameterized); - if (m_mainParameter != null) { + if (mainParameter != null) { throw new ParameterException("Only one @Parameter with no names attribute is" - + " allowed, found:" + m_mainParameter + " and " + parameterized); + + " allowed, found:" + mainParameter + " and " + parameterized); } - m_mainParameter = parameterized; - m_mainParameterObject = object; - m_mainParameterAnnotation = p; - m_mainParameterDescription = - new ParameterDescription(object, p, parameterized, options.m_bundle, this); + mainParameter = parameterized; + mainParameterObject = object; + mainParameterAnnotation = p; + mainParameterDescription = + new ParameterDescription(object, p, parameterized, options.bundle, this); } else { ParameterDescription pd = - new ParameterDescription(object, p, parameterized, options.m_bundle, this); + new ParameterDescription(object, p, parameterized, options.bundle, this); for (String name : p.names()) { - if (m_descriptions.containsKey(new StringKey(name))) { + if (descriptions.containsKey(new StringKey(name))) { throw new ParameterException("Found the option " + name + " multiple times"); } p("Adding description for " + name); - m_fields.put(parameterized, pd); - m_descriptions.put(new StringKey(name), pd); + fields.put(parameterized, pd); + descriptions.put(new StringKey(name), pd); - if (p.required()) m_requiredFields.put(parameterized, pd); + if (p.required()) requiredFields.put(parameterized, pd); } } } else if (parameterized.getDelegateAnnotation() != null) { @@ -592,16 +588,16 @@ public class JCommander { // DynamicParameter dp = wp.getDynamicParameter(); for (String name : dp.names()) { - if (m_descriptions.containsKey(name)) { + if (descriptions.containsKey(name)) { throw new ParameterException("Found the option " + name + " multiple times"); } p("Adding description for " + name); ParameterDescription pd = - new ParameterDescription(object, dp, parameterized, options.m_bundle, this); - m_fields.put(parameterized, pd); - m_descriptions.put(new StringKey(name), pd); + new ParameterDescription(object, dp, parameterized, options.bundle, this); + fields.put(parameterized, pd); + descriptions.put(new StringKey(name), pd); - if (dp.required()) m_requiredFields.put(parameterized, pd); + if (dp.required()) requiredFields.put(parameterized, pd); } } } @@ -609,12 +605,12 @@ public class JCommander { private void initializeDefaultValue(ParameterDescription pd) { for (String optionName : pd.getParameter().names()) { - String def = options.m_defaultProvider.getDefaultValueFor(optionName); + String def = options.defaultProvider.getDefaultValueFor(optionName); if (def != null) { p("Initializing " + optionName + " with default value:" + def); pd.addValue(def, true /* default */); // remove the parameter from the list of fields to be required - m_requiredFields.remove(pd.getParameterized()); + requiredFields.remove(pd.getParameterized()); return; } } @@ -623,7 +619,7 @@ public class JCommander { /** * Main method that parses the values and initializes the fields accordingly. */ - private void parseValues(final String[] args, final boolean validate) { + private void parseValues(String[] args, boolean validate) { // This boolean becomes true if we encounter a command, which indicates we need // to stop parsing (the parsing of the command will be done in a sub JCommander // object) @@ -651,7 +647,7 @@ public class JCommander { // char[] password = readPassword(pd.getDescription(), pd.getParameter().echoInput()); pd.addValue(new String(password)); - m_requiredFields.remove(pd.getParameterized()); + requiredFields.remove(pd.getParameterized()); } else { if (pd.getParameter().variableArity()) { // @@ -669,22 +665,22 @@ public class JCommander { if ((fieldType == boolean.class || fieldType == Boolean.class) && pd.getParameter().arity() == -1) { pd.addValue("true"); - m_requiredFields.remove(pd.getParameterized()); + requiredFields.remove(pd.getParameterized()); } else { increment = processFixedArity(args, i, pd, validate, fieldType); } // If it's a help option, remember for later if (pd.isHelp()) { - m_helpWasSpecified = true; + helpWasSpecified = true; } } } } else { - if (options.m_acceptUnknownOptions) { - m_unknownArgs.add(arg); + if (options.acceptUnknownOptions) { + unknownArgs.add(arg); i++; while (i < args.length && !isOption(args[i])) { - m_unknownArgs.add(args[i++]); + unknownArgs.add(args[i++]); } increment = 0; } else { @@ -698,7 +694,7 @@ public class JCommander { if ("--".equals(arg) && !isDashDash) { isDashDash = true; } - else if (m_commands.isEmpty()) { + else if (commands.isEmpty()) { // // Regular (non-command) parsing // @@ -706,19 +702,19 @@ public class JCommander { String value = a; // If there's a non-quoted version, prefer that one Object convertedValue = value; - if (m_mainParameter.getGenericType() instanceof ParameterizedType) { - ParameterizedType p = (ParameterizedType) m_mainParameter.getGenericType(); + if (mainParameter.getGenericType() instanceof ParameterizedType) { + ParameterizedType p = (ParameterizedType) mainParameter.getGenericType(); Type cls = p.getActualTypeArguments()[0]; if (cls instanceof Class) { - convertedValue = convertValue(m_mainParameter, (Class) cls, null, value); + convertedValue = convertValue(mainParameter, (Class) cls, null, value); } } - ParameterDescription.validateParameter(m_mainParameterDescription, - m_mainParameterAnnotation.validateWith(), + ParameterDescription.validateParameter(mainParameterDescription, + mainParameterAnnotation.validateWith(), "Default", value); - m_mainParameterDescription.setAssigned(true); + mainParameterDescription.setAssigned(true); mp.add(convertedValue); } else { // @@ -727,8 +723,8 @@ public class JCommander { if (jc == null && validate) { throw new MissingCommandException("Expected a command, got " + arg, arg); } else if (jc != null) { - m_parsedCommand = jc.m_programName.m_name; - m_parsedAlias = arg; //preserve the original form + parsedCommand = jc.programName.name; + parsedAlias = arg; //preserve the original form // Found a valid command, ask it to parse the remainder of the arguments. // Setting the boolean commandParsed to true will force the current @@ -741,10 +737,10 @@ public class JCommander { i += increment; } - // Mark the parameter descriptions held in m_fields as assigned - for (ParameterDescription parameterDescription : m_descriptions.values()) { + // Mark the parameter descriptions held in fields as assigned + for (ParameterDescription parameterDescription : descriptions.values()) { if (parameterDescription.isAssigned()) { - m_fields.get(parameterDescription.getParameterized()).setAssigned(true); + fields.get(parameterDescription.getParameterized()).setAssigned(true); } } @@ -806,15 +802,20 @@ public class JCommander { (Boolean.class.isAssignableFrom(fieldType) || boolean.class.isAssignableFrom(fieldType))) { pd.addValue("true"); - m_requiredFields.remove(pd.getParameterized()); + requiredFields.remove(pd.getParameterized()); } else if (index < args.length - 1) { int offset = "--".equals(args[index + 1]) ? 1 : 0; + Object finalValue = null; if (index + arity < args.length) { for (int j = 1; j <= arity; j++) { String value = trim(args[index + j + offset]); - pd.addValue(arg, value, false, validate); - m_requiredFields.remove(pd.getParameterized()); + finalValue = pd.addValue(arg, value, false, validate, j - 1); + requiredFields.remove(pd.getParameterized()); + } + + if (finalValue != null && validate) { + pd.validateValueParameter(arg, finalValue); } index += arity + offset; } else { @@ -851,30 +852,30 @@ public class JCommander { * error message). */ private List<?> getMainParameter(String arg) { - if (m_mainParameter == null) { + if (mainParameter == null) { throw new ParameterException( - "Was passed main parameter '" + arg + "' but no main parameter was defined"); + "Was passed main parameter '" + arg + "' but no main parameter was defined in your arg class"); } - List<?> result = (List<?>) m_mainParameter.get(m_mainParameterObject); + List<?> result = (List<?>) mainParameter.get(mainParameterObject); if (result == null) { result = Lists.newArrayList(); - if (!List.class.isAssignableFrom(m_mainParameter.getType())) { - throw new ParameterException("Main parameter field " + m_mainParameter - + " needs to be of type List, not " + m_mainParameter.getType()); + if (!List.class.isAssignableFrom(mainParameter.getType())) { + throw new ParameterException("Main parameter field " + mainParameter + + " needs to be of type List, not " + mainParameter.getType()); } - m_mainParameter.set(m_mainParameterObject, result); + mainParameter.set(mainParameterObject, result); } - if (m_firstTimeMainParameter) { + if (firstTimeMainParameter) { result.clear(); - m_firstTimeMainParameter = false; + firstTimeMainParameter = false; } return result; } public String getMainParameterDescription() { - if (m_descriptions == null) createDescriptions(); - return m_mainParameterAnnotation != null ? m_mainParameterAnnotation.description() + if (descriptions == null) createDescriptions(); + return mainParameterAnnotation != null ? mainParameterAnnotation.description() : null; } @@ -886,13 +887,20 @@ public class JCommander { } /** + * Get the program name (used only in the usage). + */ + public String getProgramName(){ + return programName == null ? null : programName.getName(); + } + + /** * Set the program name * * @param name program name * @param aliases aliases to the program name */ public void setProgramName(String name, String... aliases) { - m_programName = new ProgramName(name, Arrays.asList(aliases)); + programName = new ProgramName(name, Arrays.asList(aliases)); } /** @@ -944,7 +952,7 @@ public class JCommander { if (!"".equals(bundleName)) { bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault()); } else { - bundle = options.m_bundle; + bundle = options.bundle; } if (bundle != null) { @@ -976,6 +984,134 @@ public class JCommander { getConsole().println(sb.toString()); } + public static Builder newBuilder() { + return new Builder(); + } + + static class Builder { + private JCommander jCommander = new JCommander(); + private String[] args = null; + + public Builder() { + } + + /** + * Adds the provided arg object to the set of objects that this commander + * will parse arguments into. + * + * @param o The arg object expected to contain {@link Parameter} + * annotations. If <code>object</code> is an array or is {@link Iterable}, + * the child objects will be added instead. + */ + public Builder addObject(Object o) { + jCommander.addObject(o); + return this; + } + + /** + * Sets the {@link ResourceBundle} to use for looking up descriptions. + * Set this to <code>null</code> to use description text directly. + */ + public Builder resourceBundle(ResourceBundle bundle) { + jCommander.setDescriptionsBundle(bundle); + return this; + } + + public Builder args(String[] args) { + this.args = args; + return this; + } + + /** + * Disables expanding {@code @file}. + * + * JCommander supports the {@code @file} syntax, which allows you to put all your options + * into a file and pass this file as parameter @param expandAtSign whether to expand {@code @file}. + */ + public Builder expandAtSign(Boolean expand) { + jCommander.setExpandAtSign(expand); + return this; + } + + /** + * Set the program name (used only in the usage). + */ + public Builder programName(String name) { + jCommander.setProgramName(name); + return this; + } + + public Builder columnSize(int columnSize) { + jCommander.setColumnSize(columnSize); + return this; + } + + /** + * Define the default provider for this instance. + */ + public Builder defaultProvider(IDefaultProvider provider) { + jCommander.setDefaultProvider(provider); + return this; + } + + /** + * Adds a factory to lookup string converters. The added factory is used prior to previously added factories. + * @param factory the factory determining string converters + */ + public Builder addConverterFactory(IStringConverterFactory factory) { + jCommander.addConverterFactory(factory); + return this; + } + + public Builder verbose(int verbose) { + jCommander.setVerbose(verbose); + return this; + } + + public Builder allowAbbreviatedOptions(boolean b) { + jCommander.setAllowAbbreviatedOptions(b); + return this; + } + + public Builder acceptUnknownOptions(boolean b) { + jCommander.setAcceptUnknownOptions(b); + return this; + } + + public Builder allowParameterOverwriting(boolean b) { + jCommander.setAllowParameterOverwriting(b); + return this; + } + + public Builder atFileCharset(Charset charset) { + jCommander.setAtFileCharset(charset); + return this; + } + + public Builder addConverterInstanceFactory(IStringConverterInstanceFactory factory) { + jCommander.addConverterInstanceFactory(factory); + return this; + } + + public Builder addCommand(Object command) { + jCommander.addCommand(command); + return this; + } + + public Builder addCommand(String name, Object command, String... aliases) { + jCommander.addCommand(name, command, aliases); + return this; + } + + public JCommander build() { + if (args != null) { + jCommander.parse(args); + } + return jCommander; + } + } + + /** * Store the help in the passed string builder. */ @@ -984,8 +1120,9 @@ public class JCommander { } public void usage(StringBuilder out, String indent) { - if (m_descriptions == null) createDescriptions(); - boolean hasCommands = !m_commands.isEmpty(); + if (descriptions == null) createDescriptions(); + boolean hasCommands = !commands.isEmpty(); + boolean hasOptions = !descriptions.isEmpty(); //indenting int descriptionIndent = 6; @@ -994,12 +1131,13 @@ public class JCommander { // // First line of the usage // - String programName = m_programName != null ? m_programName.getDisplayName() : "<main class>"; + String programName = this.programName != null ? this.programName.getDisplayName() : "<main class>"; StringBuilder mainLine = new StringBuilder(); - mainLine.append(indent).append("Usage: ").append(programName).append(" [options]"); + mainLine.append(indent).append("Usage: ").append(programName); + if (hasOptions) mainLine.append(" [options]"); if (hasCommands) mainLine.append(indent).append(" [command] [command options]"); - if (m_mainParameterDescription != null) { - mainLine.append(" ").append(m_mainParameterDescription.getDescription()); + if (mainParameterDescription != null) { + mainLine.append(" ").append(mainParameterDescription.getDescription()); } wrapDescription(out, indentCount, mainLine.toString()); out.append("\n"); @@ -1009,7 +1147,7 @@ public class JCommander { // int longestName = 0; List<ParameterDescription> sorted = Lists.newArrayList(); - for (ParameterDescription pd : m_fields.values()) { + for (ParameterDescription pd : fields.values()) { if (!pd.getParameter().hidden()) { sorted.add(pd); // + to have an extra space between the name and the description @@ -1062,10 +1200,10 @@ public class JCommander { // If commands were specified, show them as well // if (hasCommands) { - out.append(" Commands:\n"); + out.append(indent + " Commands:\n"); // The magic value 3 is the number of spaces between the name of the option // and its description - for (Map.Entry<ProgramName, JCommander> commands : m_commands.entrySet()) { + for (Map.Entry<ProgramName, JCommander> commands : this.commands.entrySet()) { Object arg = commands.getValue().getObjects().get(0); Parameters p = arg.getClass().getAnnotation(Parameters.class); if (p == null || !p.hidden()) { @@ -1078,7 +1216,7 @@ public class JCommander { // Options for this command JCommander jc = findCommandByAlias(progName.getName()); - jc.usage(out, " "); + jc.usage(out, indent + " "); out.append("\n"); } } @@ -1086,19 +1224,19 @@ public class JCommander { } private Comparator<? super ParameterDescription> getParameterDescriptionComparator() { - return options.m_parameterDescriptionComparator; + return options.parameterDescriptionComparator; } public void setParameterDescriptionComparator(Comparator<? super ParameterDescription> c) { - options.m_parameterDescriptionComparator = c; + options.parameterDescriptionComparator = c; } public void setColumnSize(int columnSize) { - options.m_columnSize = columnSize; + options.columnSize = columnSize; } public int getColumnSize() { - return options.m_columnSize; + return options.columnSize; } /** @@ -1138,18 +1276,18 @@ public class JCommander { * format (e.g. HTML). */ public List<ParameterDescription> getParameters() { - return new ArrayList<>(m_fields.values()); + return new ArrayList<>(fields.values()); } /** * @return the main parameter description or null if none is defined. */ public ParameterDescription getMainParameter() { - return m_mainParameterDescription; + return mainParameterDescription; } private void p(String string) { - if (options.m_verbose > 0 || System.getProperty(JCommander.DEBUG_PROPERTY) != null) { + if (options.verbose > 0 || System.getProperty(JCommander.DEBUG_PROPERTY) != null) { getConsole().println("[JCommander] " + string); } } @@ -1158,7 +1296,7 @@ public class JCommander { * Define the default provider for this instance. */ public void setDefaultProvider(IDefaultProvider defaultProvider) { - options.m_defaultProvider = defaultProvider; + options.defaultProvider = defaultProvider; } /** @@ -1187,12 +1325,12 @@ public class JCommander { * Adds a factory to lookup string converters. The added factory is used prior to previously added factories. * @param converterInstanceFactory the factory generating string converter instances */ - public void addConverterInstanceFactory(final IStringConverterInstanceFactory converterInstanceFactory) { - options.m_converterInstanceFactories.add(0, converterInstanceFactory); + public void addConverterInstanceFactory(IStringConverterInstanceFactory converterInstanceFactory) { + options.converterInstanceFactories.add(0, converterInstanceFactory); } private IStringConverter<?> findConverterInstance(Parameter parameter, Class<?> forType, String optionName) { - for (IStringConverterInstanceFactory f : options.m_converterInstanceFactories) { + for (IStringConverterInstanceFactory f : options.converterInstanceFactories) { IStringConverter<?> result = f.getConverterInstance(parameter, forType, optionName); if (result != null) return result; } @@ -1307,8 +1445,8 @@ public class JCommander { jc.addObject(object); jc.createDescriptions(); jc.setProgramName(name, aliases); - ProgramName progName = jc.m_programName; - m_commands.put(progName, jc); + ProgramName progName = jc.programName; + commands.put(progName, jc); /* * Register aliases @@ -1327,7 +1465,7 @@ public class JCommander { throw new ParameterException("Cannot set alias " + alias + " for " + name + " command because it has already been defined for " - + mappedName.m_name + " command"); + + mappedName.name + " command"); } aliasMap.put(alias, progName); } @@ -1336,14 +1474,14 @@ public class JCommander { public Map<String, JCommander> getCommands() { Map<String, JCommander> res = Maps.newLinkedHashMap(); - for (Map.Entry<ProgramName, JCommander> entry : m_commands.entrySet()) { - res.put(entry.getKey().m_name, entry.getValue()); + for (Map.Entry<ProgramName, JCommander> entry : commands.entrySet()) { + res.put(entry.getKey().name, entry.getValue()); } return res; } public String getParsedCommand() { - return m_parsedCommand; + return parsedCommand; } /** @@ -1354,7 +1492,7 @@ public class JCommander { * @return Name of command or alias passed to command line. If none passed: <code>null</code>. */ public String getParsedAlias() { - return m_parsedAlias; + return parsedAlias; } /** @@ -1374,22 +1512,22 @@ public class JCommander { * parsing the command line. */ public List<Object> getObjects() { - return m_objects; + return objects; } private ParameterDescription findParameterDescription(String arg) { - return FuzzyMap.findInMap(m_descriptions, new StringKey(arg), - options.m_caseSensitiveOptions, options.m_allowAbbreviatedOptions); + return FuzzyMap.findInMap(descriptions, new StringKey(arg), + options.caseSensitiveOptions, options.allowAbbreviatedOptions); } private JCommander findCommand(ProgramName name) { - return FuzzyMap.findInMap(m_commands, name, - options.m_caseSensitiveOptions, options.m_allowAbbreviatedOptions); + return FuzzyMap.findInMap(commands, name, + options.caseSensitiveOptions, options.allowAbbreviatedOptions); } private ProgramName findProgramName(String name) { return FuzzyMap.findInMap(aliasMap, new StringKey(name), - options.m_caseSensitiveOptions, options.m_allowAbbreviatedOptions); + options.caseSensitiveOptions, options.allowAbbreviatedOptions); } /* @@ -1413,25 +1551,25 @@ public class JCommander { * Encapsulation of either a main application or an individual command. */ private static final class ProgramName implements IKey { - private final String m_name; - private final List<String> m_aliases; + private final String name; + private final List<String> aliases; ProgramName(String name, List<String> aliases) { - m_name = name; - m_aliases = aliases; + this.name = name; + this.aliases = aliases; } @Override public String getName() { - return m_name; + return name; } private String getDisplayName() { StringBuilder sb = new StringBuilder(); - sb.append(m_name); - if (!m_aliases.isEmpty()) { + sb.append(name); + if (!aliases.isEmpty()) { sb.append("("); - Iterator<String> aliasesIt = m_aliases.iterator(); + Iterator<String> aliasesIt = aliases.iterator(); while (aliasesIt.hasNext()) { sb.append(aliasesIt.next()); if (aliasesIt.hasNext()) { @@ -1447,7 +1585,7 @@ public class JCommander { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((m_name == null) ? 0 : m_name.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @@ -1460,10 +1598,10 @@ public class JCommander { if (getClass() != obj.getClass()) return false; ProgramName other = (ProgramName) obj; - if (m_name == null) { - if (other.m_name != null) + if (name == null) { + if (other.name != null) return false; - } else if (!m_name.equals(other.m_name)) + } else if (!name.equals(other.name)) return false; return true; } @@ -1480,31 +1618,31 @@ public class JCommander { } public void setVerbose(int verbose) { - options.m_verbose = verbose; + options.verbose = verbose; } public void setCaseSensitiveOptions(boolean b) { - options.m_caseSensitiveOptions = b; + options.caseSensitiveOptions = b; } public void setAllowAbbreviatedOptions(boolean b) { - options.m_allowAbbreviatedOptions = b; + options.allowAbbreviatedOptions = b; } public void setAcceptUnknownOptions(boolean b) { - options.m_acceptUnknownOptions = b; + options.acceptUnknownOptions = b; } public List<String> getUnknownOptions() { - return m_unknownArgs; + return unknownArgs; } public void setAllowParameterOverwriting(boolean b) { - options.m_allowParameterOverwriting = b; + options.allowParameterOverwriting = b; } public boolean isParameterOverwritingAllowed() { - return options.m_allowParameterOverwriting; + return options.allowParameterOverwriting; } /** @@ -1512,8 +1650,7 @@ public class JCommander { * @param charset the charset */ public void setAtFileCharset(Charset charset) { - options.m_atFileCharset = charset; + options.atFileCharset = charset; } } - |