diff --git a/fixture.js b/fixture.js
index da358aa..7ceb8fe 100755
--- a/fixture.js
+++ b/fixture.js
@@ -16,3 +16,14 @@ var cli = meow({
Object.keys(cli.flags).forEach(function (el) {
console.log(el);
});
+
+cli.stdinOrInput()
+ .then(function (input) {
+ input.forEach(function (element) {
+ console.log(element);
+ });
+ })
+ .catch(function (err) {
+ console.error(err.message);
+ process.exit(1);
+ });
diff --git a/index.js b/index.js
index 54e6126..707db77 100644
--- a/index.js
+++ b/index.js
@@ -8,11 +8,15 @@ var redent = require('redent');
var readPkgUp = require('read-pkg-up');
var loudRejection = require('loud-rejection');
var normalizePackageData = require('normalize-package-data');
+var getStdin = require('get-stdin');
+var Promise = require('pinkie-promise');
// get the uncached parent
delete require.cache[__filename];
var parentDir = path.dirname(module.parent.filename);
+global.Promise = Promise;
+
module.exports = function (opts, minimistOpts) {
loudRejection();
@@ -25,9 +29,20 @@ module.exports = function (opts, minimistOpts) {
cwd: parentDir,
normalize: false
}).pkg,
- argv: process.argv.slice(2)
+ argv: process.argv.slice(2),
+ inferType: false
}, opts);
+ minimistOpts = objectAssign({string: ['_']}, minimistOpts);
+
+ var index = minimistOpts.string.indexOf('_');
+
+ if (opts.inferType === false && index === -1) {
+ minimistOpts.string.push('_');
+ } else if (opts.inferType === true && index !== -1) {
+ minimistOpts.string.splice(index, 1);
+ }
+
if (Array.isArray(opts.help)) {
opts.help = opts.help.join('\n');
}
@@ -69,6 +84,19 @@ module.exports = function (opts, minimistOpts) {
flags: camelcaseKeys(argv),
pkg: pkg,
help: help,
- showHelp: showHelp
+ showHelp: showHelp,
+ stdinOrInput: function () {
+ if (!_ && process.stdin.isTTY) {
+ return Promise.reject(new Error('input required'));
+ }
+
+ if (_.length > 0) {
+ return Promise.resolve(_);
+ }
+
+ return getStdin().then(function (data) {
+ return [data];
+ });
+ }
};
};
diff --git a/package.json b/package.json
index 9b28ffe..40054a8 100644
--- a/package.json
+++ b/package.json
@@ -39,16 +39,19 @@
],
"dependencies": {
"camelcase-keys": "^2.0.0",
+ "get-stdin": "^5.0.1",
"loud-rejection": "^1.0.0",
"minimist": "^1.1.3",
"normalize-package-data": "^2.3.4",
"object-assign": "^4.0.1",
+ "pinkie-promise": "^2.0.0",
"read-pkg-up": "^1.0.1",
"redent": "^1.0.0",
"trim-newlines": "^1.0.0"
},
"devDependencies": {
"ava": "*",
+ "execa": "^0.1.1",
"indent-string": "^2.1.0",
"xo": "*"
}
diff --git a/readme.md b/readme.md
index 7ae8ab9..e3f0294 100644
--- a/readme.md
+++ b/readme.md
@@ -126,6 +126,15 @@ Default: `process.argv.slice(2)`
Custom arguments object.
+##### inferType
+
+Type: `boolean`
+Default: `false`
+
+Infer the argument type.
+
+By default, the argument `5` in `$ foo 5` becomes a string. Enabling this would infer it as a number.
+
#### minimistOptions
Type: `object`
diff --git a/test.js b/test.js
index f9f58d6..0274848 100644
--- a/test.js
+++ b/test.js
@@ -1,8 +1,11 @@
-import childProcess from 'child_process';
import test from 'ava';
import indentString from 'indent-string';
+import execa from 'execa';
+import pkg from './package.json';
import fn from './';
+global.Promise = Promise;
+
test('return object', t => {
const cli = fn({
argv: ['foo', '--foo-bar', '-u', 'cat'],
@@ -21,46 +24,29 @@ test('return object', t => {
t.is(cli.flags.unicorn, 'cat');
t.is(cli.pkg.name, 'meow');
t.is(cli.help, indentString('\nCLI app helper\n\nUsage\n foo ', ' '));
- t.end();
});
test('support help shortcut', t => {
const cli = fn(['unicorn', 'cat']);
t.is(cli.help, indentString('\nCLI app helper\n\nunicorn\ncat', ' '));
- t.end();
});
-test('spawn cli and show version', t => {
- t.plan(2);
+test('spawn cli and show version', async t => {
+ const {stdout} = await execa('./fixture.js', ['--version']);
- childProcess.execFile('./fixture.js', ['--version'], {
- cwd: __dirname
- }, (err, stdout) => {
- t.ifError(err);
- t.is(stdout.trim(), require('./package.json').version);
- });
+ t.is(stdout, pkg.version);
});
-test('spawn cli and show help screen', t => {
- t.plan(2);
+test('spawn cli and show help screen', async t => {
+ const {stdout} = await execa('./fixture.js', ['--help']);
- childProcess.execFile('./fixture.js', ['--help'], {
- cwd: __dirname
- }, (err, stdout) => {
- t.ifError(err);
- t.is(stdout, indentString('\nCustom description\n\nUsage\n foo \n', ' '));
- });
+ t.is(stdout, indentString('\nCustom description\n\nUsage\n foo ', ' '));
});
-test('spawn cli and test input', t => {
- t.plan(2);
+test('spawn cli and test input', async t => {
+ const {stdout} = await execa('./fixture.js', ['foo', '-u', 'cat']);
- childProcess.execFile('./fixture.js', ['-u', 'cat'], {
- cwd: __dirname
- }, (err, stdout) => {
- t.ifError(err);
- t.is(stdout, 'u\nunicorn\nmeow\n');
- });
+ t.is(stdout, 'u\nunicorn\nmeow\nfoo');
});
test.serial('pkg.bin as a string should work', t => {
@@ -72,10 +58,23 @@ test.serial('pkg.bin as a string should work', t => {
});
t.is(process.title, 'browser-sync');
- t.end();
});
test('single character flag casing should be preserved', t => {
t.ok(fn({argv: ['-F']}).flags.F);
- t.end();
+});
+
+test('type inference', t => {
+ t.is(fn({argv: ['5']}).input[0], '5');
+ t.is(fn({argv: ['5']}, {string: ['_']}).input[0], '5');
+ t.is(fn({argv: ['5'], inferType: true}).input[0], 5);
+ t.is(fn({argv: ['5'], inferType: true}, {string: ['foo']}).input[0], 5);
+});
+
+test('stdinOrInput', async t => {
+ const stdin = await execa.shell('echo \'foo bar\' | ./fixture.js');
+ const input = await execa('./fixture.js', ['foo', 'bar']);
+
+ t.is(stdin.stdout, 'meow\nfoo bar\n');
+ t.is(input.stdout, 'meow\nfoo\nbar');
});