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<String> 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