UNPKG

clp

Version:

A tiny and fast command line arguments parser.

170 lines (145 loc) 5.16 kB
"use strict"; var isNumber = require("is-number"), matchIt = require("match-it"), lastChar = require("last-char"); // Part of the code from this file was originally written by // the contributors in https://github.com/substack/minimist function hasKey(obj, keys) { var o = obj; keys.slice(0, -1).forEach(function (key) { o = o[key] || {}; }); var key = keys[keys.length - 1]; return key in o; } /** * clp * Parses the cli arguments. * * @name clp * @function * @param {Array} args The arguments to parse (default: the process arguments). * @returns {Object} An object containing the parsed arguments. */ module.exports = function clp(args) { args = args || process.argv.slice(2); var flags = { bools: {}, strings: {} }, argv = { _: [] }, notFlags = [], dashDashIndex = args.indexOf("--"); function argDefined(key, arg) { return flags.allBools && /^--[^=]+$/.test(arg) || flags.strings[key] || flags.bools[key] || aliases[key]; } function setArg(key, val, arg) { if (arg && flags.unknownFn && !argDefined(key, arg)) { if (flags.unknownFn(arg) === false) return; } var value = !flags.strings[key] && isNumber(val) ? Number(val) : val; setKey(argv, key.split("."), value); } function setKey(obj, keys, value) { var o = obj; keys.slice(0, -1).forEach(function (key) { if (o[key] === undefined) o[key] = {}; o = o[key]; }); var key = keys[keys.length - 1]; if (o[key] === undefined || flags.bools[key] || typeof o[key] === "boolean") { o[key] = value; } else if (Array.isArray(o[key])) { o[key].push(value); } else { o[key] = [o[key], value]; } } function aliasIsBoolean(key) { return aliases[key].some(function (x) { return flags.bools[x]; }); } if (~dashDashIndex) { notFlags = args.slice(dashDashIndex + 1); args = args.slice(0, dashDashIndex); } for (var i = 0; i < args.length; ++i) { var arg = args[i], oneOf = { doubleDashEqual: matchIt(arg, /^--([^=]+)=([\s\S]*)$/), negative: matchIt(arg, /^--no-(.+)/), doubleDash: matchIt(arg, /^--(.+)/) }; if (oneOf.doubleDashEqual.length) { var key = oneOf.doubleDashEqual[1], value = oneOf.doubleDashEqual[2]; setArg(key, value, arg); } else if (oneOf.negative.length) { setArg(oneOf.negative[1], false, arg); } else if (oneOf.doubleDash.length) { var _key = oneOf.doubleDash[1], next = args[i + 1]; if (next !== undefined && next.charAt(0) !== "-") { setArg(_key, next, arg); i++; } else { var isTrue = next === "true"; if (isTrue || next === "false") { setArg(_key, isTrue, arg); i++; } else { setArg(_key, flags.strings[_key] ? "" : true, arg); } } } else if (/^-[^-]+/.test(arg)) { var letters = arg.slice(1, -1).split(""), broken = false; for (var j = 0; j < letters.length; ++j) { var _next = arg.slice(j + 2), cLetter = letters[j]; if (_next === "-") { setArg(cLetter, _next, arg); continue; } if (/[A-Za-z]/.test(cLetter) && _next.includes("=")) { setArg(cLetter, _next.split("=")[1], arg); broken = true; break; } if (/[A-Za-z]/.test(cLetter) && /-?\d+(\.\d*)?(e-?\d+)?$/.test(_next)) { setArg(cLetter, _next, arg); broken = true; break; } var nextLetter = letters[j + 1]; if (nextLetter && nextLetter.match(/\W/)) { setArg(cLetter, _next, arg); broken = true; break; } else { setArg(cLetter, flags.strings[cLetter] ? "" : true, arg); } } var _key2 = lastChar(arg); if (!broken && _key2 !== "-") { var nextArg = args[i + 1]; if (nextArg && !/^(-|--)[^-]/.test(nextArg)) { setArg(_key2, args[i + 1], arg); i++; } else if (nextArg && /true|false/.test(nextArg)) { setArg(_key2, nextArg === "true", arg); i++; } else { setArg(_key2, true, arg); } } } else { argv._.push(flags.strings["_"] || !isNumber(arg) ? arg : Number(arg)); } } notFlags.forEach(function (key) { argv._.push(key); }); return argv; };