forked from lix-project/lix-website
158 lines
3.9 KiB
Markdown
158 lines
3.9 KiB
Markdown
|
Chainsaw
|
||
|
========
|
||
|
|
||
|
Build chainable fluent interfaces the easy way in node.js.
|
||
|
|
||
|
With this meta-module you can write modules with chainable interfaces.
|
||
|
Chainsaw takes care of all of the boring details and makes nested flow control
|
||
|
super simple too.
|
||
|
|
||
|
Just call `Chainsaw` with a constructor function like in the examples below.
|
||
|
In your methods, just do `saw.next()` to move along to the next event and
|
||
|
`saw.nest()` to create a nested chain.
|
||
|
|
||
|
Examples
|
||
|
========
|
||
|
|
||
|
add_do.js
|
||
|
---------
|
||
|
|
||
|
This silly example adds values with a chainsaw.
|
||
|
|
||
|
var Chainsaw = require('chainsaw');
|
||
|
|
||
|
function AddDo (sum) {
|
||
|
return Chainsaw(function (saw) {
|
||
|
this.add = function (n) {
|
||
|
sum += n;
|
||
|
saw.next();
|
||
|
};
|
||
|
|
||
|
this.do = function (cb) {
|
||
|
saw.nest(cb, sum);
|
||
|
};
|
||
|
});
|
||
|
}
|
||
|
|
||
|
AddDo(0)
|
||
|
.add(5)
|
||
|
.add(10)
|
||
|
.do(function (sum) {
|
||
|
if (sum > 12) this.add(-10);
|
||
|
})
|
||
|
.do(function (sum) {
|
||
|
console.log('Sum: ' + sum);
|
||
|
})
|
||
|
;
|
||
|
|
||
|
Output:
|
||
|
Sum: 5
|
||
|
|
||
|
prompt.js
|
||
|
---------
|
||
|
|
||
|
This example provides a wrapper on top of stdin with the help of
|
||
|
[node-lazy](https://github.com/pkrumins/node-lazy) for line-processing.
|
||
|
|
||
|
var Chainsaw = require('chainsaw');
|
||
|
var Lazy = require('lazy');
|
||
|
|
||
|
module.exports = Prompt;
|
||
|
function Prompt (stream) {
|
||
|
var waiting = [];
|
||
|
var lines = [];
|
||
|
var lazy = Lazy(stream).lines.map(String)
|
||
|
.forEach(function (line) {
|
||
|
if (waiting.length) {
|
||
|
var w = waiting.shift();
|
||
|
w(line);
|
||
|
}
|
||
|
else lines.push(line);
|
||
|
})
|
||
|
;
|
||
|
|
||
|
var vars = {};
|
||
|
return Chainsaw(function (saw) {
|
||
|
this.getline = function (f) {
|
||
|
var g = function (line) {
|
||
|
saw.nest(f, line, vars);
|
||
|
};
|
||
|
|
||
|
if (lines.length) g(lines.shift());
|
||
|
else waiting.push(g);
|
||
|
};
|
||
|
|
||
|
this.do = function (cb) {
|
||
|
saw.nest(cb, vars);
|
||
|
};
|
||
|
});
|
||
|
}
|
||
|
|
||
|
And now for the new Prompt() module in action:
|
||
|
|
||
|
var util = require('util');
|
||
|
var stdin = process.openStdin();
|
||
|
|
||
|
Prompt(stdin)
|
||
|
.do(function () {
|
||
|
util.print('x = ');
|
||
|
})
|
||
|
.getline(function (line, vars) {
|
||
|
vars.x = parseInt(line, 10);
|
||
|
})
|
||
|
.do(function () {
|
||
|
util.print('y = ');
|
||
|
})
|
||
|
.getline(function (line, vars) {
|
||
|
vars.y = parseInt(line, 10);
|
||
|
})
|
||
|
.do(function (vars) {
|
||
|
if (vars.x + vars.y < 10) {
|
||
|
util.print('z = ');
|
||
|
this.getline(function (line) {
|
||
|
vars.z = parseInt(line, 10);
|
||
|
})
|
||
|
}
|
||
|
else {
|
||
|
vars.z = 0;
|
||
|
}
|
||
|
})
|
||
|
.do(function (vars) {
|
||
|
console.log('x + y + z = ' + (vars.x + vars.y + vars.z));
|
||
|
process.exit();
|
||
|
})
|
||
|
;
|
||
|
|
||
|
Installation
|
||
|
============
|
||
|
|
||
|
With [npm](http://github.com/isaacs/npm), just do:
|
||
|
npm install chainsaw
|
||
|
|
||
|
or clone this project on github:
|
||
|
|
||
|
git clone http://github.com/substack/node-chainsaw.git
|
||
|
|
||
|
To run the tests with [expresso](http://github.com/visionmedia/expresso),
|
||
|
just do:
|
||
|
|
||
|
expresso
|
||
|
|
||
|
|
||
|
Light Mode vs Full Mode
|
||
|
=======================
|
||
|
|
||
|
`node-chainsaw` supports two different modes. In full mode, every
|
||
|
action is recorded, which allows you to replay actions using the
|
||
|
`jump()`, `trap()` and `down()` methods.
|
||
|
|
||
|
However, if your chainsaws are long-lived, recording every action can
|
||
|
consume a tremendous amount of memory, so we also offer a "light" mode
|
||
|
where actions are not recorded and the aforementioned methods are
|
||
|
disabled.
|
||
|
|
||
|
To enable light mode simply use `Chainsaw.light()` to construct your
|
||
|
saw, instead of `Chainsaw()`.
|
||
|
|
||
|
|