nix-clap
Version:
Simple, lightweight, flexible, and comprehensive Un*x Command Line Argument Parsing for NodeJS
146 lines (124 loc) • 3.34 kB
JavaScript
;
const stripAnsi = require("strip-ansi");
/* eslint-disable no-magic-numbers,max-params, */
function camelCase(str) {
return str.split("-").reduce((cc, w) => `${cc}${w[0].toUpperCase()}${w.slice(1)}`);
}
function objEach(obj, iterator) {
for (const key in obj) {
iterator(obj[key], key);
}
}
function cbOrVal(x) {
return typeof x === "function" ? x() : x;
}
// specialized obj dup for nix-clap
function dup(obj) {
const copy = {};
if (obj) {
objEach(obj, (val, key) => {
copy[key] = val && val.constructor.name === "Object" ? Object.assign({}, val) : val;
});
}
return copy;
}
function noAnsiLen(str) {
return stripAnsi(str).length;
}
function padStr(str, w) {
const len = Math.max(0, w - noAnsiLen(str));
return `${str}${Array(len + 1).join(" ")}`;
}
function padStrRight(str, w) {
const len = w - noAnsiLen(str);
return `${Array(len + 1).join(" ")}${str}`;
}
function fitLine(strs, margin, indent, lineWidth) {
const out = [margin + strs[0]];
const add = (str, last) => {
let line = out[out.length - 1];
if (noAnsiLen(line) + str.length + 1 > lineWidth) {
out.push("");
line = margin + indent;
} else {
line += " ";
}
if (last) {
line += padStrRight(str, lineWidth - noAnsiLen(line));
} else {
line += str;
}
out[out.length - 1] = line;
};
const lastIx = strs.length - 1;
for (let i = 1; i < strs.length; i++) {
add(strs[i], i === lastIx);
}
return out.map(x => x.trimRight());
}
function fitLines(strs, margin, indent, leftWidth, lineWidth) {
if (strs.length === 0) return [];
if (strs.length === 1) return [`${margin}${strs[0]}`];
if (noAnsiLen(strs[0]) > leftWidth) {
const output = [`${margin}${strs[0]}`];
return output.concat(fitLine([indent].concat(strs.slice(1)), margin, indent, lineWidth));
} else {
return fitLine([padStr(strs[0], leftWidth)].concat(strs.slice(1)), margin, indent, lineWidth);
}
}
function makeDefaults(options) {
const defaults = {};
objEach(options, (opt, name) => {
if (opt.hasOwnProperty("default")) {
defaults[camelCase(name)] = opt.default;
}
});
return defaults;
}
function applyDefaults(defaults, ctx, src) {
objEach(defaults, (val, key) => {
if (!ctx.opts.hasOwnProperty(key)) {
ctx.opts[key] = val;
ctx.source[key] = src || "default";
}
});
}
function toBoolean(value) {
const x = value.toUpperCase();
return x && x !== "0" && x !== "FALSE" && x !== "NO";
}
function convertValue(type, value, spec) {
if (typeof value !== "string") return value;
if (type === "number") {
return parseInt(value, 10);
} else if (type === "float") {
return parseFloat(value);
} else if (!type || type === "boolean") {
return toBoolean(value);
} else if (spec && spec[type]) {
const customType = spec[type].constructor.name;
if (customType === "Function") {
return spec[type](value);
} else if (customType === "RegExp") {
const mx = value.match(spec[type]);
return mx ? mx[0] : undefined;
} else {
return spec[type];
}
}
return value;
}
module.exports = {
camelCase,
objEach,
cbOrVal,
dup,
fitLines,
padStr,
padStrRight,
makeDefaults,
applyDefaults,
toBoolean,
convertValue,
noop: () => {}
};