mirror of
				https://github.com/therootcompany/greenlock.js.git
				synced 2024-11-16 17:29:00 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			241 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			241 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict';
 | 
						|
 | 
						|
var CLI = module.exports;
 | 
						|
 | 
						|
var defaultConf;
 | 
						|
var defaultOpts;
 | 
						|
var bags = [];
 | 
						|
 | 
						|
CLI.parse = function(conf) {
 | 
						|
    var opts = (defaultOpts = {});
 | 
						|
    defaultConf = conf;
 | 
						|
 | 
						|
    Object.keys(conf).forEach(function(k) {
 | 
						|
        var v = conf[k];
 | 
						|
        if (!v) {
 | 
						|
            console.error(
 | 
						|
                'Developer Error: missing cli flag definition for',
 | 
						|
                JSON.stringify(k)
 | 
						|
            );
 | 
						|
            process.exit(1);
 | 
						|
        }
 | 
						|
        var aliases = v[5];
 | 
						|
        var bag;
 | 
						|
        var bagName;
 | 
						|
 | 
						|
        // the name of the argument set is now the 0th argument
 | 
						|
        v.unshift(k);
 | 
						|
        // v[0] flagname
 | 
						|
        // v[1] short flagname
 | 
						|
        // v[2] description
 | 
						|
        // v[3] type
 | 
						|
        // v[4] default value
 | 
						|
        // v[5] aliases
 | 
						|
 | 
						|
        if ('bag' === v[3]) {
 | 
						|
            bag = v[0]; // 'bag-option-xxxx' => '--bag-option-'
 | 
						|
            bag = '--' + bag.replace(/xxx.*/, '');
 | 
						|
            bags.push(bag);
 | 
						|
 | 
						|
            bagName = toBagName(bag.replace(/^--/, ''));
 | 
						|
            opts[bagName] = {};
 | 
						|
        }
 | 
						|
 | 
						|
        if ('json' === v[3]) {
 | 
						|
            bagName = toBagName(v[0].replace(/-json$/, '')); // 'bag-option-json' => 'bagOptionOpts'
 | 
						|
            opts[bagName] = {};
 | 
						|
        } else if ('ignore' !== v[3] && 'undefined' !== typeof v[4]) {
 | 
						|
            // set the default values (where 'undefined' is not an allowed value)
 | 
						|
            opts[toCamel(k)] = v[4];
 | 
						|
        }
 | 
						|
 | 
						|
        if (!aliases) {
 | 
						|
            aliases = [];
 | 
						|
        } else if ('string' === typeof aliases) {
 | 
						|
            aliases = aliases.split(',');
 | 
						|
        }
 | 
						|
        aliases.forEach(function(alias) {
 | 
						|
            if (alias in conf) {
 | 
						|
                throw new Error(
 | 
						|
                    "Cannot alias '" +
 | 
						|
                        alias +
 | 
						|
                        "' from '" +
 | 
						|
                        k +
 | 
						|
                        "': option already exists"
 | 
						|
                );
 | 
						|
            }
 | 
						|
            conf[alias] = v;
 | 
						|
        });
 | 
						|
    });
 | 
						|
};
 | 
						|
 | 
						|
