<commit_before>'use strict';

var co = require('co');
var path = require('path');
var util = require('util');
var debug = require('debug');
var mkdirp = require('mkdirp');
var chokidar = require('chokidar');
var Cat = require('concat-with-sourcemaps');
var assign = require('object-assign');
var flatten = require('flatten');
var expand = require('globby');
var arrify = require('arrify');
// promisify `fs` methods
var thenify = require('thenify-all');
var fs = thenify(require('fs'), {}, ['writeFile']);
// locals
var utils = require('./utils');
var Emitter = require('./emitter');
// shorthands
var sep = path.sep;
var _ = debug('fly');
var clear = utils.defer(require('rimraf'));

function Fly(options) {
	var self = this;

	if (!(self instanceof Fly)) {
		throw new TypeError('Fly cannot be invoked without \'new\'');
	}

	options = assign({
		file: '.',
		host: {},
		plugins: []
	}, options || {});

	// shorter aliases
	var host = options.host;
	var file = options.file;
	var plugins = options.plugins;

	// ~ `super()`
	Emitter.call(self);

	// attach files & funcs into the curr instance
	assign(self, {
		file: file,
		plugins: plugins,
		root: path.dirname(file),
		alert: utils.alert,
		error: utils.error,
		defer: utils.defer,
		log: utils.log,
		host: (typeof host === 'function') ? assign(host, {default: host}) : host,
		debug: _,
		_: {
			filters: []
		},
		tasks: Object.keys(host).reduce(function (_, key) {
			var obj = {};
			obj[key] = host[key].bind(self);
			return assign(_, obj);
		}, {})
	});

	plugins.forEach(function (el) {
		if (!el.plugin) {
			throw new Error('Did you forget to `npm i -D ' + el.name + '`?');
		}
		// if (plugin.default) plugin = plugin.default
		el.plugin.call(self, debug(el.name.replace('-', ':')), _('load %o', el.name));
	});

	_('chdir %o', self.root);
	process.chdir(self.root);
}

// `Fly extends Emitter`...
util.inherits(Fly, Emitter);
module.exports = Fly;

/**
 * Compose a new, yeildable sequence.
 * Resets instance's glob, filters, and writer.
 *
 * @param  {String|Array} globs The glob selection
 * @return 											The current Fly instance.
 */
Fly.prototype.source = function (globs) {
	globs = arrify(globs);

	assign(this, {
		_: {
			filters: [],
			globs: flatten(globs)
		}
	});

	this._.cat = undefined;
	_('source %o', this._.globs);
	return this;
};

/**
 * Add filter / transform function.
 * Create a closure bound to the current Fly instance.
 *
 * @param {String|Function} name 		The name of filter || the callback
 * @param {Function} 				cb 			the function: (cb, options) => {}
*/
Fly.prototype.filter = function (name, cb) {
	var type = typeof name;

	if (type === 'function') {
		this.filter({cb: name});
	} else if (type === 'object') {
		this._.filters.push(name);
	} else {
		if (typeof this[name] === 'function') {
			throw new RangeError(name + ' method is already defined!');
		}

		this[name] = function (options) {
			var rest = [].slice.call(arguments);
			rest.shift(); // remove `options` argument

			debug('fly')(`${name} %o, %o`, options, rest);

			return this.filter({
				cb: cb,
				options: options,
				rest: rest
			});
		};
	}

	return this;
};

/**
 * Watch IO events within glob selections & run tasks
 * @param  {String} globs   The glob patterns to observe<commit_msg>fix es6 template string<commit_after>'use strict';

var co = require('co');
var path = require('path');
var util = require('util');
var debug = require('debug');
var mkdirp = require('mkdirp');
var chokidar = require('chokidar');
var Cat = require('concat-with-sourcemaps');
var assign = require('object-assign');
var flatten = require('flatten');
var expand = require('globby');
var arrify = require('arrify');
// promisify `fs` methods
var thenify = require('thenify-all');
var fs = thenify(require('fs'), {}, ['writeFile']);
// locals
var utils = require('./utils');
var Emitter = require('./emitter');
// shorthands
var sep = path.sep;
var _ = debug('fly');
var clear = utils.defer(require('rimraf'));

function Fly(options) {
	var self = this;

	if (!(self instanceof Fly)) {
		throw new TypeError('Fly cannot be invoked without \'new\'');
	}

	options = assign({
		file: '.',
		host: {},
		plugins: []
	}, options || {});

	// shorter aliases
	var host = options.host;
	var file = options.file;
	var plugins = options.plugins;

	// ~ `super()`
	Emitter.call(self);

	// attach files & funcs into the curr instance
	assign(self, {
		file: file,
		plugins: plugins,
		root: path.dirname(file),
		alert: utils.alert,
		error: utils.error,
		defer: utils.defer,
		log: utils.log,
		host: (typeof host === 'function') ? assign(host, {default: host}) : host,
		debug: _,
		_: {
			filters: []
		},
		tasks: Object.keys(host).reduce(function (_, key) {
			var obj = {};
			obj[key] = host[key].bind(self);
			return assign(_, obj);
		}, {})
	});

	plugins.forEach(function (el) {
		if (!el.plugin) {
			throw new Error('Did you forget to `npm i -D ' + el.name + '`?');
		}
		// if (plugin.default) plugin = plugin.default
		el.plugin.call(self, debug(el.name.replace('-', ':')), _('load %o', el.name));
	});

	_('chdir %o', self.root);
	process.chdir(self.root);
}

// `Fly extends Emitter`...
util.inherits(Fly, Emitter);
module.exports = Fly;

/**
 * Compose a new, yeildable sequence.
 * Resets instance's glob, filters, and writer.
 *
 * @param  {String|Array} globs The glob selection
 * @return 											The current Fly instance.
 */
Fly.prototype.source = function (globs) {
	globs = arrify(globs);

	assign(this, {
		_: {
			filters: [],
			globs: flatten(globs)
		}
	});

	this._.cat = undefined;
	_('source %o', this._.globs);
	return this;
};

/**
 * Add filter / transform function.
 * Create a closure bound to the current Fly instance.
 *
 * @param {String|Function} name 		The name of filter || the callback
 * @param {Function} 				cb 			the function: (cb, options) => {}
*/
Fly.prototype.filter = function (name, cb) {
	var type = typeof name;

	if (type === 'function') {
		this.filter({cb: name});
	} else if (type === 'object') {
		this._.filters.push(name);
	} else {
		if (typeof this[name] === 'function') {
			throw new RangeError(name + ' method is already defined!');
		}

		this[name] = function (options) {
			var rest = [].slice.call(arguments);
			rest.shift(); // remove `options` argument

			debug('fly')(name + ' %o, %o', options, rest);

			return this.filter({
				cb: cb,
				options: options,
				rest: rest
			});
		};
	}

	return this;
};

/**
 * Watch IO events within glob selections & run tasks
 * @param  {String} globs   The glob patterns to observe
{'fraction_non_alphanumeric': 0.1829787234042553, 'fraction_numerical': 0.00015197568389057752, 'mean_word_length': 3.5199175824175826, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, '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': '6043445', 'n_tokens_mistral': 2419, 'n_tokens_neox': 2219, 'n_words': 626}