fh-fhc
Version:
A Command Line Interface for FeedHenry
166 lines (153 loc) • 3.6 kB
JavaScript
/* globals i18n */
// centralized stdout writer.
// TODO Refactor really old/stale code that can be replaced by color and console modules.
exports.doColor = doColor;
exports.write = write;
var fhc = require("../fhc.js");
var streams = {};
var net = require("net");
var util = require("util");
var tty = require("tty");
function doColor(stream) {
var conf = fhc.config.get("color");
if (!conf) {
return false;
}
if (conf === "always") {
return true;
}
return isatty(stream);
}
function isatty(stream) {
if (!tty.isatty) {
return true;
}
if (!stream) {
return false;
}
if (stream.isTTY) {
return true;
}
if (stream && (typeof stream.fd === "number")) {
stream.isTTY = tty.isatty(stream.fd);
}
return stream.isTTY;
}
function write(args, stream, lf, cb) {
if (typeof cb !== "function" && typeof lf === "function") {
cb = lf;
lf = null;
}
if (typeof cb !== "function" && typeof stream === "function") {
cb = stream;
stream = fhc.config.get("outfd");
}
stream = getStream(stream);
if (!lf) {
lf = isatty(stream);
}
if (!stream) {
if (cb) {
cb();
}
return false;
}
var isArray = Array.isArray(args);
if (!isArray) {
args = [args];
}
var msg = ""
, colored = doColor(stream)
, sep = isArray ? ',\n' : ' ';
msg = args.map(function(arg) {
if (typeof arg !== "string") {
if (fhc.config.get('usesysinspect')) {
return util.inspect(arg, false, 5, colored) + "\n";
}
return JSON.stringify(arg, null, fhc.config.get('jsondepth'));
}
if (!colored) {
arg = arg.replace(/\033\[[0-9;]*m/g, '');
}
return arg;
}).join(sep);
if (isArray) {
msg = "[" + msg + "]";
}
// listen to the "output" event to cancel/modify/redirect
fhc.output = {stream:stream, message:msg};
fhc.emit("output", fhc.output);
if (!fhc.output) {
return cb && cb(), false; // cancelled
}
stream = fhc.output.stream;
msg = fhc.output.message;
// use the \r\n in case we're in raw mode.
msg = msg.split(/\r?\n/).concat("").join(lf ? "\r\n" : "\n");
// output to stderr should be synchronous
if (stream === process.stderr ||stream.fd === 2) {
process.stderr.write(msg);
if (cb) {
cb();
}
return true;
}
var flushed = stream.write(msg);
if (flushed && cb) {
process.nextTick(cb);
} else {
stream.on("drain", cb);
}
return flushed;
}
var hadError = false;
function getStream(fd) {
if (hadError) {
return;
}
var stream;
if (!fd && fd !== 0) {
return process.stderr;
}
if (typeof fd === "string") {
fd = +fd;
}
if (fd && typeof fd === "object") {
stream = fd;
fd = fd.fd;
} else if (streams[fd]) {
stream = streams[fd];
} else {
switch (fd) {
case 1:
stream = process.stdout;
stream.fd = fd;
stream.writable = true;
break;
case 2:
stream = process.stderr;
stream.fd = fd;
stream.writable = true;
break;
default:
try {
stream = new net.Stream(fd);
if (!stream || !stream.writable) {
throw new Error(i18n._("Stream not writable"));
}
} catch (ex) {
// if this fails, then regular logging is most likely broken.
var er = new Error("cannot output to fd "+fd + ": "+
(ex.stack || ex.message).substr(7) + "\n");
console.error(er.stack);
hadError = true;
process.exit(1);
}
}
}
if (!stream || !stream.writable) {
return;
}
streams[fd] = stream;
return stream;
}