<commit_before># planify

[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Coverage Status][coveralls-image]][coveralls-url] [![Dependency status][david-dm-image]][david-dm-url] [![Dev Dependency status][david-dm-dev-image]][david-dm-dev-url]

[npm-url]:https://npmjs.org/package/planify
[downloads-image]:http://img.shields.io/npm/dm/planify.svg
[npm-image]:http://img.shields.io/npm/v/planify.svg
[travis-url]:https://travis-ci.org/IndigoUnited/node-planify
[travis-image]:http://img.shields.io/travis/IndigoUnited/node-planify.svg
[coveralls-url]:https://coveralls.io/r/IndigoUnited/node-planify
[coveralls-image]:https://img.shields.io/coveralls/IndigoUnited/node-planify.svg
[david-dm-url]:https://david-dm.org/IndigoUnited/node-planify
[david-dm-image]:https://img.shields.io/david/IndigoUnited/node-planify.svg
[david-dm-dev-url]:https://david-dm.org/IndigoUnited/node-planify#info=devDependencies
[david-dm-dev-image]:https://img.shields.io/david/dev/IndigoUnited/node-planify.svg

Plan a series of steps and display their output in a beautiful way.

Ever wanted to write a simple CLI that run a series of tasks with beautiful output? I did and I always ended up doing a thin wrapper repeatedly. This library provides a concise way to define these tasks while offering a handful of reporters to output the progress in a variety of ways.


## Installation

`$ npm install planify`


## Usage


The API is very simple, yet very powerful:

```js
const planify = require('planify');

planify({ reporter: 'blocks' })  // 'blocks' is the default reporter
.step('Synchronous step', (data) => {
    console.log('A sync step in which data is', data);
    data.foz = 'baz';  // Set some data to the next step
})
.step('Callback step', (data, done) => {
    console.log('A callback step in which data is', data);
    setTimeout(done, 500);
})
.step('Promise step', (data) => {
    console.log('A promise step in which data is', data);
    return new Promise((resolve) => {
        setTimeout(resolve, 500);
    });
})
.phase('Some group of steps', (phase) => {
    phase.step('Synchronous step inside a phase', (data) => {
        console.log('A sync step inside a phase in which data is', data);
    });
})
.run({ foo: 'bar' })
// Run returns a promise but callback style is also supported
.then(() => process.exit(), (err) => process.exit(1));
```

You can build nested phases as many times as you wish. API is chainable to make it easier to build your plan.

Running this would look like this:

<img src="./doc/example-blocks.png" width="600">

But changing the reporter to `spec` would look like this:

<img src="./doc/example-spec.png" width="600">

