Skip to content

Instantly share code, notes, and snippets.

@jcayzac
Created May 10, 2012 07:33
Show Gist options
  • Save jcayzac/2651693 to your computer and use it in GitHub Desktop.
Save jcayzac/2651693 to your computer and use it in GitHub Desktop.
"use strict";
var fs = require('fs'),
path = require('path'),
events = require('events'),
async = require('async');
function FolderTraversal(dir, filter) {
function defaultFilter(v) {
return v;
}
events.EventEmitter.prototype.constructor.call(this);
var queue = [], busy = false, remaining = 0, errors = [];
filter = filter || defaultFilter;
var filterType = Object.prototype.toString.call(filter).slice(8, -1);
switch (filterType) {
case 'String':
filter = new RegExp(filter);
case 'RegExp':
filter = filter.exec.bind(filter);
case 'Function':
break;
default:
throw new TypeError('filter must be a String, a RegExp or a Function');
}
var self = this;
self.on('dir', function (folder, entries) {
remaining += entries.length;
entries.forEach(function (entry) {
var fullEntry = path.join(folder, entry);
fs.stat(path.join(dir, fullEntry), function (err, stat) {
if (err) {
errors.push(err);
} else {
var m;
if (stat && stat.isDirectory()) {
self.emit('run', fullEntry);
} else if ((m = filter(entry))) {
self.emit('file', fullEntry, m);
}
}
if (--remaining === 0) {
self.emit('end', errors.length ? errors : null);
}
})
});
});
self.on('processQueue', function() {
queue.forEach(function (folder) {
fs.readdir(path.join(dir, folder), function (err, entries) {
if (err) {
errors.push(err);
} else {
self.emit('dir', folder, entries);
}
if (--remaining === 0) {
self.emit('end', errors.length ? errors : null);
}
});
});
queue = [];
busy = false;
});
self.on('run', function (folder) {
++remaining;
queue.push(folder || null);
if (!busy) {
process.nextTick(function () {
self.emit('processQueue');
});
busy = true;
}
});
}
FolderTraversal.prototype = Object.create(events.EventEmitter.prototype);
FolderTraversal.prototype.constructor = FolderTraversal;
FolderTraversal.traverse = function(dir, filter, iterator, callback) {
var traverse = new FolderTraversal(dir, filter);
traverse.on('file', iterator);
traverse.on('end', function(err) {
callback(err);
});
traverse.emit('run');
};
/* Example:
FolderTraversal.traverse(
'assets',
/^([^@]+)(?:@([^\.]+))?\.(.+)$/,
function(fn, match) {
console.log([fn, match]);
},
function(errors) {
console.log('EOT. Errors: ' + errors);
}
);
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment