--- /dev/null
+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()`.
+
+