m19c / gulp-run

Pipe to shell commands in gulp
ISC License
151 stars 25 forks source link

Is it possible to write task taking stdin using `gulp-run` #16

Closed kompot closed 10 years ago

kompot commented 10 years ago

Hi, is it possible to write a task taking stdin as input and forwarding it further? Something like

gulp.task('task-taking-stdin', function() {
  var run = require('gulp-run');
  run.exec().pipe(someOtherTask())
});

Could you please guide me if that's something possible to be achieved with gulp-run.

cbarrick commented 10 years ago

The run function is actually a constructor, where the new keyword is optional. The constructed object is a stream, which, when written to, spawns a new process with the written data as the stdin. The .exec method is simply an alias for .write. So run('my-command').exec('my-stdin') is how you run a command with a specific stdin. .exec can take whatever is most convenient (strings, buffers, or Vinyl files) to use as stdin, but note that every call to .exec/.write spawns a separate process.

I'm not entirely clear as to what you are asking, so forgive me if the following examples don't cover your use case.


Trying to use process.stdin (i.e. tty input) as the stdin of your command?

In general, I don't recommend doing that. If you have cases where you need different inputs to your command, I would write separate tasks and hard-code the input:

gulp.task('task-A', function () {
  run('my-command').exec('some input');
}
gulp.task('task-B', function () {
  run('my-command').exec('different input');
}

If you absolutely must use process.stdin as the stdin of the command, try creating a Vinyl file from process.stdin and passing that to .exec.


Creating a command pipeline like you would in a shell/make?

A command that looks like this in a shell:

command1 | command2 | command3

could look like this with gulp-run:

run('command1').exec()
  .pipe(run('command2'))
  .pipe(run('command3'));

or, even better, like this:

run('command1 | command2 | command3').exec();

Using the output of a command as the input to another plugin?

Like other gulp plugins, you can pipe the output to another plugin

run('command1 | command2 | command3').exec()
  .pipe(some_other_plugin);

Using the output of another plugin as the stdin of a command?

The other plugin probably has a pipe method that's compatible with gulp-run

some_other_plugin()
  .pipe(run('command1'));
kompot commented 10 years ago

Thank you for your effort for such a detailed explanation. Really cleared things up.

What I'm trying to achieve is that I run external (to gulp) command like

cat file.txt | gulp taskThatTakesStdin

I guess this is the way to go "try creating a Vinyl file from process.stdin and passing that to .exec"?

cbarrick commented 10 years ago

Could you run that external command from within your gulp task instead?

You can't pipe out to another task, but you can wrap your existing task. Something like:

gulp.task('new-task', function () {
    run('cat file.txt').exec()
        .pipe(foo())
        .pipe(bar());
})

where the old task was

gulp.task('old-task', function () {
    foo()
        .pipe(bar());
})
kompot commented 10 years ago

Actually I think I can. The task was to check whether git staged content passes eslint/jscs tests.

So I'll try to run git cat-file -p /path/to/staged/file within gulp and not in a pre-commit hook.

Thanks for your participation!