| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library args.src.parser; | 5 library args.src.parser; |
| 6 | 6 |
| 7 import 'arg_parser.dart'; | 7 import 'arg_parser.dart'; |
| 8 import 'arg_results.dart'; | 8 import 'arg_results.dart'; |
| 9 import 'option.dart'; | 9 import 'option.dart'; |
| 10 | 10 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 | 85 |
| 86 // Invoke the callbacks. | 86 // Invoke the callbacks. |
| 87 grammar.options.forEach((name, option) { | 87 grammar.options.forEach((name, option) { |
| 88 if (option.callback == null) return; | 88 if (option.callback == null) return; |
| 89 option.callback(option.getOrDefault(results[name])); | 89 option.callback(option.getOrDefault(results[name])); |
| 90 }); | 90 }); |
| 91 | 91 |
| 92 // Add in the leftover arguments we didn't parse to the innermost command. | 92 // Add in the leftover arguments we didn't parse to the innermost command. |
| 93 rest.addAll(args); | 93 rest.addAll(args); |
| 94 args.clear(); | 94 args.clear(); |
| 95 return newArgResults(grammar, results, commandName, commandResults, rest, | 95 return newArgResults( |
| 96 arguments); | 96 grammar, results, commandName, commandResults, rest, arguments); |
| 97 } | 97 } |
| 98 | 98 |
| 99 /// Pulls the value for [option] from the second argument in [args]. | 99 /// Pulls the value for [option] from the second argument in [args]. |
| 100 /// | 100 /// |
| 101 /// Validates that there is a valid value there. | 101 /// Validates that there is a valid value there. |
| 102 void readNextArgAsValue(Option option) { | 102 void readNextArgAsValue(Option option) { |
| 103 // Take the option argument from the next command line arg. | 103 // Take the option argument from the next command line arg. |
| 104 validate(args.length > 0, | 104 validate(args.length > 0, 'Missing argument for "${option.name}".'); |
| 105 'Missing argument for "${option.name}".'); | |
| 106 | 105 |
| 107 // Make sure it isn't an option itself. | 106 // Make sure it isn't an option itself. |
| 108 validate(!_ABBR_OPT.hasMatch(current) && !_LONG_OPT.hasMatch(current), | 107 validate(!_ABBR_OPT.hasMatch(current) && !_LONG_OPT.hasMatch(current), |
| 109 'Missing argument for "${option.name}".'); | 108 'Missing argument for "${option.name}".'); |
| 110 | 109 |
| 111 setOption(results, option, current); | 110 setOption(results, option, current); |
| 112 args.removeAt(0); | 111 args.removeAt(0); |
| 113 } | 112 } |
| 114 | 113 |
| 115 /// Tries to parse the current argument as a "solo" option, which is a single | 114 /// Tries to parse the current argument as a "solo" option, which is a single |
| 116 /// hyphen followed by a single letter. | 115 /// hyphen followed by a single letter. |
| 117 /// | 116 /// |
| 118 /// We treat this differently than collapsed abbreviations (like "-abc") to | 117 /// We treat this differently than collapsed abbreviations (like "-abc") to |
| 119 /// handle the possible value that may follow it. | 118 /// handle the possible value that may follow it. |
| 120 bool parseSoloOption() { | 119 bool parseSoloOption() { |
| 121 var soloOpt = _SOLO_OPT.firstMatch(current); | 120 var soloOpt = _SOLO_OPT.firstMatch(current); |
| 122 if (soloOpt == null) return false; | 121 if (soloOpt == null) return false; |
| 123 | 122 |
| 124 var option = grammar.findByAbbreviation(soloOpt[1]); | 123 var option = grammar.findByAbbreviation(soloOpt[1]); |
| 125 if (option == null) { | 124 if (option == null) { |
| 126 // Walk up to the parent command if possible. | 125 // Walk up to the parent command if possible. |
| 127 validate(parent != null, | 126 validate( |
| 128 'Could not find an option or flag "-${soloOpt[1]}".'); | 127 parent != null, 'Could not find an option or flag "-${soloOpt[1]}".'); |
| 129 return parent.parseSoloOption(); | 128 return parent.parseSoloOption(); |
| 130 } | 129 } |
| 131 | 130 |
| 132 args.removeAt(0); | 131 args.removeAt(0); |
| 133 | 132 |
| 134 if (option.isFlag) { | 133 if (option.isFlag) { |
| 135 setOption(results, option, true); | 134 setOption(results, option, true); |
| 136 } else { | 135 } else { |
| 137 readNextArgAsValue(option); | 136 readNextArgAsValue(option); |
| 138 } | 137 } |
| 139 | 138 |
| 140 return true; | 139 return true; |
| 141 } | 140 } |
| 142 | 141 |
| 143 /// Tries to parse the current argument as a series of collapsed abbreviations | 142 /// Tries to parse the current argument as a series of collapsed abbreviations |
| 144 /// (like "-abc") or a single abbreviation with the value directly attached | 143 /// (like "-abc") or a single abbreviation with the value directly attached |
| 145 /// to it (like "-mrelease"). | 144 /// to it (like "-mrelease"). |
| 146 bool parseAbbreviation(Parser innermostCommand) { | 145 bool parseAbbreviation(Parser innermostCommand) { |
| 147 var abbrOpt = _ABBR_OPT.firstMatch(current); | 146 var abbrOpt = _ABBR_OPT.firstMatch(current); |
| 148 if (abbrOpt == null) return false; | 147 if (abbrOpt == null) return false; |
| 149 | 148 |
| 150 // If the first character is the abbreviation for a non-flag option, then | 149 // If the first character is the abbreviation for a non-flag option, then |
| 151 // the rest is the value. | 150 // the rest is the value. |
| 152 var c = abbrOpt[1].substring(0, 1); | 151 var c = abbrOpt[1].substring(0, 1); |
| 153 var first = grammar.findByAbbreviation(c); | 152 var first = grammar.findByAbbreviation(c); |
| 154 if (first == null) { | 153 if (first == null) { |
| 155 // Walk up to the parent command if possible. | 154 // Walk up to the parent command if possible. |
| 156 validate(parent != null, | 155 validate( |
| 157 'Could not find an option with short name "-$c".'); | 156 parent != null, 'Could not find an option with short name "-$c".'); |
| 158 return parent.parseAbbreviation(innermostCommand); | 157 return parent.parseAbbreviation(innermostCommand); |
| 159 } else if (!first.isFlag) { | 158 } else if (!first.isFlag) { |
| 160 // The first character is a non-flag option, so the rest must be the | 159 // The first character is a non-flag option, so the rest must be the |
| 161 // value. | 160 // value. |
| 162 var value = '${abbrOpt[1].substring(1)}${abbrOpt[2]}'; | 161 var value = '${abbrOpt[1].substring(1)}${abbrOpt[2]}'; |
| 163 setOption(results, first, value); | 162 setOption(results, first, value); |
| 164 } else { | 163 } else { |
| 165 // If we got some non-flag characters, then it must be a value, but | 164 // If we got some non-flag characters, then it must be a value, but |
| 166 // if we got here, it's a flag, which is wrong. | 165 // if we got here, it's a flag, which is wrong. |
| 167 validate(abbrOpt[2] == '', | 166 validate(abbrOpt[2] == '', |
| 168 'Option "-$c" is a flag and cannot handle value ' | 167 'Option "-$c" is a flag and cannot handle value ' |
| 169 '"${abbrOpt[1].substring(1)}${abbrOpt[2]}".'); | 168 '"${abbrOpt[1].substring(1)}${abbrOpt[2]}".'); |
| 170 | 169 |
| 171 // Not an option, so all characters should be flags. | 170 // Not an option, so all characters should be flags. |
| 172 // We use "innermostCommand" here so that if a parent command parses the | 171 // We use "innermostCommand" here so that if a parent command parses the |
| 173 // *first* letter, subcommands can still be found to parse the other | 172 // *first* letter, subcommands can still be found to parse the other |
| 174 // letters. | 173 // letters. |
| 175 for (var i = 0; i < abbrOpt[1].length; i++) { | 174 for (var i = 0; i < abbrOpt[1].length; i++) { |
| 176 var c = abbrOpt[1].substring(i, i + 1); | 175 var c = abbrOpt[1].substring(i, i + 1); |
| 177 innermostCommand.parseShortFlag(c); | 176 innermostCommand.parseShortFlag(c); |
| 178 } | 177 } |
| 179 } | 178 } |
| 180 | 179 |
| 181 args.removeAt(0); | 180 args.removeAt(0); |
| 182 return true; | 181 return true; |
| 183 } | 182 } |
| 184 | 183 |
| 185 void parseShortFlag(String c) { | 184 void parseShortFlag(String c) { |
| 186 var option = grammar.findByAbbreviation(c); | 185 var option = grammar.findByAbbreviation(c); |
| 187 if (option == null) { | 186 if (option == null) { |
| 188 // Walk up to the parent command if possible. | 187 // Walk up to the parent command if possible. |
| 189 validate(parent != null, | 188 validate( |
| 190 'Could not find an option with short name "-$c".'); | 189 parent != null, 'Could not find an option with short name "-$c".'); |
| 191 parent.parseShortFlag(c); | 190 parent.parseShortFlag(c); |
| 192 return; | 191 return; |
| 193 } | 192 } |
| 194 | 193 |
| 195 // In a list of short options, only the first can be a non-flag. If | 194 // In a list of short options, only the first can be a non-flag. If |
| 196 // we get here we've checked that already. | 195 // we get here we've checked that already. |
| 197 validate(option.isFlag, | 196 validate( |
| 198 'Option "-$c" must be a flag to be in a collapsed "-".'); | 197 option.isFlag, 'Option "-$c" must be a flag to be in a collapsed "-".'); |
| 199 | 198 |
| 200 setOption(results, option, true); | 199 setOption(results, option, true); |
| 201 } | 200 } |
| 202 | 201 |
| 203 /// Tries to parse the current argument as a long-form named option, which | 202 /// Tries to parse the current argument as a long-form named option, which |
| 204 /// may include a value like "--mode=release" or "--mode release". | 203 /// may include a value like "--mode=release" or "--mode release". |
| 205 bool parseLongOption() { | 204 bool parseLongOption() { |
| 206 var longOpt = _LONG_OPT.firstMatch(current); | 205 var longOpt = _LONG_OPT.firstMatch(current); |
| 207 if (longOpt == null) return false; | 206 if (longOpt == null) return false; |
| 208 | 207 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 } | 261 } |
| 263 | 262 |
| 264 if (option.isMultiple) { | 263 if (option.isMultiple) { |
| 265 var list = results.putIfAbsent(option.name, () => []); | 264 var list = results.putIfAbsent(option.name, () => []); |
| 266 list.add(value); | 265 list.add(value); |
| 267 } else { | 266 } else { |
| 268 results[option.name] = value; | 267 results[option.name] = value; |
| 269 } | 268 } |
| 270 } | 269 } |
| 271 } | 270 } |
| OLD | NEW |