2 const path = require('path');
3 const buildMinimistOptions = require('minimist-options');
4 const minimist = require('minimist');
5 const camelcaseKeys = require('camelcase-keys');
6 const decamelizeKeys = require('decamelize-keys');
7 const trimNewlines = require('trim-newlines');
8 const redent = require('redent');
9 const readPkgUp = require('read-pkg-up');
10 const loudRejection = require('loud-rejection');
11 const normalizePackageData = require('normalize-package-data');
13 // Prevent caching of this module so module.parent is always accurate
14 delete require.cache[__filename];
15 const parentDir = path.dirname(module.parent.filename);
17 module.exports = (helpMessage, opts) => {
20 if (typeof helpMessage === 'object' && !Array.isArray(helpMessage)) {
25 opts = Object.assign({
30 argv: process.argv.slice(2),
38 let minimistOpts = Object.assign({
42 minimistOpts = decamelizeKeys(minimistOpts, '-', {exclude: ['stopEarly', '--']});
45 delete minimistOpts.arguments;
48 minimistOpts = buildMinimistOptions(minimistOpts);
51 const argv = minimist(opts.argv, minimistOpts);
52 let help = redent(trimNewlines((opts.help || '').replace(/\t+\n*$/, '')), 2);
54 normalizePackageData(pkg);
56 process.title = pkg.bin ? Object.keys(pkg.bin)[0] : pkg.name;
58 let description = opts.description;
59 if (!description && description !== false) {
60 description = pkg.description;
63 help = (description ? `\n ${description}\n` : '') + (help ? `\n${help}\n` : '\n');
65 const showHelp = code => {
67 process.exit(typeof code === 'number' ? code : 2);
70 const showVersion = () => {
71 console.log(typeof opts.version === 'string' ? opts.version : pkg.version);
75 if (argv.version && opts.autoVersion) {
79 if (argv.help && opts.autoHelp) {
86 const flags = camelcaseKeys(argv, {exclude: ['--', /^\w$/]});