all files / lib/ Cli.js

96.49% Statements 55/57
87.5% Branches 28/32
100% Functions 8/8
96.49% Lines 55/57
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168                                            48× 44×     48× 48× 48× 48× 48× 48× 48×   48× 48× 48× 48×   48× 47×                         11× 11×                       43× 38×                                           53×     53×   53×     53× 43×     10×   53×   53×       51×               51×   51×   49×     42×   41× 40×   37×                     40×                
#!/usr/bin/node
var Option = require('./Option'),
	Flag = require('./Flag'),
	Command = require('./Command'),
	CommandGroup = require('./CommandGroup'),
	helpers = require('./Helpers'),
 
	ConfigError = require('./error/config'),
	InvalidInputError = require('./error/invalid-input');
 
/**
 * Cli Constructor
 *
 * Create a new Cli Object, pass in options to configure the base Cli.
 *
 * Options (type, default value):
 *
 * * scriptName (string, null) - The name of cli script, this is automatically parsed, but use this as an override. Used in displaying documentation.
 * * verboseEnabled (boolean, true) - Automatically parse -v, -vv, -vvv, and --verbose
 *
 * @param cliOptions
 * @constructor
 */
function Cli(cliOptions) {
	if (cliOptions === undefined) {
		cliOptions = {};
	}
 
	this.description = cliOptions.description || '';
	this.scriptName = cliOptions.scriptName;
	this.verboseEnabled = (cliOptions.verboseEnabled !== undefined) ? cliOptions.verboseEnabled : true;
	this.helpEnabled = (cliOptions.helpEnabled !== undefined) ? cliOptions.helpEnabled : true;
	this.helpOnNoArgs = (cliOptions.helpOnNoArgs !== undefined) ? cliOptions.helpOnNoArgs : true;
	this.exitOnHelp = (cliOptions.exitOnHelp !== undefined) ? cliOptions.exitOnHelp : false;
	this.allowExtraArgs = (cliOptions.allowExtraArgs !== undefined) ? cliOptions.allowExtraArgs : false;
 
	this.params = {};
	this.options = [];
	this.flags = [];
	this.commandGroups = [];
 
	if (this.verboseEnabled) {
		this.params.verbose = 0;
	}
}
 
/**
 * Add Command Group
 *
 * Create a command group and add it to the config.
 * @param {{name, [description], commands, [callback] [required]}} options
 *
 * @see CommandGroup
 * @returns {Cli}
 */
Cli.prototype.commandGroup = function (options) {
	this.commandGroups.push(new CommandGroup(options));
	return this;
};
 
/**
 * Add Option
 *
 * Adds an Option to the CLI to be checked during the parse() method. See Option for more info.
 * @param {{name, description, [shortFlag], [longFlag], [type], [length]}} options
 *
 * @see Option
 * @returns {Cli}
 */
Cli.prototype.option = function (options) {
	this.options.push(new Option(options));
	return this;
};
 
/**
 * Add Flag
 *
 * Adds a Flag to the CLI to be checked during the parse() method. See Flag for more info.
 * @param {{name, [description], short, [long], [value]}} options
 * @see Flag
 * @returns {Cli}
 */
Cli.prototype.flag = function (options) {
	this.flags.push(new Flag(options));
	return this;
};
 
/**
 * Parse
 *
 * Take the arguments (or array passed) and parse it into the params object.
 * @param {String[]} [args] An optional array of args, the process.argv is used by default.
 * @returns {Object}
 * @throws ConfigError
 * @throws InvalidInputError
 */
Cli.prototype.parse = function (args) {
	Iif (args == undefined) {
		args = process.argv;
	}
	var helpCalled = false;
	//Pull off the node path
	args.shift();
 
	//Parse Script Name
	if (this.scriptName == null) {
		this.scriptName = args.shift();
	}
	else {
		args.shift();
	}
	this.params = {};
 
	if (args.length === 0 && this.helpOnNoArgs) {
		return this.getHelpText();
	}
 
	//Parse flags - Make sure we grab help text first
	var flagParams = Flag.parse(args, this.flags, {
			verboseEnabled: this.verboseEnabled,
			helpEnabled: this.helpEnabled,
			allowExtra: this.allowExtraArgs
		},
		function () {
			this.getHelpText();
			helpCalled = true;
		}.bind(this)
	);
	helpers.merge(this.params, flagParams);
 
	if (!helpCalled) {
		//Parse Option
		helpers.merge(this.params, Option.parse(args, this.options));
 
		//Parse Command Groups
		helpers.merge(this.params, CommandGroup.parse(args, this.commandGroups));
 
		if (!this.allowExtraArgs) {
			this.checkForExtras(args);
		}
		return this.params;
	}
};
 
/**
 * Check For Extras
 *
 * Checks for remaining args and throws an error.
 * @throws InvalidInputError
 * @param args
 */
Cli.prototype.checkForExtras = function (args) {
	if (args.length) {
		throw new InvalidInputError("Invalid extra params supplied: " + args.join(', '));
	}
};
 
Cli.prototype.getHelpText = function () {
	var TtyParser = require('./output-parsers/tty');
	var ttyParser = new TtyParser(this);
	ttyParser.output();
	Iif (this.exitOnHelp) {
		process.exit(3);
	}
};
 
 
module.exports = Cli;