You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					158 lines
				
				3.9 KiB
			
		
		
			
		
	
	
					158 lines
				
				3.9 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								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()`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 |