Home | History | Annotate | Download | only in options
      1 // Copyright 2014 The Bazel Authors. All rights reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //    http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 package com.google.devtools.common.options;
     16 
     17 import com.google.devtools.common.options.OptionsParser.ConstructionException;
     18 import java.util.Arrays;
     19 import java.util.List;
     20 
     21 /**
     22  * Interface for parsing options from a single options specification class.
     23  *
     24  * The {@link Options#parse(Class, String...)} method in this class has no clear
     25  * use case. Instead, use the {@link OptionsParser} class directly, as in this
     26  * code snippet:
     27  *
     28  * <pre>
     29  * OptionsParser parser = OptionsParser.newOptionsParser(FooOptions.class);
     30  * try {
     31  *   parser.parse(FooOptions.class, args);
     32  * } catch (OptionsParsingException e) {
     33  *   System.err.print("Error parsing options: " + e.getMessage());
     34  *   System.err.print(options.getUsage());
     35  *   System.exit(1);
     36  * }
     37  * FooOptions foo = parser.getOptions(FooOptions.class);
     38  * List&lt;String&gt; otherArguments = parser.getResidue();
     39  * </pre>
     40  *
     41  * Using this class in this case actually results in more code.
     42  *
     43  * @see OptionsParser for parsing options from multiple options specification classes.
     44  */
     45 public class Options<O extends OptionsBase> {
     46 
     47   /**
     48    * Parse the options provided in args, given the specification in
     49    * optionsClass.
     50    */
     51   public static <O extends OptionsBase> Options<O> parse(Class<O> optionsClass, String... args)
     52       throws OptionsParsingException {
     53     OptionsParser parser = OptionsParser.newOptionsParser(optionsClass);
     54     parser.parse(OptionPriority.PriorityCategory.COMMAND_LINE, null, Arrays.asList(args));
     55     List<String> remainingArgs = parser.getResidue();
     56     return new Options<>(parser.getOptions(optionsClass), remainingArgs.toArray(new String[0]));
     57   }
     58 
     59   /**
     60    * A convenience function for use in main methods. Parses the command line parameters, and exits
     61    * upon error. Also, prints out the usage message if "--help" appears anywhere within {@code
     62    * args}.
     63    */
     64   public static <O extends OptionsBase> Options<O> parseAndExitUponError(
     65       Class<O> optionsClass, boolean allowResidue, String... args) {
     66     OptionsParser parser = null;
     67     try {
     68       parser = OptionsParser.newOptionsParser(optionsClass);
     69       parser.setAllowResidue(allowResidue);
     70     } catch (ConstructionException e) {
     71       System.err.println("Error constructing the options parser: " + e.getMessage());
     72       System.exit(2);
     73     }
     74     parser.parseAndExitUponError(args);
     75     List<String> remainingArgs = parser.getResidue();
     76     return new Options<>(parser.getOptions(optionsClass), remainingArgs.toArray(new String[0]));
     77   }
     78 
     79   /**
     80    * Returns an options object at its default values.  The returned object may
     81    * be freely modified by the caller, by assigning its fields.
     82    */
     83   public static <O extends OptionsBase> O getDefaults(Class<O> optionsClass) {
     84     try {
     85       return parse(optionsClass, new String[0]).getOptions();
     86     } catch (OptionsParsingException e) {
     87       String message = "Error while parsing defaults: " + e.getMessage();
     88       throw new AssertionError(message);
     89     }
     90   }
     91 
     92   /**
     93    * Returns a usage string (renders the help information, the defaults, and
     94    * of course the option names).
     95    */
     96   public static String getUsage(Class<? extends OptionsBase> optionsClass) {
     97     StringBuilder usage = new StringBuilder();
     98     OptionsUsage.getUsage(optionsClass, usage);
     99     return usage.toString();
    100   }
    101 
    102   private O options;
    103   private String[] remainingArgs;
    104 
    105   private Options(O options, String[] remainingArgs) {
    106     this.options = options;
    107     this.remainingArgs = remainingArgs;
    108   }
    109 
    110   /**
    111    * Returns an instance of options class O.
    112    */
    113   public O getOptions() {
    114     return options;
    115   }
    116 
    117   /**
    118    * Returns the arguments that we didn't parse.
    119    */
    120   public String[] getRemainingArgs() {
    121     return remainingArgs;
    122   }
    123 
    124 }
    125