Skip to content

Commit

Permalink
add stdin or input handling
Browse files Browse the repository at this point in the history
  • Loading branch information
SamVerschueren committed Dec 16, 2015
1 parent 9812414 commit af1f9dc
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 31 deletions.
11 changes: 11 additions & 0 deletions fixture.js
Expand Up @@ -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);
});
32 changes: 30 additions & 2 deletions index.js
Expand Up @@ -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();

Expand All @@ -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');
}
Expand Down Expand Up @@ -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];
});
}
};
};
3 changes: 3 additions & 0 deletions package.json
Expand Up @@ -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": "*"
}
Expand Down
9 changes: 9 additions & 0 deletions readme.md
Expand Up @@ -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`
Expand Down
57 changes: 28 additions & 29 deletions 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'],
Expand All @@ -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 <input>', ' '));
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 <input>\n', ' '));
});
t.is(stdout, indentString('\nCustom description\n\nUsage\n foo <input>', ' '));
});

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 => {
Expand All @@ -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');
});

0 comments on commit af1f9dc

Please sign in to comment.