thedesk/app/node_modules/chainsaw/README.markdown
2018-02-18 16:29:06 +09:00

3.9 KiB

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 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, 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,
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().