Files
nexe/node_modules/celeri/lib/index.js
T
2011-11-26 17:00:12 -06:00

401 lines
7.1 KiB
JavaScript
Executable File

var tty = require('tty'),
fs = require('fs'),
Structr = require('structr'),
beanpole = require('beanpole'),
_buffer = '',
router = beanpole.router();
exports.utils = require('./utils');
//CLEAN ME!!!!!!!!!!!!!!!!!
_delimiterRepl = /\s+/g,
_delimiter = ' ';
var _queue = [],
_queueRunning = false;
/**
* queued commands
*/
exports.next = function(callback)
{
exports.queue(callback)();
return this;
}
exports.queue = function(callback)
{
return function()
{
var args = arguments,
listeners = [],
self = {
next: function()
{
var args = arguments;
listeners.forEach(function(listener)
{
listener.apply(null, args);
})
_queueRunning = true;
if(_queue.length)
{
_queue.shift()();
}
else
{
_queueRunning = false;
}
},
attach: function(callback)
{
listeners.push(callback);
}
}
_queue.push(function()
{
callback.apply(self, args);
});
if(!_queueRunning)
{
self.next();
}
return exports;
}
return exports;
}
/**
* spacing between arguments
*/
exports.delimiter = function(value)
{
if(!arguments.length) return _delimiter;
_delimiterRepl = new RegExp(value + '+','ig');
return _delimiter = value;
};
/**
* Converts CLI arguments to beanpole routes. Nifty huh?
*/
function _toRoute(type)
{
return type.replace(_delimiterRepl, '\/');
}
/**
* size of the terminal window
*/
exports.size = function()
{
return tty.getWindowSize();
}
/**
* number of columns in the terminal window (characters / width)
*/
exports.columns = function()
{
return exports.size()[1] || exports.size();
}
/**
* number of rows in the terminal window
*/
exports.rows = function()
{
return exports.size()[0];
}
var _inputPrefix = '> ';
exports.inputPrefix = function(prefix)
{
if(!arguments.length) return _inputPrefix;
return _inputPrefix = prefix || '';
}
exports.on = function(type, callback)
{
if(typeof type == 'object')
{
var disposables = [];
if(type instanceof Array)
{
for(var i = type.length; i--;)
{
disposables.push(exports.on(type[i], callback));
}
}
else
{
for(var t in type)
{
disposables.push(exports.on(t, type[t]));
}
}
return {
dispose: function()
{
disposables.forEach(function(disposable)
{
disposable.dispose();
});
}
};
}
return router.on('push /'+_toRoute(type), callback);
}
exports.emit = function(type, data)
{
//catch parse errors
try
{
return router.push(_toRoute(type), data, { meta: { passive: 1 } });
}
catch(e)
{
//console.log(e.stack);
}
return false;
}
exports.buffer = function(value, ignoreReplace)
{
if(!arguments.length) return _buffer;
_buffer = value;
return !ignoreReplace ? exports.replaceLine(value) : value;
}
/**
* Replaces the current line in the terminal window
*/
exports.replaceLine = function(buffer, cursorTo)
{
//need to clear the line before replacing it
process.stdout.clearLine();
//set the cursor to zero, otherwise we'll have padding we don't want
exports.cursor(0);
//write the buffer
process.stdout.write(buffer);
//set the cursor to the new position!
exports.cursor(cursorTo != undefined ? cursorTo : buffer.length);
return _buffer = buffer;
}
/**
* inserts text into the current line
*/
exports.insertText = function(str, position)
{
var buffer = exports.buffer();
exports.replaceLine(buffer.substr(0, position) + str + buffer.substr(position), position + str.length);
}
/**
* Takes a chunk of text out of the current line
*/
exports.spliceLine = function(position, length, newCursor)
{
var buffer = exports.buffer();
exports.replaceLine(buffer.substr(0, position) + buffer.substr(position + length), newCursor);
}
var _cursorPosition = 0;
/**
*/
exports.cursor = function(position)
{
if(!arguments.length) return _cursorPosition;
process.stdout.cursorTo(position);
return _cursorPosition = position;
}
function stringRep(key)
{
var chain = '';
for(var prop in key)
{
if(!key[prop]) continue;
if(key[prop] == true)
{
chain = prop+'-'+chain;
}
else
{
chain += key.name;
}
}
return chain;
}
exports.write = function(string)
{
process.stdout.write(string);
}
exports.newLine = function(buffer)
{
if(buffer) exports.write(buffer);
exports.write('\n');
exports.buffer('');
}
exports.open = function(ops)
{
if(ops)
{
if(ops.prefix) exports.inputPrefix(ops.prefix);
if(ops.delimiter) exports.delimiter(ops.delimiter);
}
if(exports.opened) return;
exports.opened = true;
stdin = process.openStdin();
stdin.setEncoding('utf8');
tty.setRawMode(true);
stdin.on('keypress', function(c, key)
{
//integer?
if(!key) key = { name: c.toString() }
var chain = stringRep(key),
emitSuccess = exports.emit(chain);
//not a handled item to boot? Probably enter, delete, left, right, up, etc. Append it.
if(!emitSuccess && c)
{
if(!_buffer.length)
{
exports.insertText(exports.inputPrefix(), _cursorPosition);
}
exports.insertText(c, _cursorPosition);
//exports.insertText(c, Math.max(_cursorPosition, exports.inputPrefix().length));
}
//new line? reset
if(key && key.name == 'enter')
{
//exports.replaceLine(exports.buffer().magenta);
process.stdout.write('\n');
_buffer = '';
_cursorPosition = 0;
//exports.insertText(exports.inputPrefix(), _cursorPosition);
//exports.cursor(0);
}
//for custom handlers: password, confirm, etc.
exports.emit('keypress', { char: c, key: key });
//character code?
if(key.name.length == 1)
{
exports.emit('charpress', c);
}
});
}
exports.parse = function(args)
{
var self = this;
args.forEach(function(arg)
{
var argParts = arg.split(':');
for(var i = argParts.length; i--;)
{
argParts[i] = encodeURIComponent(argParts[i]);
}
self.emit(argParts.join('/'));
});
}
fs.readdirSync( __dirname + '/modules').forEach(function(module)
{
require( __dirname + '/modules/'+module).plugin(exports);
});