// Generated by CoffeeScript 2.1.1 (function() { var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments, repeat, splice = [].splice; ({repeat} = require('./helpers')); // A simple **OptionParser** class to parse option flags from the command-line. // Use it like so: // parser = new OptionParser switches, helpBanner // options = parser.parse process.argv // The first non-option is considered to be the start of the file (and file // option) list, and all subsequent arguments are left unparsed. // The `coffee` command uses an instance of **OptionParser** to parse its // command-line arguments in `src/command.coffee`. exports.OptionParser = OptionParser = class OptionParser { // Initialize with a list of valid options, in the form: // [short-flag, long-flag, description] // Along with an optional banner for the usage help. constructor(ruleDeclarations, banner) { this.banner = banner; this.rules = buildRules(ruleDeclarations); } // Parse the list of arguments, populating an `options` object with all of the // specified options, and return it. Options after the first non-option // argument are treated as arguments. `options.arguments` will be an array // containing the remaining arguments. This is a simpler API than many option // parsers that allow you to attach callback actions for every flag. Instead, // you're responsible for interpreting the options object. parse(args) { var argument, hasArgument, i, isList, len, name, options, positional, rules; // The CoffeeScript option parser is a little odd; options after the first // non-option argument are treated as non-option arguments themselves. // Optional arguments are normalized by expanding merged flags into multiple // flags. This allows you to have `-wl` be the same as `--watch --lint`. // Note that executable scripts with a shebang (`#!`) line should use the // line `#!/usr/bin/env coffee`, or `#!/absolute/path/to/coffee`, without a // `--` argument after, because that will fail on Linux (see #3946). ({rules, positional} = normalizeArguments(args, this.rules.flagDict)); options = {}; // The `argument` field is added to the rule instance non-destructively by // `normalizeArguments`. for (i = 0, len = rules.length; i < len; i++) { ({hasArgument, argument, isList, name} = rules[i]); if (hasArgument) { if (isList) { if (options[name] == null) { options[name] = []; } options[name].push(argument); } else { options[name] = argument; } } else { options[name] = true; } } if (positional[0] === '--') { options.doubleDashed = true; positional = positional.slice(1); } options.arguments = positional; return options; } // Return the help text for this **OptionParser**, listing and describing all // of the valid options, for `--help` and such. help() { var i, len, letPart, lines, ref, rule, spaces; lines = []; if (this.banner) { lines.unshift(`${this.banner}\n`); } ref = this.rules.ruleList; for (i = 0, len = ref.length; i < len; i++) { rule = ref[i]; spaces = 15 - rule.longFlag.length; spaces = spaces > 0 ? repeat(' ', spaces) : ''; letPart = rule.shortFlag ? rule.shortFlag + ', ' : ' '; lines.push(' ' + letPart + rule.longFlag + spaces + rule.description); } return `\n${lines.join('\n')}\n`; } }; // Helpers // ------- // Regex matchers for option flags on the command line and their rules. LONG_FLAG = /^(--\w[\w\-]*)/; SHORT_FLAG = /^(-\w)$/; MULTI_FLAG = /^-(\w{2,})/; // Matches the long flag part of a rule for an option with an argument. Not // applied to anything in process.argv. OPTIONAL = /\[(\w+(\*?))\]/; // Build and return the list of option rules. If the optional *short-flag* is // unspecified, leave it out by padding with `null`. buildRules = function(ruleDeclarations) { var flag, flagDict, i, j, len, len1, ref, rule, ruleList, tuple; ruleList = (function() { var i, len, results; results = []; for (i = 0, len = ruleDeclarations.length; i < len; i++) { tuple = ruleDeclarations[i]; if (tuple.length < 3) { tuple.unshift(null); } results.push(buildRule(...tuple)); } return results; })(); flagDict = {}; for (i = 0, len = ruleList.length; i < len; i++) { rule = ruleList[i]; ref = [rule.shortFlag, rule.longFlag]; // `shortFlag` is null if not provided in the rule. for (j = 0, len1 = ref.length; j < len1; j++) { flag = ref[j]; if (!(flag != null)) { continue; } if (flagDict[flag] != null) { throw new Error(`flag ${flag} for switch ${rule.name} was already declared for switch ${flagDict[flag].name}`); } flagDict[flag] = rule; } } return {ruleList, flagDict}; }; // Build a rule from a `-o` short flag, a `--output [DIR]` long flag, and the // description of what the option does. buildRule = function(shortFlag, longFlag, description) { var match; match = longFlag.match(OPTIONAL); shortFlag = shortFlag != null ? shortFlag.match(SHORT_FLAG)[1] : void 0; longFlag = longFlag.match(LONG_FLAG)[1]; return { name: longFlag.replace(/^--/, ''), shortFlag: shortFlag, longFlag: longFlag, description: description, hasArgument: !!(match && match[1]), isList: !!(match && match[2]) }; }; normalizeArguments = function(args, flagDict) { var arg, argIndex, flag, i, innerOpts, j, lastOpt, len, len1, multiFlags, multiOpts, needsArgOpt, positional, ref, rule, rules, singleRule, withArg; rules = []; positional = []; needsArgOpt = null; for (argIndex = i = 0, len = args.length; i < len; argIndex = ++i) { arg = args[argIndex]; // If the previous argument given to the script was an option that uses the // next command-line argument as its argument, create copy of the option’s // rule with an `argument` field. if (needsArgOpt != null) { withArg = Object.assign({}, needsArgOpt.rule, { argument: arg }); rules.push(withArg); needsArgOpt = null; continue; } multiFlags = (ref = arg.match(MULTI_FLAG)) != null ? ref[1].split('').map(function(flagName) { return `-${flagName}`; }) : void 0; if (multiFlags != null) { multiOpts = multiFlags.map(function(flag) { var rule; rule = flagDict[flag]; if (rule == null) { throw new Error(`unrecognized option ${flag} in multi-flag ${arg}`); } return {rule, flag}; }); // Only the last flag in a multi-flag may have an argument. [...innerOpts] = multiOpts, [lastOpt] = splice.call(innerOpts, -1); for (j = 0, len1 = innerOpts.length; j < len1; j++) { ({rule, flag} = innerOpts[j]); if (rule.hasArgument) { throw new Error(`cannot use option ${flag} in multi-flag ${arg} except as the last option, because it needs an argument`); } rules.push(rule); } if (lastOpt.rule.hasArgument) { needsArgOpt = lastOpt; } else { rules.push(lastOpt.rule); } } else if ([LONG_FLAG, SHORT_FLAG].some(function(pat) { return arg.match(pat) != null; })) { singleRule = flagDict[arg]; if (singleRule == null) { throw new Error(`unrecognized option ${arg}`); } if (singleRule.hasArgument) { needsArgOpt = { rule: singleRule, flag: arg }; } else { rules.push(singleRule); } } else { // This is a positional argument. positional = args.slice(argIndex); break; } } if (needsArgOpt != null) { throw new Error(`value required for ${needsArgOpt.flag}, but it was the last argument provided`); } return {rules, positional}; }; }).call(this);