<commit_before># confidant

[![Build Status](https://travis-ci.org/gaye/confidant.png?branch=master)](https://travis-ci.org/gaye/confidant)

Configure your project for [ninja](https://martine.github.io/ninja/)'s parallel and incremental builds with pure js.

### Overview

Confidant will scan the filesystem rooted at the directory from which it
is run for files named `configure.js`. `configure.js` files look like this:

```js
// configure.js example
var denodeify = require('promise').denodeify;
var exec = require('mz/child_process').exec;
var fs = require('mz/fs');
var mkdirp = denodeify(require('mkdirp'));
var ncp = denodeify(require('ncp').ncp);
var rimraf = denodeify(require('rimraf'));
var rjs = require('requirejs');

module.exports = [
  {
    inputs: ['build.js', 'js/**/*.js'],
    output: 'app.js',
    rule: function() {
      return fs.readFile('./build.js', 'utf8').then(function(contents) {
        var config = JSON.parse(contents);
        return new Promise(function(resolve) {
          rjs.optimize(config, resolve);
        });
      });
    }
  },
  {
    inputs: ['index.html', 'app.js', 'style/**/*'],
    output: 'application.zip',
    rule: function() {
      return mkdirp('stage')
      .then(function() {
        return Promise.all([
          ncp('index.html', 'stage/index.html'),
          ncp('app.js', 'stage/app.js'),
          ncp('style', 'stage/style')
        ]);
      })
      .then(function() {
        return exec('zip application.zip index.html app.js style', {
          cwd: './stage'
        });
      })
      .then(function() {
        return fs.rename('./stage/application.zip', './application.zip');
      })
      .then(function() {
        return rimraf('./stage');
      });
    }
  }
];
```

And combine and convert them into a `build.ninja` file like so

```ninja
# This ninja build file was generated by confidant.
# Do not modify it directly. Instead, modify one or
# more configure.js files.

rule rule-0
  command = cd /home/gareth/Documents/confidant/test/fixtures/rjs && node -e "var denodeify = require('promise').denodeify;var exec = require('mz/child_process').exec;var fs = require('mz/fs');var mkdirp = denodeify(require('mkdirp'));var ncp = denodeify(require('ncp').ncp);var rimraf = denodeify(require('rimraf'));var rjs = require('requirejs');module.exports = [  {    inputs: ['build.js', 'js/**/*.js'],    output: 'app.js',    rule: function() {      return fs.readFile('./build.js', 'utf8').then(function(contents) {        var config = JSON.parse(contents);        return new Promise(function(resolve) {          rjs.optimize(config, resolve);        });      });    }  },  {    inputs: ['index.html', 'app.js', 'style/**/*'],    output: 'application.zip',    rule: function() {      return mkdirp('stage')      .then(function() {        return Promise.all([          ncp('index.html', 'stage/index.html'),          ncp('app.js', 'stage/app.js'),          ncp('style', 'stage/style')        ]);      })      .then(function() {        return exec('zip application.zip index.html app.js style', {          cwd: './stage'        });      })      .then(function() {        return fs.rename('./stage/application.zip', './application.zip');      })      .then(function() {        return rimraf('./stage');      });    }  }];(function rule() {    return fs.readFile('./build.js', 'utf8').then(function (contents) {      var config = JSON.parse(contents);      return new Promise(function (resolve) {        rjs.optimize(config, resolve);      });    });  })()"

build /home/gareth/Documents/confidant/test/fixtures/rjs/app.js: rule-0 /home/gareth/Documents/confidant/test/fixtures/rjs/build.js /home/gareth/Documents/confidant/test/fixtures/rjs/js/hello.js /home/gareth/Documents/confidant/test/fixtures/rjs/js/main.js

rule rule-1
  command = cd /home/gareth/Documents/confidant/test/fixtures/rjs && node -e "var denodeify = require('promise').denodeify;var exec = require('mz/child_process').exec;var fs = require('mz/fs');var mkdirp = denodeify(require('mkdirp'));var ncp = denodeify(require('ncp').ncp);var rimraf = denodeify(require('rimraf'));var rjs = require('requirejs');module.exports = [  {    inputs: ['build.js', 'js/**/*.js'],    output: 'app.js',    rule: function() {      return fs.readFile('./build.js', 'utf8').then(function(contents) {        var config = JSON.parse(contents);        return new Promise(function(resolve) {          rjs.optimize(config, resolve);        });      });    }  },  {    inputs: ['index.html', 'app.js', 'style/**/*'],    output: 'application.zip',    rule: function() {      return mkdirp('stage')      .then(function() {        return Promise.all([          ncp('index.html', 'stage/index.html'),          ncp('app.js', 'stage/app.js'),          ncp('style', 'stage/style')        ]);      })      .then(function() {        return exec('zip application.zip index.html app.js style', {          cwd: './stage'        });      })      .then(function() {        return fs.rename('./stage/application.zip', './application.zip');      })      .then(function() {        return rimraf('./stage');      });    }  }];(function rule() {    return mkdirp('stage').then(function () {      return Promise.all([ncp('index.html', 'stage/index.html'), ncp('app.js', 'stage/app.js'), ncp('style', 'stage/style')]);    }).then(function () {      return exec('zip application.zip index.html app.js style', {        cwd: './stage'      });    }).then(function () {      return fs.rename('./stage/application.zip', './application.zip');    }).then(function () {      return rimraf('./stage');    });  })()"

build /home/gareth/Documents/confidant/test/fixtures/rjs/application.zip: rule-1 /home/gareth/Documents/confidant/test/fixtures/rjs/index.html /home/gareth/Documents/confidant/test/fixtures/rjs/app.js /home/gareth/Documents/confidant/test/fixtures/rjs/style/app.css
```

This enables web devs to write their build rules in a comfortable
setting while leveraging ninja's ability to run independent tasks in
parallel and update targets incrementally.

### Installation

confidant is an npm package. You can install it globally with `npm
install -g confidant`. Note that it's only tested with nodejs and iojs
versions 0.12 and up.

### Usage

From `confidant -h`

```
usage: confidant [-h] [-v] [--exclude EXCLUDE] dir

Command line tool to configure your ninja build in pure js

Positional arguments:
  dir                Where to search for configure.js build files

Optional arguments:
  -h, --help         Show this help message and exit.
  -v, --version      Show program's version number and exit.
  --exclude EXCLUDE  Optional comma separated list of directories to
                     omit from fs scan
```<commit_msg>Update README with usage from node<commit_after># confidant

[![Build Status](https://travis-ci.org/gaye/confidant.png?branch=master)](https://travis-ci.org/gaye/confidant)

Configure your project for [ninja](https://martine.github.io/ninja/)'s parallel and incremental builds with pure js.

### Overview

Confidant will scan the filesystem rooted at the directory from which it
is run for files named `configure.js`. `configure.js` files look like this:

```js
// configure.js example
var denodeify = require('promise').denodeify;
var exec = require('mz/child_process').exec;
var fs = require('mz/fs');
var mkdirp = denodeify(require('mkdirp'));
var ncp = denodeify(require('ncp').ncp);
var rimraf = denodeify(require('rimraf'));
var rjs = require('requirejs');

module.exports = [
  {
    inputs: ['build.js', 'js/**/*.js'],
    output: 'app.js',
    rule: function() {
      return fs.readFile('./build.js', 'utf8').then(function(contents) {
        var config = JSON.parse(contents);
        return new Promise(function(resolve) {
          rjs.optimize(config, resolve);
        });
      });
    }
  },
  {
    inputs: ['index.html', 'app.js', 'style/**/*'],
    output: 'application.zip',
    rule: function() {
      return mkdirp('stage')
      .then(function() {
        return Promise.all([
          ncp('index.html', 'stage/index.html'),
          ncp('app.js', 'stage/app.js'),
          ncp('style', 'stage/style')
        ]);
      })
      .then(function() {
        return exec('zip application.zip index.html app.js style', {
          cwd: './stage'
        });
      })
      .then(function() {
        return fs.rename('./stage/application.zip', './application.zip');
      })
      .then(function() {
        return rimraf('./stage');
      });
    }
  }
];
```

And combine and convert them into a `build.ninja` file like so

```ninja
# This ninja build file was generated by confidant.
# Do not modify it directly. Instead, modify one or
# more configure.js files.

rule rule-0
  command = cd /home/gareth/Documents/confidant/test/fixtures/rjs && node -e "var denodeify = require('promise').denodeify;var exec = require('mz/child_process').exec;var fs = require('mz/fs');var mkdirp = denodeify(require('mkdirp'));var ncp = denodeify(require('ncp').ncp);var rimraf = denodeify(require('rimraf'));var rjs = require('requirejs');module.exports = [  {    inputs: ['build.js', 'js/**/*.js'],    output: 'app.js',    rule: function() {      return fs.readFile('./build.js', 'utf8').then(function(contents) {        var config = JSON.parse(contents);        return new Promise(function(resolve) {          rjs.optimize(config, resolve);        });      });    }  },  {    inputs: ['index.html', 'app.js', 'style/**/*'],    output: 'application.zip',    rule: function() {      return mkdirp('stage')      .then(function() {        return Promise.all([          ncp('index.html', 'stage/index.html'),          ncp('app.js', 'stage/app.js'),          ncp('style', 'stage/style')        ]);      })      .then(function() {        return exec('zip application.zip index.html app.js style', {          cwd: './stage'        });      })      .then(function() {        return fs.rename('./stage/application.zip', './application.zip');      })      .then(function() {        return rimraf('./stage');      });    }  }];(function rule() {    return fs.readFile('./build.js', 'utf8').then(function (contents) {      var config = JSON.parse(contents);      return new Promise(function (resolve) {        rjs.optimize(config, resolve);      });    });  })()"

build /home/gareth/Documents/confidant/test/fixtures/rjs/app.js: rule-0 /home/gareth/Documents/confidant/test/fixtures/rjs/build.js /home/gareth/Documents/confidant/test/fixtures/rjs/js/hello.js /home/gareth/Documents/confidant/test/fixtures/rjs/js/main.js

rule rule-1
  command = cd /home/gareth/Documents/confidant/test/fixtures/rjs && node -e "var denodeify = require('promise').denodeify;var exec = require('mz/child_process').exec;var fs = require('mz/fs');var mkdirp = denodeify(require('mkdirp'));var ncp = denodeify(require('ncp').ncp);var rimraf = denodeify(require('rimraf'));var rjs = require('requirejs');module.exports = [  {    inputs: ['build.js', 'js/**/*.js'],    output: 'app.js',    rule: function() {      return fs.readFile('./build.js', 'utf8').then(function(contents) {        var config = JSON.parse(contents);        return new Promise(function(resolve) {          rjs.optimize(config, resolve);        });      });    }  },  {    inputs: ['index.html', 'app.js', 'style/**/*'],    output: 'application.zip',    rule: function() {      return mkdirp('stage')      .then(function() {        return Promise.all([          ncp('index.html', 'stage/index.html'),          ncp('app.js', 'stage/app.js'),          ncp('style', 'stage/style')        ]);      })      .then(function() {        return exec('zip application.zip index.html app.js style', {          cwd: './stage'        });      })      .then(function() {        return fs.rename('./stage/application.zip', './application.zip');      })      .then(function() {        return rimraf('./stage');      });    }  }];(function rule() {    return mkdirp('stage').then(function () {      return Promise.all([ncp('index.html', 'stage/index.html'), ncp('app.js', 'stage/app.js'), ncp('style', 'stage/style')]);    }).then(function () {      return exec('zip application.zip index.html app.js style', {        cwd: './stage'      });    }).then(function () {      return fs.rename('./stage/application.zip', './application.zip');    }).then(function () {      return rimraf('./stage');    });  })()"

build /home/gareth/Documents/confidant/test/fixtures/rjs/application.zip: rule-1 /home/gareth/Documents/confidant/test/fixtures/rjs/index.html /home/gareth/Documents/confidant/test/fixtures/rjs/app.js /home/gareth/Documents/confidant/test/fixtures/rjs/style/app.css
```

This enables web devs to write their build rules in a comfortable
setting while leveraging ninja's ability to run independent tasks in
parallel and update targets incrementally.

### Installation

confidant is an npm package. You can install it globally with `npm
install -g confidant`. Note that it's only tested with nodejs and iojs
versions 0.12 and up.

### Usage

#### From the command line

From `confidant -h`

```
usage: confidant [-h] [-v] [--exclude EXCLUDE] dir

Command line tool to configure your ninja build in pure js

Positional arguments:
  dir                Where to search for configure.js build files

Optional arguments:
  -h, --help         Show this help message and exit.
  -v, --version      Show program's version number and exit.
  --exclude EXCLUDE  Optional comma separated list of directories to
                     omit from fs scan
```

#### From within nodejs

```js
var confidant = require('confidant');
// confidant can be invoked with an object representing its command line args
confidant({
  dir: './path/to/somewhere',
  exclude: 'bower_components,node_modules'  // Or whatever else
});
```
{'fraction_non_alphanumeric': 0.17502722323049003, 'fraction_numerical': 0.0015970961887477313, 'mean_word_length': 2.9654576856649397, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6550363', 'n_tokens_mistral': 4311, 'n_tokens_neox': 4204, 'n_words': 982}