UNPKG

argv-walk

Version:

Walk an argv array with a handler function using minimist conventions

151 lines (134 loc) 4.39 kB
// @ts-check // This code was extracted from [minimist](https://github.com/substack/minimist) v1.2.5 (MIT) and has been modified. function walkArgv(argv, opts) { var flags = { bools: {} }; var notFlags = []; if (opts && opts.onArg && typeof opts.onArg === 'function') { flags.onArg = opts.onArg; } else { throw new Error('onArg handler must be defined'); } if (typeof opts['boolean'] === 'boolean' && opts['boolean']) { flags.allBools = true; } else { [] .concat(opts['boolean']) .filter(Boolean) .forEach(function (key) { flags.bools[key] = true; }); } if (argv.indexOf('--') !== -1) { notFlags = argv.slice(argv.indexOf('--') + 1); argv = argv.slice(0, argv.indexOf('--')); } function setArg(key, value, arg, index, indexOffset, compoundIndex, isShort, isStrict) { if (key === '__proto__') { // Prevent prototype pollution return; } if ( flags.onArg({ compoundIndex, index, indexOffset: indexOffset ? indexOffset : 0, isShort: !!isShort, isStrict: !!isStrict, item: arg, key, value }) === false ) { flags.stop = true; } } for (var i = 0; i < argv.length; i++) { var key, next; var arg = argv[i]; if (/^--.+=/.test(arg)) { // Using [\s\S] instead of . because js doesn't support the // 'dotall' regex modifier. See: // http://stackoverflow.com/a/1068308/13216 var m = arg.match(/^--([^=]+)=([\s\S]*)$/); key = m[1]; var value = m[2]; if (flags.bools[key]) { value = value !== 'false'; } setArg(key, value, arg, i, 0, undefined, false, true); } else if (/^--no-.+/.test(arg)) { key = arg.match(/^--no-(.+)/)[1]; setArg(key, false, arg, i); } else if (/^--.+/.test(arg)) { key = arg.match(/^--(.+)/)[1]; next = argv[i + 1]; if ( next !== undefined && !/^-/.test(next) && !flags.bools[key] && !flags.allBools ) { setArg(key, next, arg, i, 1); i++; } else if (/^(true|false)$/.test(next)) { setArg(key, next === 'true', arg, i, 1); i++; } else { setArg(key, true, arg, i); } } else if (/^-[^-]+/.test(arg)) { var letters = arg.slice(1, -1).split(''); var broken = false; for (var j = 0; j < letters.length; j++) { next = arg.slice(j + 2); if (next === '-') { setArg(letters[j], next, arg, i, 0, j, true); continue; } if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) { // compoundIndex (j) is omitted because '-v=1' is not a compound argument setArg(letters[j], next.split('=')[1], arg, i, 0, undefined, true, true); broken = true; break; } if (/[A-Za-z]/.test(letters[j]) && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { // compoundIndex (j) is omitted because '-n123' is not a compound argument setArg(letters[j], next, arg, i, 0, undefined, true); broken = true; break; } if (letters[j + 1] && letters[j + 1].match(/\W/)) { // compoundIndex (j) is omitted for single short arguments (see slashBreak test) setArg(letters[j], arg.slice(j + 2), arg, i, 0, j > 0 ? j : undefined, true); broken = true; break; } else { setArg(letters[j], true, arg, i, 0, j, true); } } key = arg.slice(-1)[0]; if (!broken && key !== '-') { // compoundIndex is undefined for single short arguments var compoundIndex = letters.length > 0 ? letters.length : undefined; if (argv[i + 1] && !/^(-|--)[^-]/.test(argv[i + 1]) && !flags.bools[key]) { setArg(key, argv[i + 1], arg, i, 1, compoundIndex, true); i++; } else if (argv[i + 1] && /^(true|false)$/.test(argv[i + 1])) { setArg(key, argv[i + 1] === 'true', arg, i, 1, compoundIndex, true); i++; } else { setArg(key, true, arg, i, 0, compoundIndex, true); } } } else { setArg(null, arg, arg, i); } if (flags.stop) { break; } } notFlags.forEach(function (arg, idx) { setArg('--', arg, arg, argv.length + idx); }); } module.exports = walkArgv;