CLI.main = function(cb, args) {
 | 
						|
    var leftovers = [];
 | 
						|
    var conf = defaultConf;
 | 
						|
    var opts = defaultOpts;
 | 
						|
 | 
						|
    if (!opts) {
 | 
						|
        throw new Error("you didn't call `CLI.parse(configuration)`");
 | 
						|
    }
 | 
						|
 | 
						|
    // TODO what's the existing API for this?
 | 
						|
    if (!args) {
 | 
						|
        args = process.argv.slice(2);
 | 
						|
    }
 | 
						|
 | 
						|
    var flag;
 | 
						|
    var cnf;
 | 
						|
    var typ;
 | 
						|
 | 
						|
    function grab(bag) {
 | 
						|
        var bagName = toBagName(bag);
 | 
						|
        if (bag !== flag.slice(0, bag.length)) {
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        opts[bagName][toCamel(flag.slice(bag.length))] = args.shift();
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    while (args.length) {
 | 
						|
        // take one off the top
 | 
						|
        flag = args.shift();
 | 
						|
 | 
						|
        // mind the gap
 | 
						|
        if ('--' === flag) {
 | 
						|
            leftovers = leftovers.concat(args);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
 | 
						|
        // help!
 | 
						|
        if (
 | 
						|
            '--help' === flag ||
 | 
						|
            '-h' === flag ||
 | 
						|
            '/?' === flag ||
 | 
						|
            'help' === flag
 | 
						|
        ) {
 | 
						|
            printHelp(conf);
 | 
						|
            process.exit(1);
 | 
						|
        }
 | 
						|
 | 
						|
        // only long names are actually used
 | 
						|
        if ('--' !== flag.slice(0, 2)) {
 | 
						|
            console.error("error: unrecognized flag '" + flag + "'");
 | 
						|
            process.exit(1);
 | 
						|
        }
 | 
						|
 | 
						|
        cnf = conf[flag.slice(2)];
 | 
						|
        if (!cnf) {
 | 
						|
            // look for arbitrary flags
 | 
						|
            if (bags.some(grab)) {
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
 | 
						|
            // other arbitrary args are not used
 | 
						|
            console.error("unrecognized elided flag '" + flag + "'");
 | 
						|
            process.exit(1);
 | 
						|
        }
 | 
						|
 | 
						|
        // encourage switching to non-aliased version
 | 
						|
        if (flag !== '--' + cnf[0]) {
 | 
						|
            console.warn(
 | 
						|
                "use of '" +
 | 
						|
                    flag +
 | 
						|
                    "' is deprecated, use '--" +
 | 
						|
                    cnf[0] +
 | 
						|
                    "' instead"
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        // look for xxx-json flags
 | 
						|
        if ('json' === cnf[3]) {
 | 
						|
            try {
 | 
						|
                var json = JSON.parse(args.shift());
 | 
						|
                var bagName = toBagName(cnf[0].replace(/-json$/, ''));
 | 
						|
                Object.keys(json).forEach(function(k) {
 | 
						|
                    opts[bagName][k] = json[k];
 | 
						|
                });
 | 
						|
            } catch (e) {
 | 
						|
                console.error("Could not parse option '" + flag + "' as JSON:");
 | 
						|
                console.error(e.message);
 | 
						|
                process.exit(1);
 | 
						|
            }
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
 | 
						|
        // set booleans, otherwise grab the next arg in line
 | 
						|
        typ = cnf[3];
 | 
						|
        // TODO --no-<whatever> to negate
 | 
						|
        if (Boolean === typ || 'boolean' === typ) {
 | 
						|
            opts[toCamel(cnf[0])] = true;
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
        opts[toCamel(cnf[0])] = args.shift();
 | 
						|
        continue;
 | 
						|
    }
 | 
						|
 | 
						|
    cb(leftovers, opts);
 | 
						|
};
 | 
						|
 | 
						|
function toCamel(str) {
 | 
						|
    return str.replace(/-([a-z0-9])/g, function(m) {
 | 
						|
        return m[1].toUpperCase();
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
function toBagName(bag) {
 | 
						|
    // trim leading and trailing '-'
 | 
						|
    bag = bag.replace(/^-+/g, '').replace(/-+$/g, '');
 | 
						|
    return toCamel(bag) + 'Opts'; // '--bag-option-' => bagOptionOpts
 | 
						|
}
 | 
						|
 | 
						|
function printHelp(conf) {
 | 
						|
    var flagLen = 0;
 | 
						|
    var typeLen = 0;
 | 
						|
    var defLen = 0;
 | 
						|
 | 
						|
    Object.keys(conf).forEach(function(k) {
 | 
						|
        flagLen = Math.max(flagLen, conf[k][0].length);
 | 
						|
        typeLen = Math.max(typeLen, conf[k][3].length);
 | 
						|
        if ('undefined' !== typeof conf[k][4]) {
 | 
						|
            defLen = Math.max(
 | 
						|
                defLen,
 | 
						|
                '(Default: )'.length + String(conf[k][4]).length
 | 
						|
            );
 | 
						|
        }
 | 
						|
    });
 | 
						|
 | 
						|
    Object.keys(conf).forEach(function(k) {
 | 
						|
        var v = conf[k];
 | 
						|
 | 
						|
        // skip aliases
 | 
						|
        if (v[0] !== k) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        var def = v[4];
 | 
						|
        if ('undefined' === typeof def) {
 | 
						|
            def = '';
 | 
						|
        } else {
 | 
						|
            def = '(default: ' + JSON.stringify(def) + ')';
 | 
						|
        }
 | 
						|
 | 
						|
        var msg =
 | 
						|
            ' --' +
 | 
						|
            v[0].padEnd(flagLen) +
 | 
						|
            ' ' +
 | 
						|
            v[3].padStart(typeLen + 1) +
 | 
						|
            ' ' +
 | 
						|
            (v[2] || '') +
 | 
						|
            ' ' +
 | 
						|
            def; /*.padStart(defLen)*/
 | 
						|
        // v[0] flagname
 | 
						|
        // v[1] short flagname
 | 
						|
        // v[2] description
 | 
						|
        // v[3] type
 | 
						|
        // v[4] default value
 | 
						|
        // v[5] aliases
 | 
						|
 | 
						|
        console.info(msg);
 | 
						|
    });
 | 
						|
}
 |