gobblejs / gobble

The last build tool you'll ever need
333 stars 20 forks source link

piping #94

Open icambron opened 8 years ago

icambron commented 8 years ago

One thing that frustrates me about the gobble API is that I can't figure out how to compose things. Specifically, I want to do something like this:

var foo = function(node){
  return node.transform('stuff').transform('more-stuff');
}

gobble('src').pipe(foo).moveTo('place');
gobble('otherSrc').pipe(foo).moveTo('otherPlace');

I think pipe is probably a very simple function on Node that looks something like:

pipe(f){
  return f(this);
}

So...is there:

a) a way I'm missing to accomplish this? b) a way of hacking this in from userspace (I couldn't figure out how to monkey patch it)? c) a chance you'd take that addition as a PR?

martypdx commented 8 years ago

You can pass a function to .transform, isn't that the same thing?

icambron commented 8 years ago

Hmm, but the function passed to transform takes input and output dirs or files, not nodes. It's not obvious to me how to do this sort of thing with transform directly.

martypdx commented 8 years ago

File transformers take input, options where input is string contents of file and you return output:

gobble( 'src' ).transform( code => '/* bird */' + code ).moveTo( 'place' );
icambron commented 8 years ago

Right, but I want compose existing transformations and reuse those compositions. I don't need to work directly with the strings.

msegado commented 8 years ago

This is actually a common enough operation that there's been talk of adding a pipe operator into JS itself: https://github.com/mindeavor/es-pipeline-operator . That's a long way off though, so for now I could see the value of a pipe method for convenience. Biggest downside I see is that it increases the API surface area slightly.

Re. monkey patching, I think you can grab any Node instance and add the pipe method to the original prototype as follows (assuming the prototype chain is only one level deep; some experimentation may be needed):

nodeInstance.constructor.prototype.pipe = function pipe(f) { return f(this); };
icambron commented 8 years ago

Yeah, I played around with that for a bit yesterday and was surprised that I couldn't quite get anything to work. But could easily have been user error.

msegado commented 8 years ago

Odd. Give this a shot:

gobble('').constructor.prototype.pipe = function pipe(f) { return f(this); };

[EDIT: huh yeah, I see what you mean; not working for me]

msegado commented 8 years ago

OK... the Source and Merger nodes returned by gobble() are subclasses of Node, so we do need to go a level higher in the prototype chain. The following works, albeit with reliance on __proto__:

gobble([]).__proto__.__proto__.pipe = function pipe(f) { return f(this); };
icambron commented 8 years ago

Ah, right, I should have figured that out. Thanks!

msegado commented 8 years ago

Np! On Nov 27, 2015 5:38 PM, "Isaac Cambron" notifications@github.com wrote:

Ah, right, I should have figured that out. Thanks!

— Reply to this email directly or view it on GitHub https://github.com/gobblejs/gobble/issues/94#issuecomment-160223181.