react / react-0.13.3 / examples / basic-commonjs / node_modules / browserify / node_modules / umd / node_modules / uglify-js / node_modules / yargs / lib / usage.js
80759 views// this file handles outputting usage instructions,1// failures, etc. keeps logging in one place.2var decamelize = require('decamelize'),3wordwrap = require('wordwrap'),4wsize = require('window-size');56module.exports = function (yargs) {7var self = {};89// methods for ouputting/building failure message.10var fails = [];11self.failFn = function (f) {12fails.push(f);13};1415var failMessage = null;16var showHelpOnFail = true;17self.showHelpOnFail = function (enabled, message) {18if (typeof enabled === 'string') {19message = enabled;20enabled = true;21}22else if (typeof enabled === 'undefined') {23enabled = true;24}25failMessage = message;26showHelpOnFail = enabled;27return self;28};2930self.fail = function (msg) {31if (fails.length) {32fails.forEach(function (f) {33f(msg);34});35} else {36if (showHelpOnFail) yargs.showHelp("error");37if (msg) console.error(msg);38if (failMessage) {39if (msg) console.error("");40console.error(failMessage);41}42if (yargs.getExitProcess()){43process.exit(1);44}else{45throw new Error(msg);46}47}48};4950// methods for ouputting/building help (usage) message.51var usage;52self.usage = function (msg) {53usage = msg;54};5556var examples = [];57self.example = function (cmd, description) {58examples.push([cmd, description || '']);59};6061var commands = [];62self.command = function (cmd, description) {63commands.push([cmd, description || '']);64};65self.getCommands = function () {66return commands;67};6869var descriptions = {};70self.describe = function (key, desc) {71if (typeof key === 'object') {72Object.keys(key).forEach(function (k) {73self.describe(k, key[k]);74});75}76else {77descriptions[key] = desc;78}79};80self.getDescriptions = function() {81return descriptions;82}8384var epilog;85self.epilog = function (msg) {86epilog = msg;87};8889var wrap = windowWidth();90self.wrap = function (cols) {91wrap = cols;92};9394self.help = function () {95var demanded = yargs.getDemanded(),96options = yargs.getOptions(),97keys = Object.keys(98Object.keys(descriptions)99.concat(Object.keys(demanded))100.concat(Object.keys(options.default))101.reduce(function (acc, key) {102if (key !== '_') acc[key] = true;103return acc;104}, {})105);106107var help = keys.length ? [ 'Options:' ] : [];108109// your application's commands, i.e., non-option110// arguments populated in '_'.111if (commands.length) {112help.unshift('');113114var commandsTable = {};115commands.forEach(function(command) {116commandsTable[command[0]] = {117desc: command[1],118extra: ''119};120});121122help = ['Commands:'].concat(formatTable(commandsTable, 5), help);123}124125// the usage string.126if (usage) {127var u = usage.replace(/\$0/g, yargs.$0);128if (wrap) u = wordwrap(0, wrap)(u);129help.unshift(u, '');130}131132// the options table.133var aliasKeys = (Object.keys(options.alias) || [])134.concat(Object.keys(yargs.parsed.newAliases) || []);135136keys = keys.filter(function(key) {137return !yargs.parsed.newAliases[key] && aliasKeys.every(function(alias) {138return -1 == (options.alias[alias] || []).indexOf(key);139});140});141142var switches = keys.reduce(function (acc, key) {143acc[key] = [ key ].concat(options.alias[key] || [])144.map(function (sw) {145return (sw.length > 1 ? '--' : '-') + sw146})147.join(', ')148;149return acc;150}, {});151152var switchTable = {};153keys.forEach(function (key) {154var kswitch = switches[key];155var desc = descriptions[key] || '';156var type = null;157158if (options.boolean[key]) type = '[boolean]';159if (options.count[key]) type = '[count]';160if (options.string[key]) type = '[string]';161if (options.normalize[key]) type = '[string]';162163var extra = [164type,165demanded[key]166? '[required]'167: null168,169defaultString(options.default[key], options.defaultDescription[key])170].filter(Boolean).join(' ');171172switchTable[kswitch] = {173desc: desc,174extra: extra175};176});177help.push.apply(help, formatTable(switchTable, 3));178179if (keys.length) help.push('');180181// describe some common use-cases for your application.182if (examples.length) {183examples.forEach(function (example) {184example[0] = example[0].replace(/\$0/g, yargs.$0);185});186187var examplesTable = {};188examples.forEach(function(example) {189examplesTable[example[0]] = {190desc: example[1],191extra: ''192};193});194195help.push.apply(help, ['Examples:'].concat(formatTable(examplesTable, 5), ''));196}197198// the usage string.199if (epilog) {200var e = epilog.replace(/\$0/g, yargs.$0);201if (wrap) e = wordwrap(0, wrap)(e);202help.push(e, '');203}204205return help.join('\n');206};207208self.showHelp = function (level) {209level = level || 'error';210console[level](self.help());211}212213// format the default-value-string displayed in214// the right-hand column.215function defaultString(value, defaultDescription) {216var string = '[default: ';217218if (value === undefined) return null;219220if (defaultDescription) {221string += defaultDescription;222} else {223switch (typeof value) {224case 'string':225string += JSON.stringify(value);226break;227case 'function':228string += '(' + (value.name.length ? decamelize(value.name, '-') : 'generated-value') + ')'229break;230default:231string += value;232}233}234235return string + ']';236}237238// word-wrapped two-column layout used by239// examples, options, commands.240function formatTable (table, padding) {241var output = [];242243// size of left-hand-column.244var llen = longest(Object.keys(table));245246// don't allow the left-column to take up247// more than half of the screen.248if (wrap) {249llen = Math.min(llen, parseInt(wrap / 2));250}251252// size of right-column.253var desclen = longest(Object.keys(table).map(function (k) {254return table[k].desc;255}));256257Object.keys(table).forEach(function(left) {258var desc = table[left].desc,259extra = table[left].extra,260leftLines = null;261262if (wrap) {263desc = wordwrap(llen + padding + 1, wrap)(desc)264.slice(llen + padding + 1);265}266267// if we need to wrap the left-hand-column,268// split it on to multiple lines.269if (wrap && left.length > llen) {270leftLines = wordwrap(2, llen)(left.trim()).split('\n');271left = '';272}273274var lpadding = new Array(275Math.max(llen - left.length + padding, 0)276).join(' ');277278var dpadding = new Array(279Math.max(desclen - desc.length + 1, 0)280).join(' ');281282if (!wrap && dpadding.length > 0) {283desc += dpadding;284}285286var prelude = ' ' + left + lpadding;287288var body = [ desc, extra ].filter(Boolean).join(' ');289290if (wrap) {291var dlines = desc.split('\n');292var dlen = dlines.slice(-1)[0].length293+ (dlines.length === 1 ? prelude.length : 0)294295if (extra.length > wrap) {296body = desc + '\n' + wordwrap(llen + 4, wrap)(extra)297} else {298body = desc + (dlen + extra.length > wrap - 2299? '\n'300+ new Array(wrap - extra.length + 1).join(' ')301+ extra302: new Array(wrap - extra.length - dlen + 1).join(' ')303+ extra304);305}306}307308if (leftLines) { // handle word-wrapping the left-hand-column.309var rightLines = body.split('\n'),310firstLine = prelude + rightLines[0],311lineCount = Math.max(leftLines.length, rightLines.length);312313for (var i = 0; i < lineCount; i++) {314var left = leftLines[i],315right = i ? rightLines[i] : firstLine;316317output.push(strcpy(left, right, firstLine.length));318}319} else {320output.push(prelude + body);321}322});323324return output;325}326327// find longest string in array of strings.328function longest (xs) {329return Math.max.apply(330null,331xs.map(function (x) { return x.length })332);333}334335// copy one string into another, used when336// formatting usage table.337function strcpy (source, destination, width) {338var str = ''339340source = source || '';341destination = destination || new Array(width).join(' ');342343for (var i = 0; i < destination.length; i++) {344var char = destination.charAt(i);345346if (char === ' ') char = source.charAt(i) || char;347348str += char;349}350351return str;352}353354// guess the width of the console window, max-width 100.355function windowWidth() {356return wsize.width ? Math.min(80, wsize.width) : null;357}358359// logic for displaying application version.360var version = null;361self.version = function (ver, opt, msg) {362version = ver;363};364365self.showVersion = function() {366if (typeof version === 'function') console.log(version());367else console.log(version);368};369370return self;371}372373374