This is very similar to the [mocha](https://github.com/mochajs/mocha)'s spec reporter isn't it? In fact a lot of the API was inspired in it. Finally, changing the reporter to `progress` would show a beautiful progress bar instead:

<img src="./doc/example-progress.png" width="600">

As you can see, changing the appearance of the output is very easy. You may even allow your CLI users to choose the reporter by mapping `--reporter` to `options.reporter` by using [yargs](https://github.com/bcoe/yargs) or something similar. Cool huh?


### Reporters

The are several built-in reporters:

- `blocks`: blocks is the default reporter and it outputs everything, including stuff printed to the stdout and stderr.
- `spec`: spec reporter is very similar to mocha's spec reporter but stuff written to the stdout and stderr are hidden.
- `progress`: progress reporter shows a beautiful progress bar showing the overall progress of the plan; stuff written to the stdout and stderr are hidden.
- `json`: json reporter outputs a machine readable object with all the plan lifecycle events.
- `silent`: silent reporter which simply outputs nothing.

You can easily make your own reporter. Take a look at the [`json`](./reporters/json.js) reporter implementation for an example. Anyway, here's a simple example:

```js
// my-reporter.js
function myReporter(options) {
    /* ... */

    return {
        plan: {
            start() { /* ... */ },
        },
    };
}

module.exports = myReporter;

// example.js
const planify = require('planify');
const myReporter = require('./my-reporter');

const plan = planify({
    reporter: myReporter({ /* reporter options if any */ })
});

/* ... */
```

One cool feature of the reporters is that they can be async. You may return promises or use callbacks to do async reporting (.e.g.: save stuff to a database);<commit_msg>Update README.<commit_after># planify

[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Coverage Status][coveralls-image]][coveralls-url] [![Dependency status][david-dm-image]][david-dm-url] [![Dev Dependency status][david-dm-dev-image]][david-dm-dev-url]

[npm-url]:https://npmjs.org/package/planify
[downloads-image]:http://img.shields.io/npm/dm/planify.svg
[npm-image]:http://img.shields.io/npm/v/planify.svg
[travis-url]:https://travis-ci.org/IndigoUnited/node-planify
[travis-image]:http://img.shields.io/travis/IndigoUnited/node-planify.svg
[coveralls-url]:https://coveralls.io/r/IndigoUnited/node-planify
[coveralls-image]:https://img.shields.io/coveralls/IndigoUnited/node-planify.svg
[david-dm-url]:https://david-dm.org/IndigoUnited/node-planify
[david-dm-image]:https://img.shields.io/david/IndigoUnited/node-planify.svg
[david-dm-dev-url]:https://david-dm.org/IndigoUnited/node-planify#info=devDependencies
[david-dm-dev-image]:https://img.shields.io/david/dev/IndigoUnited/node-planify.svg

Plan a series of steps and display their output in a beautiful way.

Ever wanted to write a simple CLI that run a series of tasks with beautiful output? I did and I always ended up doing a thin wrapper repeatedly. This library provides a concise way to define these tasks while offering a handful of reporters to output the progress in a variety of ways.


## Installation

`$ npm install planify`


## Usage


The API is very simple, yet very powerful:

```js
const planify = require('planify');

planify({ reporter: 'blocks' })  // 'blocks' is the default reporter
.step('Synchronous step', (data) => {
    console.log('A sync step in which data is', data);
    data.foz = 'baz';  // Set some data to the next step
})
.step('Callback step', (data, done) => {
    console.log('A callback step in which data is', data);
    setTimeout(done, 500);
})
.step('Promise step', (data) => {
    console.log('A promise step in which data is', data);
    return new Promise((resolve) => {
        setTimeout(resolve, 500);
    });
})
.phase('Some group of steps', (phase) => {
    phase.step('Synchronous step inside a phase', (data) => {
        console.log('A sync step inside a phase in which data is', data);
    });
})
.run({ foo: 'bar' })
// Run returns a promise but callback style is also supported
.then(() => process.exit(), (err) => process.exit(1));
```

You can build nested phases as many times as you wish. API is chainable to make it easier to build your plan.

Running this would look like this:

<img src="./doc/example-blocks.png" width="600">

But changing the reporter to `spec` would look like this:

<img src="./doc/example-spec.png" width="600">

This is very similar to the [mocha](https://github.com/mochajs/mocha)'s spec reporter isn't it? In fact a lot of the API was inspired in it. Finally, changing the reporter to `progress` would show a beautiful progress bar instead:

<img src="./doc/example-progress.png" width="600">

As you can see, changing the appearance of the output is very easy. You may even allow your CLI users to choose the reporter by mapping `--reporter` to `options.reporter` by using [yargs](https://github.com/bcoe/yargs) or something similar. Cool huh?


### Reporters

The are several built-in reporters:

- `blocks`: blocks is the default reporter and it outputs everything, including stuff printed to the stdout and stderr.
- `spec`: spec reporter is very similar to mocha's spec reporter but stuff written to the stdout and stderr are hidden.
- `progress`: progress reporter shows a beautiful progress bar showing the overall progress of the plan; stuff written to the stdout and stderr are hidden.
- `json`: json reporter outputs a machine readable object with all the plan lifecycle events.
- `silent`: silent reporter which simply outputs nothing.

You can easily make your own reporter. Take a look at the [`json`](./reporters/json.js) reporter implementation for an example. You may use a custom reporter like this:

```js
// my-reporter.js
function myReporter(options) {
    /* ... */

    return {
        plan: {
            start() { /* ... */ },
        },
    };
}

module.exports = myReporter;

// example.js
const planify = require('planify');
const myReporter = require('./my-reporter');

const plan = planify({
    reporter: myReporter({ /* reporter options if any */ })
});

/* ... */
```

One cool feature of the reporters is that they can be async. You may return promises or use callbacks to do async reporting (.e.g.: save stuff to a database).
{'fraction_non_alphanumeric': 0.1365965333042625, 'fraction_numerical': 0.003488498855336313, 'mean_word_length': 4.015855658829961, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 25, 'https://': 20, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2291802', 'n_tokens_mistral': 2885, 'n_tokens_neox': 2765, 'n_words': 983}