2015-04-04 09:53:59 -07:00
|
|
|
// Licensed to the Software Freedom Conservancy (SFC) under one
|
|
|
|
|
// or more contributor license agreements. See the NOTICE file
|
|
|
|
|
// distributed with this work for additional information
|
|
|
|
|
// regarding copyright ownership. The SFC licenses this file
|
|
|
|
|
// to you under the Apache License, Version 2.0 (the
|
|
|
|
|
// "License"); you may not use this file except in compliance
|
|
|
|
|
// with the License. You may obtain a copy of the License at
|
2012-09-09 02:25:02 +00:00
|
|
|
//
|
2015-04-04 09:53:59 -07:00
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
2012-09-09 02:25:02 +00:00
|
|
|
//
|
2015-04-04 09:53:59 -07:00
|
|
|
// Unless required by applicable law or agreed to in writing,
|
|
|
|
|
// software distributed under the License is distributed on an
|
|
|
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
|
|
|
// KIND, either express or implied. See the License for the
|
|
|
|
|
// specific language governing permissions and limitations
|
|
|
|
|
// under the License.
|
2012-09-09 02:25:02 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @fileoverview A simple command line option parser.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
var path = require('path');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Repeats a string n times.
|
|
|
|
|
* @param {string} str The string to repeat.
|
|
|
|
|
* @param {number} n The number of times to repeat the string.
|
|
|
|
|
* @return {string} The repeated string, concatenated together.
|
|
|
|
|
*/
|
|
|
|
|
function repeatStr(str, n) {
|
|
|
|
|
return new Array(n + 1).join(str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Trims a string of all trailing and leading whitespace.
|
|
|
|
|
* @param {string} str The string to trim.
|
|
|
|
|
* @return {string} The trimmed string.
|
|
|
|
|
*/
|
|
|
|
|
function trimStr(str) {
|
|
|
|
|
return str.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Wraps the provided {@code text} so every line is at most {@code width}
|
|
|
|
|
* characters long.
|
|
|
|
|
* @param {string} text The text to wrap.
|
|
|
|
|
* @param {number} width The maximum line length.
|
|
|
|
|
* @param {string=} opt_indent String that will be prepended to each line.
|
|
|
|
|
* Defaults to the empty string.
|
|
|
|
|
* @return {!Array.<string>} A list of lines, without newline characters.
|
|
|
|
|
*/
|
|
|
|
|
function wrapStr(text, width, opt_indent) {
|
|
|
|
|
var out = [],
|
|
|
|
|
indent = opt_indent || '';
|
|
|
|
|
|
|
|
|
|
if (indent.length >= width) {
|
|
|
|
|
throw Error('Wrapped line indentation is longer than permitted width: ' +
|
|
|
|
|
indent.length + ' >= ' + width);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
text.split('\n').forEach(function(line) {
|
|
|
|
|
if (/^\s*$/.test(line)) {
|
|
|
|
|
out.push(''); // Push a blank line.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
line = indent + trimStr(line);
|
|
|
|
|
out.push(line.substring(0, width));
|
|
|
|
|
line = line.substring(width);
|
|
|
|
|
} while (line);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The total number of columns for output in a printed help message.
|
|
|
|
|
* @type {number}
|
|
|
|
|
* @const
|
|
|
|
|
*/
|
|
|
|
|
var TOTAL_WIDTH = 80;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Indentation to use between the left column and options string, and between
|
|
|
|
|
* the options string and help text.
|
|
|
|
|
* @type {string}
|
|
|
|
|
* @const
|
|
|
|
|
*/
|
|
|
|
|
var IDENTATION = ' ';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The maximum column for option text.
|
|
|
|
|
* @type {number}
|
|
|
|
|
* @const
|
|
|
|
|
*/
|
|
|
|
|
var MAX_HELP_POSITION = 24;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Column where the help text should begin.
|
|
|
|
|
* @type {number}
|
|
|
|
|
* @const
|
|
|
|
|
*/
|
|
|
|
|
var HELP_TEXT_POSITION = MAX_HELP_POSITION + IDENTATION.length;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Formats a help message for the given parser.
|
2020-08-16 00:03:35 +05:30
|
|
|
* @param {string} usage The usage string. All occurrences of "$0" will be
|
2012-09-09 02:25:02 +00:00
|
|
|
* replaced with the name of the current program.
|
|
|
|
|
* @param {!Object.<!Option>} options The options to format.
|
|
|
|
|
* @return {string} The formatted help message.
|
|
|
|
|
*/
|
|
|
|
|
function formatHelpMsg(usage, options) {
|
2012-09-09 03:07:49 +00:00
|
|
|
var prog = path.basename(
|
|
|
|
|
process.argv[0]) + ' ' + path.basename(process.argv[1]);
|
2012-09-09 02:25:02 +00:00
|
|
|
var help = [
|
|
|
|
|
usage.replace(/\$0\b/g, prog),
|
|
|
|
|
'',
|
|
|
|
|
'Options:',
|
|
|
|
|
formatOption('help', 'Show this message and exit')
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
Object.keys(options).sort().forEach(function(key) {
|
|
|
|
|
help.push(formatOption(key, options[key].help));
|
2012-09-09 03:07:49 +00:00
|
|
|
});
|
2012-09-09 02:25:02 +00:00
|
|
|
|
|
|
|
|
help.push('');
|
|
|
|
|
|
|
|
|
|
return help.join('\n');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Formats the help message for a single option. Will place the option string
|
|
|
|
|
* and help text on the same line whenever possible.
|
|
|
|
|
* @param {string} name The name of the option.
|
|
|
|
|
* @param {string} helpMsg The option's help message.
|
|
|
|
|
* @return {string} The formatted option.
|
|
|
|
|
*/
|
|
|
|
|
function formatOption(name, helpMsg) {
|
|
|
|
|
var result = [];
|
|
|
|
|
var options = IDENTATION + '--' + name;
|
|
|
|
|
|
|
|
|
|
if (options.length > MAX_HELP_POSITION) {
|
|
|
|
|
result.push(options);
|
|
|
|
|
result.push('\n');
|
|
|
|
|
result.push(wrapStr(helpMsg, TOTAL_WIDTH,
|
|
|
|
|
repeatStr(' ', HELP_TEXT_POSITION)).join('\n'));
|
|
|
|
|
} else {
|
|
|
|
|
var spaceCount = HELP_TEXT_POSITION - options.length;
|
|
|
|
|
options += repeatStr(' ', spaceCount) + helpMsg;
|
|
|
|
|
result.push(options.substring(0, TOTAL_WIDTH));
|
|
|
|
|
options = options.substring(TOTAL_WIDTH);
|
|
|
|
|
if (options) {
|
|
|
|
|
result.push('\n');
|
|
|
|
|
result.push(wrapStr(options, TOTAL_WIDTH,
|
|
|
|
|
repeatStr(' ', HELP_TEXT_POSITION)).join('\n'));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result.join('');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var OPTION_NAME_PATTERN = '[a-zA-Z][a-zA-Z0-9_]*';
|
|
|
|
|
var OPTION_NAME_REGEX = new RegExp('^' + OPTION_NAME_PATTERN + '$');
|
|
|
|
|
var OPTION_FLAG_REGEX = new RegExp(
|
|
|
|
|
'^--(' + OPTION_NAME_PATTERN + ')(?:=(.*))?$');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function checkOptionName(name, options) {
|
|
|
|
|
if ('help' === name) {
|
|
|
|
|
throw Error('"help" is a reserved option name');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!OPTION_NAME_REGEX.test(name)) {
|
|
|
|
|
throw Error('option ' + JSON.stringify(name) + ' must match ' +
|
|
|
|
|
OPTION_NAME_REGEX);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (name in options) {
|
|
|
|
|
throw Error('option ' + JSON.stringify(name) + ' has already been defined');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function parseOptionValue(name, spec, value) {
|
|
|
|
|
try {
|
|
|
|
|
return spec.parse(value);
|
|
|
|
|
} catch (ex) {
|
|
|
|
|
ex.message = 'Invalid value for ' + JSON.stringify('--' + name) +
|
|
|
|
|
': ' + ex.message;
|
|
|
|
|
throw ex;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function parseBoolean(value) {
|
|
|
|
|
// Empty string if the option was specified without a value; implies true.
|
|
|
|
|
if (!value) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var tmp = value.toLowerCase();
|
|
|
|
|
if (tmp === 'true' || tmp === '1') {
|
|
|
|
|
return true;
|
|
|
|
|
} else if (tmp === 'false' || tmp === '0') {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
throw Error(JSON.stringify(value) + ' is not a valid boolean value');
|
|
|
|
|
}
|
|
|
|
|
parseBoolean['default'] = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function parseNumber(value) {
|
|
|
|
|
if (/^0x\d+$/.test(value)) {
|
|
|
|
|
return parseInt(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var num = parseFloat(value);
|
|
|
|
|
if (isNaN(num) || num != value) {
|
|
|
|
|
throw Error(JSON.stringify(value) + ' is not a valid number');
|
|
|
|
|
}
|
|
|
|
|
return num;
|
|
|
|
|
}
|
|
|
|
|
parseNumber['default'] = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function parseString(value) { return value; }
|
|
|
|
|
parseString['default'] = '';
|
|
|
|
|
|
|
|
|
|
|
2013-06-29 22:59:48 -07:00
|
|
|
function parseRegex(value) { return new RegExp(value); }
|
|
|
|
|
|
|
|
|
|
|
2012-09-09 02:25:02 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A command line option parser. Will automatically parse the command line
|
|
|
|
|
* arguments to this program upon accessing the {@code options} or {@code argv}
|
|
|
|
|
* properies. The command line will only be re-parsed if this parser's
|
|
|
|
|
* configuration has changed since the last access.
|
|
|
|
|
* @constructor
|
|
|
|
|
*/
|
|
|
|
|
function OptionParser() {
|
|
|
|
|
|
|
|
|
|
/** @type {string} */
|
|
|
|
|
var usage = OptionParser.DEFAULT_USAGE;
|
|
|
|
|
|
|
|
|
|
/** @type {boolean} */
|
|
|
|
|
var mustParse = true;
|
|
|
|
|
|
|
|
|
|
/** @type {!Object.<*>} */
|
|
|
|
|
var parsedOptions = {};
|
|
|
|
|
|
|
|
|
|
/** @type {!Array.<string>} */
|
|
|
|
|
var extraArgs = [];
|
|
|
|
|
|
|
|
|
|
/**
|
2020-08-16 00:03:35 +05:30
|
|
|
* Sets the usage string. All occurrences of "$0" will be replaced with the
|
2012-09-09 02:25:02 +00:00
|
|
|
* current executable's name.
|
|
|
|
|
* @param {string} usageStr The new usage string.
|
|
|
|
|
* @return {!OptionParser} A self reference.
|
2012-09-09 03:07:49 +00:00
|
|
|
* @this {OptionParser}
|
2012-09-09 02:25:02 +00:00
|
|
|
*/
|
|
|
|
|
this.usage = function(usageStr) {
|
|
|
|
|
mustParse = true;
|
|
|
|
|
usage = usageStr;
|
|
|
|
|
return this;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @type {!Object.<{
|
|
|
|
|
* help: string,
|
|
|
|
|
* parse: function(string): *,
|
|
|
|
|
* required: boolean,
|
|
|
|
|
* list: boolean,
|
|
|
|
|
* callback: function(*),
|
|
|
|
|
* default: *
|
|
|
|
|
* }>}
|
|
|
|
|
*/
|
|
|
|
|
var options = {};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds a new option to this parser.
|
|
|
|
|
* @param {string} name The name of the option.
|
|
|
|
|
* @param {function(string): *} parseFn The function to use for parsing the
|
|
|
|
|
* option. If this function has a "default" property, it will be used as
|
|
|
|
|
* the default value for the option if it was not provided on the command
|
|
|
|
|
* line. If not specified, the default value will be undefined. The
|
2020-08-16 00:03:35 +05:30
|
|
|
* default value may be overridden using the "default" property in the
|
2012-09-09 02:25:02 +00:00
|
|
|
* option spec.
|
|
|
|
|
* @param {Object=} opt_spec The option spec.
|
|
|
|
|
* @return {!OptionParser} A self reference.
|
2012-09-09 03:07:49 +00:00
|
|
|
* @this {OptionParser}
|
2012-09-09 02:25:02 +00:00
|
|
|
*/
|
|
|
|
|
this.addOption = function(name, parseFn, opt_spec) {
|
|
|
|
|
checkOptionName(name, options);
|
|
|
|
|
var spec = opt_spec || {};
|
|
|
|
|
|
|
|
|
|
// Quoted notation for "default" to bypass annoying IDE syntax bug.
|
|
|
|
|
var defaultValue = spec['default'] ||
|
|
|
|
|
(!!spec.list ? [] : parseFn['default']);
|
|
|
|
|
|
|
|
|
|
options[name] = {
|
|
|
|
|
help: spec.help || '',
|
|
|
|
|
parse: parseFn,
|
|
|
|
|
required: !!spec.required,
|
|
|
|
|
list: !!spec.list,
|
|
|
|
|
callback: spec.callback || function() {},
|
|
|
|
|
'default': defaultValue
|
|
|
|
|
};
|
|
|
|
|
mustParse = true;
|
|
|
|
|
return this;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Defines a boolean option. Option values may be one of {'', 'true', 'false',
|
|
|
|
|
* '0', '1'}. In the case of the empty string (''), the option value will be
|
|
|
|
|
* set to true.
|
|
|
|
|
* @param {string} name The name of the option.
|
|
|
|
|
* @param {Object=} opt_spec The option spec.
|
|
|
|
|
* @return {!OptionParser} A self reference.
|
2012-09-09 03:07:49 +00:00
|
|
|
* @this {OptionParser}
|
|
|
|
|
*/
|
2012-09-09 02:25:02 +00:00
|
|
|
this.boolean = function(name, opt_spec) {
|
|
|
|
|
return this.addOption(name, parseBoolean, opt_spec);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Defines a numeric option.
|
|
|
|
|
* @param {string} name The name of the option.
|
|
|
|
|
* @param {Object=} opt_spec The option spec.
|
|
|
|
|
* @return {!OptionParser} A self reference.
|
2012-09-09 03:07:49 +00:00
|
|
|
* @this {OptionParser}
|
2012-09-09 02:25:02 +00:00
|
|
|
*/
|
|
|
|
|
this.number = function(name, opt_spec) {
|
|
|
|
|
return this.addOption(name, parseNumber, opt_spec);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Defines a path option. Each path will be resolved relative to the
|
2020-08-16 00:03:35 +05:30
|
|
|
* current working directory, if not absolute.
|
2012-09-09 02:25:02 +00:00
|
|
|
* @param {string} name The name of the option.
|
|
|
|
|
* @param {Object=} opt_spec The option spec.
|
|
|
|
|
* @return {!OptionParser} A self reference.
|
2012-09-09 03:07:49 +00:00
|
|
|
* @this {OptionParser}
|
2012-09-09 02:25:02 +00:00
|
|
|
*/
|
|
|
|
|
this.path = function(name, opt_spec) {
|
|
|
|
|
return this.addOption(name, path.resolve, opt_spec);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Defines a basic string option.
|
|
|
|
|
* @param {string} name The name of the option.
|
|
|
|
|
* @param {Object=} opt_spec The option spec.
|
|
|
|
|
* @return {!OptionParser} A self reference.
|
2012-09-09 03:07:49 +00:00
|
|
|
* @this {OptionParser}
|
2012-09-09 02:25:02 +00:00
|
|
|
*/
|
|
|
|
|
this.string = function(name, opt_spec) {
|
|
|
|
|
return this.addOption(name, parseString, opt_spec);
|
|
|
|
|
};
|
|
|
|
|
|
2013-06-29 22:59:48 -07:00
|
|
|
/**
|
|
|
|
|
* Defines a regular expression based option.
|
|
|
|
|
* @param {string} name The name of the option.
|
|
|
|
|
* @param {Object=} opt_spec The option spec.
|
|
|
|
|
* @return {!OptionParser} A self reference.
|
|
|
|
|
* @this {OptionParser}
|
|
|
|
|
*/
|
|
|
|
|
this.regex = function(name, opt_spec) {
|
|
|
|
|
return this.addOption(name, parseRegex, opt_spec);
|
|
|
|
|
};
|
|
|
|
|
|
2012-09-09 02:25:02 +00:00
|
|
|
/**
|
|
|
|
|
* Returns the parsed command line options.
|
|
|
|
|
*
|
|
|
|
|
* <p>The command line arguments will be re-parsed if this parser's
|
|
|
|
|
* configuration has changed since the last access.
|
|
|
|
|
*
|
2012-09-09 03:07:49 +00:00
|
|
|
* @return {!Object.<*>} The parsed options.
|
2012-09-09 02:25:02 +00:00
|
|
|
*/
|
|
|
|
|
this.__defineGetter__('options', function() {
|
|
|
|
|
parse();
|
|
|
|
|
return parsedOptions;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the remaining command line arguments after all options have been
|
|
|
|
|
* parsed.
|
|
|
|
|
*
|
|
|
|
|
* <p>The command line arguments will be re-parsed if this parser's
|
|
|
|
|
* configuration has changed since the last access.
|
|
|
|
|
*
|
2012-09-09 03:07:49 +00:00
|
|
|
* @return {!Array.<string>} The remaining command line arguments.
|
2012-09-09 02:25:02 +00:00
|
|
|
*/
|
|
|
|
|
this.__defineGetter__('argv', function() {
|
|
|
|
|
parse();
|
|
|
|
|
return extraArgs;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Parses a list of arguments. After parsing, the options property of this
|
|
|
|
|
* object will contain the value for each parsed flags, and the argv
|
|
|
|
|
* property will contain all remaining command line arguments.
|
|
|
|
|
* @throws {Error} If the arguments could not be parsed.
|
|
|
|
|
*/
|
|
|
|
|
this.parse = parse;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns a formatted help message for this parser.
|
2012-09-09 03:07:49 +00:00
|
|
|
* @return {string} The help message for this parser.
|
2012-09-09 02:25:02 +00:00
|
|
|
*/
|
|
|
|
|
this.getHelpMsg = getHelpMsg;
|
|
|
|
|
|
|
|
|
|
function getHelpMsg() {
|
|
|
|
|
return formatHelpMsg(usage, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function parse() {
|
|
|
|
|
if (!mustParse) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parsedOptions = {};
|
|
|
|
|
extraArgs = [];
|
|
|
|
|
|
|
|
|
|
var args = process.argv.slice(2);
|
|
|
|
|
var n = args.length;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
for (var i = 0; i < n; ++i) {
|
|
|
|
|
var arg = args[i];
|
|
|
|
|
if (arg === '--') {
|
|
|
|
|
extraArgs = args.slice(i + 1);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var match = arg.match(OPTION_FLAG_REGEX);
|
|
|
|
|
if (match) {
|
|
|
|
|
// Special case --help.
|
|
|
|
|
if (match[1] === 'help') {
|
|
|
|
|
printHelpAndDie('', 0);
|
|
|
|
|
}
|
|
|
|
|
parseOption(match);
|
|
|
|
|
} else {
|
|
|
|
|
extraArgs = args.slice(i + 1);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (ex) {
|
|
|
|
|
printHelpAndDie(ex.message, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (var name in options) {
|
|
|
|
|
var option = options[name];
|
|
|
|
|
if (!(name in parsedOptions)) {
|
|
|
|
|
if (option.required) {
|
|
|
|
|
printHelpAndDie('Missing required option: --' + name, 1);
|
|
|
|
|
}
|
|
|
|
|
parsedOptions[name] = option.list ? [] : option['default'];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mustParse = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function printHelpAndDie(errorMessage, exitCode) {
|
|
|
|
|
process.stdout.write(errorMessage + '\n');
|
|
|
|
|
process.stdout.write(getHelpMsg());
|
|
|
|
|
process.exit(exitCode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function parseOption(match) {
|
|
|
|
|
var option = options[match[1]];
|
|
|
|
|
if (!option) {
|
|
|
|
|
throw Error(JSON.stringify('--' + match[1]) + ' is not a valid option');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var value = match[2];
|
|
|
|
|
if (typeof value !== 'undefined') {
|
|
|
|
|
value = parseOptionValue(match[1], option, value);
|
|
|
|
|
} else if (option.parse === parseBoolean) {
|
|
|
|
|
value = true;
|
|
|
|
|
} else {
|
|
|
|
|
throw Error('Option ' + JSON.stringify('--' + option.name) +
|
|
|
|
|
'requires an operand');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
option.callback(value);
|
|
|
|
|
|
|
|
|
|
if (option.list) {
|
|
|
|
|
var array = parsedOptions[match[1]] || [];
|
|
|
|
|
parsedOptions[match[1]] = array;
|
|
|
|
|
array.push(value);
|
|
|
|
|
} else {
|
|
|
|
|
parsedOptions[match[1]] = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The default usage message for an option parser.
|
|
|
|
|
*/
|
|
|
|
|
Object.defineProperty(OptionParser, 'DEFAULT_USAGE', {
|
|
|
|
|
value: 'Usage: $0 [options] [arguments]',
|
|
|
|
|
writable: false,
|
|
|
|
|
enumerable: true,
|
|
|
|
|
configurable: false
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
2012-09-09 03:07:49 +00:00
|
|
|
/** @type {!OptionParser} */
|
2012-09-09 02:25:02 +00:00
|
|
|
exports.OptionParser = OptionParser;
|
|
|
|
|
|
|
|
|
|
if (module === require.main) {
|
|
|
|
|
var parser = new OptionParser().
|
|
|
|
|
boolean('bool_flag', {
|
|
|
|
|
help: 'This is a boolean flag'
|
|
|
|
|
}).
|
|
|
|
|
number('number_flag', {
|
|
|
|
|
help: 'This is a number flag'
|
|
|
|
|
}).
|
|
|
|
|
path('path_flag', {
|
|
|
|
|
help: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. ' +
|
|
|
|
|
'Nam pharetra pellentesque augue ut auctor. Mauris eget est ' +
|
|
|
|
|
'vitae quam imperdiet mollis. Ut lorem lorem, commodo et ' +
|
|
|
|
|
'interdum cursus, convallis quis mi. Aenean facilisis adipiscing ' +
|
|
|
|
|
'imperdiet. Etiam tristique facilisis ullamcorper. Vestibulum ' +
|
|
|
|
|
'at mauris quis eros lobortis viverra vel non massa. ' +
|
|
|
|
|
'Aenean eu sodales quam.'
|
|
|
|
|
}).
|
|
|
|
|
string('the_quick_brown_fox_jumped_over_the_very_lazy_dog', {
|
|
|
|
|
help: 'The quick brown fox jumped over the very lazy dog'
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log('Options are: ');
|
|
|
|
|
for (var key in parser.options) {
|
|
|
|
|
console.log(' --' + key + '=' + parser.options[key]);
|
|
|
|
|
}
|
|
|
|
|
console.log('Args are: ');
|
|
|
|
|
console.log(' ', parser.argv.join(' '));
|
2012-09-09 03:07:49 +00:00
|
|
|
}
|