all files / lib/ Flag.js

94.64% Statements 53/56
90.24% Branches 37/41
100% Functions 4/4
94.64% Lines 53/56
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                                                110× 110× 110× 110× 110×     110×       110×                           51×       51×   51× 51×   50×                 51× 51×             51× 110×   110×   14× 14× 14×     96×   36× 36× 36× 40× 40× 14×     11×   14×         110×       49× 112× 95×     49×                       54× 54× 95× 95× 22× 22×     32× 32×    
#!/usr/bin/node
var Cli = require('./Cli'),
	debug = require('debug')('Flag'),
	helpers = require('./Helpers'),
 
	ConfigError = require('./error/config'),
	InvalidInputError = require('./error/invalid-input');
 
/**
 * Flag
 *
 * A flag is a single phrase that is set as a boolean. Flags that aren't passed are set as false.
 *
 * Options:
 *
 *  * name Name of the flag, it will be stored as cli.params.[name]
 *  * [description] Description of the flag. Used in help text.
 *  * short Short version of the flag, starts with '-' and is one more character.
 *  * [long] The long version of the flag, starts with '--' and is one or more characters.
 *  * [value] The value to set the variable to if this flag is passed. Defaults to true.
 *
 * @param {{name, [description], shortFlag, [longFlag], [value]}} options
 *
 * @constructor
 */
function Flag(options) {
	this.name = options.name;
	this.description = options.description;
	this.shortFlag = options.shortFlag;
	this.longFlag = options.longFlag;
	this.value = options.value || true;
 
 
	Iif (this.shortFlag != null && (this.shortFlag.length != 2 || this.shortFlag[0] !== '-')) {
		throw new InvalidInputError("The flag: " + this.name + "'s short property must start with a '-' and be one more character.");
	}
 
	Iif (this.longFlag != null && (this.longFlag.length <= 2 || this.longFlag.substr(0, 2) !== '--')) {
		throw new InvalidInputError("The flag: " + this.name + "'s long property must start with '--' and be one or more character");
	}
}
 
/**
 *
 * @param {Array} args
 * @param {Flag[]} flags
 * @param {boolean} verbose
 * @param {boolean} help
 * @param {function} helpTextCallback Call this if we find help flag
 * @returns {*}
 */
Flag.parse = function (args, flags, options, helpTextCallback) {
	Iif (options === undefined) {
		options = {}
	}
 
	var params = {};
 
	flags = helpers.deepCopy(flags);
	if (options.verboseEnabled) {
		//Add flags for verbose.
		flags.push(new Flag({
			name: 'verbose',
			description: 'The verbosity level of the application',
			shortFlag: '-v',
			longFlag: '--verbose',
			value: 1
		}));
	}
 
	Eif (options.helpEnabled) {
		flags.push(new Flag({
			name: 'help',
			description: 'Display the help text',
			longFlag: '--help'
		}));
	}
 
	for (var i = 0; i < args.length; i++) {
		var arg = args[i],
			flag;
		if (arg.match(/^\-\-/)) {
			//Long version flags --
			debug("Flag(s) (Long version) found: " + arg);
			flag = findFlag(arg, flags);
			if (flag) {
				params[flag.name] = flag.value;
				args.splice(i, 1);
				i--;
			}
		}
		else if (arg[0] == "-") {
			//Short version flags -
			debug("Flag(s) found: " + arg);
			arg = arg.substr(1);
			for (var j = 0; j < arg.length; j++) {
				flag = findFlag('-' + arg[j], flags);
				if (flag) {
					if (params.hasOwnProperty(flag.name) && !isNaN(params[flag.name]) && !isNaN(flag.value)) {
						params[flag.name] += flag.value;
					}
					else {
						params[flag.name] = flag.value;
					}
					args.splice(i, 1);
				}
			}
		}
 
		if (flag && flag.name === 'help') {
			debug("Help text mode, running help text callback");
			return helpTextCallback();
		}
	}
	//Set all other registered flags to false
	flags.forEach(function (flag) {
		if (!params.hasOwnProperty(flag.name)) {
			params[flag.name] = false;
		}
	}.bind(this));
	return params;
};
 
/**
 * Find Flag
 *
 * Given a `key` that represents the long or short version of a flag, return the flag object from `flags`
 * @param {String} key The needle, the long or short string that represents a flag.
 * @param {Flag[]} flags
 * @returns {*}
 * @private
 */
function findFlag(key, flags) {
	debug('findFlag: ' + key);
	for (var i = 0; i < flags.length; i++) {
		var flag = flags[i];
		if (flag.shortFlag == key || flag.longFlag == key) {
			debug('Flag found!', flag);
			return flag;
		}
	}
	debug('returning null');
	return null;
}
 
module.exports = Flag;