| 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 '../args.dart'; | 7 import '../args.dart'; |
| 8 | 8 |
| 9 final _SOLO_OPT = new RegExp(r'^-([a-zA-Z0-9])$'); | 9 final _SOLO_OPT = new RegExp(r'^-([a-zA-Z0-9])$'); |
| 10 final _ABBR_OPT = new RegExp(r'^-([a-zA-Z0-9]+)(.*)$'); | 10 final _ABBR_OPT = new RegExp(r'^-([a-zA-Z0-9]+)(.*)$'); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 args.clear(); | 99 args.clear(); |
| 100 return new ArgResults(results, commandName, commandResults, rest); | 100 return new ArgResults(results, commandName, commandResults, rest); |
| 101 } | 101 } |
| 102 | 102 |
| 103 /** | 103 /** |
| 104 * Pulls the value for [option] from the second argument in [args]. Validates | 104 * Pulls the value for [option] from the second argument in [args]. Validates |
| 105 * that there is a valid value there. | 105 * that there is a valid value there. |
| 106 */ | 106 */ |
| 107 void readNextArgAsValue(Option option) { | 107 void readNextArgAsValue(Option option) { |
| 108 // Take the option argument from the next command line arg. | 108 // Take the option argument from the next command line arg. |
| 109 validate(args.length > 0, | 109 validate(args.length > 0, 'Missing argument for "${option.name}".'); |
| 110 'Missing argument for "${option.name}".'); | |
| 111 | 110 |
| 112 // Make sure it isn't an option itself. | 111 // Make sure it isn't an option itself. |
| 113 validate(!_ABBR_OPT.hasMatch(current) && !_LONG_OPT.hasMatch(current), | 112 validate(!_ABBR_OPT.hasMatch(current) && !_LONG_OPT.hasMatch(current), |
| 114 'Missing argument for "${option.name}".'); | 113 'Missing argument for "${option.name}".'); |
| 115 | 114 |
| 116 setOption(results, option, current); | 115 setOption(results, option, current); |
| 117 args.removeAt(0); | 116 args.removeAt(0); |
| 118 } | 117 } |
| 119 | 118 |
| 120 /** | 119 /** |
| 121 * Tries to parse the current argument as a "solo" option, which is a single | 120 * Tries to parse the current argument as a "solo" option, which is a single |
| 122 * hyphen followed by a single letter. We treat this differently than | 121 * hyphen followed by a single letter. We treat this differently than |
| 123 * collapsed abbreviations (like "-abc") to handle the possible value that | 122 * collapsed abbreviations (like "-abc") to handle the possible value that |
| 124 * may follow it. | 123 * may follow it. |
| 125 */ | 124 */ |
| 126 bool parseSoloOption() { | 125 bool parseSoloOption() { |
| 127 var soloOpt = _SOLO_OPT.firstMatch(current); | 126 var soloOpt = _SOLO_OPT.firstMatch(current); |
| 128 if (soloOpt == null) return false; | 127 if (soloOpt == null) return false; |
| 129 | 128 |
| 130 var option = grammar.findByAbbreviation(soloOpt[1]); | 129 var option = grammar.findByAbbreviation(soloOpt[1]); |
| 131 if (option == null) { | 130 if (option == null) { |
| 132 // Walk up to the parent command if possible. | 131 // Walk up to the parent command if possible. |
| 133 validate(parent != null, | 132 validate( |
| 134 'Could not find an option or flag "-${soloOpt[1]}".'); | 133 parent != null, 'Could not find an option or flag "-${soloOpt[1]}".'); |
| 135 return parent.parseSoloOption(); | 134 return parent.parseSoloOption(); |
| 136 } | 135 } |
| 137 | 136 |
| 138 args.removeAt(0); | 137 args.removeAt(0); |
| 139 | 138 |
| 140 if (option.isFlag) { | 139 if (option.isFlag) { |
| 141 setOption(results, option, true); | 140 setOption(results, option, true); |
| 142 } else { | 141 } else { |
| 143 readNextArgAsValue(option); | 142 readNextArgAsValue(option); |
| 144 } | 143 } |
| 145 | 144 |
| 146 return true; | 145 return true; |
| 147 } | 146 } |
| 148 | 147 |
| 149 /** | 148 /** |
| 150 * Tries to parse the current argument as a series of collapsed abbreviations | 149 * Tries to parse the current argument as a series of collapsed abbreviations |
| 151 * (like "-abc") or a single abbreviation with the value directly attached | 150 * (like "-abc") or a single abbreviation with the value directly attached |
| 152 * to it (like "-mrelease"). | 151 * to it (like "-mrelease"). |
| 153 */ | 152 */ |
| 154 bool parseAbbreviation(Parser innermostCommand) { | 153 bool parseAbbreviation(Parser innermostCommand) { |
| 155 var abbrOpt = _ABBR_OPT.firstMatch(current); | 154 var abbrOpt = _ABBR_OPT.firstMatch(current); |
| 156 if (abbrOpt == null) return false; | 155 if (abbrOpt == null) return false; |
| 157 | 156 |
| 158 // If the first character is the abbreviation for a non-flag option, then | 157 // If the first character is the abbreviation for a non-flag option, then |
| 159 // the rest is the value. | 158 // the rest is the value. |
| 160 var c = abbrOpt[1].substring(0, 1); | 159 var c = abbrOpt[1].substring(0, 1); |
| 161 var first = grammar.findByAbbreviation(c); | 160 var first = grammar.findByAbbreviation(c); |
| 162 if (first == null) { | 161 if (first == null) { |
| 163 // Walk up to the parent command if possible. | 162 // Walk up to the parent command if possible. |
| 164 validate(parent != null, | 163 validate( |
| 165 'Could not find an option with short name "-$c".'); | 164 parent != null, 'Could not find an option with short name "-$c".'); |
| 166 return parent.parseAbbreviation(innermostCommand); | 165 return parent.parseAbbreviation(innermostCommand); |
| 167 } else if (!first.isFlag) { | 166 } else if (!first.isFlag) { |
| 168 // The first character is a non-flag option, so the rest must be the | 167 // The first character is a non-flag option, so the rest must be the |
| 169 // value. | 168 // value. |
| 170 var value = '${abbrOpt[1].substring(1)}${abbrOpt[2]}'; | 169 var value = '${abbrOpt[1].substring(1)}${abbrOpt[2]}'; |
| 171 setOption(results, first, value); | 170 setOption(results, first, value); |
| 172 } else { | 171 } else { |
| 173 // If we got some non-flag characters, then it must be a value, but | 172 // If we got some non-flag characters, then it must be a value, but |
| 174 // if we got here, it's a flag, which is wrong. | 173 // if we got here, it's a flag, which is wrong. |
| 175 validate(abbrOpt[2] == '', | 174 validate( |
| 176 'Option "-$c" is a flag and cannot handle value ' | 175 abbrOpt[2] == '', |
| 177 '"${abbrOpt[1].substring(1)}${abbrOpt[2]}".'); | 176 'Option "-$c" is a flag and cannot handle value ' |
| 177 '"${abbrOpt[1].substring(1)}${abbrOpt[2]}".'); |
| 178 | 178 |
| 179 // Not an option, so all characters should be flags. | 179 // Not an option, so all characters should be flags. |
| 180 // We use "innermostCommand" here so that if a parent command parses the | 180 // We use "innermostCommand" here so that if a parent command parses the |
| 181 // *first* letter, subcommands can still be found to parse the other | 181 // *first* letter, subcommands can still be found to parse the other |
| 182 // letters. | 182 // letters. |
| 183 for (var i = 0; i < abbrOpt[1].length; i++) { | 183 for (var i = 0; i < abbrOpt[1].length; i++) { |
| 184 var c = abbrOpt[1].substring(i, i + 1); | 184 var c = abbrOpt[1].substring(i, i + 1); |
| 185 innermostCommand.parseShortFlag(c); | 185 innermostCommand.parseShortFlag(c); |
| 186 } | 186 } |
| 187 } | 187 } |
| 188 | 188 |
| 189 args.removeAt(0); | 189 args.removeAt(0); |
| 190 return true; | 190 return true; |
| 191 } | 191 } |
| 192 | 192 |
| 193 void parseShortFlag(String c) { | 193 void parseShortFlag(String c) { |
| 194 var option = grammar.findByAbbreviation(c); | 194 var option = grammar.findByAbbreviation(c); |
| 195 if (option == null) { | 195 if (option == null) { |
| 196 // Walk up to the parent command if possible. | 196 // Walk up to the parent command if possible. |
| 197 validate(parent != null, | 197 validate( |
| 198 'Could not find an option with short name "-$c".'); | 198 parent != null, 'Could not find an option with short name "-$c".'); |
| 199 parent.parseShortFlag(c); | 199 parent.parseShortFlag(c); |
| 200 return; | 200 return; |
| 201 } | 201 } |
| 202 | 202 |
| 203 // In a list of short options, only the first can be a non-flag. If | 203 // In a list of short options, only the first can be a non-flag. If |
| 204 // we get here we've checked that already. | 204 // we get here we've checked that already. |
| 205 validate(option.isFlag, | 205 validate( |
| 206 'Option "-$c" must be a flag to be in a collapsed "-".'); | 206 option.isFlag, 'Option "-$c" must be a flag to be in a collapsed "-".'); |
| 207 | 207 |
| 208 setOption(results, option, true); | 208 setOption(results, option, true); |
| 209 } | 209 } |
| 210 | 210 |
| 211 /** | 211 /** |
| 212 * Tries to parse the current argument as a long-form named option, which | 212 * Tries to parse the current argument as a long-form named option, which |
| 213 * may include a value like "--mode=release" or "--mode release". | 213 * may include a value like "--mode=release" or "--mode release". |
| 214 */ | 214 */ |
| 215 bool parseLongOption() { | 215 bool parseLongOption() { |
| 216 var longOpt = _LONG_OPT.firstMatch(current); | 216 var longOpt = _LONG_OPT.firstMatch(current); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 '"$value" is not an allowed value for option "${option.name}".'); | 272 '"$value" is not an allowed value for option "${option.name}".'); |
| 273 } | 273 } |
| 274 | 274 |
| 275 if (option.allowMultiple) { | 275 if (option.allowMultiple) { |
| 276 results[option.name].add(value); | 276 results[option.name].add(value); |
| 277 } else { | 277 } else { |
| 278 results[option.name] = value; | 278 results[option.name] = value; |
| 279 } | 279 } |
| 280 } | 280 } |
| 281 } | 281 } |
| OLD | NEW |