#!/usr/bin/env node
'use strict';
var fs = require('fs')
  , program = require('commander')
  , chalk = require('chalk')
  , moment = require('moment')
  , liner = require('./liner');

/**
 * displayError
 * Display error messages in red
 * @param message
 */
function displayError(message) {
  console.log(chalk.red.bold(message));
}

/**
 * processLine
 * @param line
 */
function processLine(line) {
  var jsObj, text, output;
  try {
    text = '';
    jsObj = JSON.parse(line);
    if (program.timestamp) {
      text = jsObj.time + ' | ';
    } else if (program.prettydate) {
      text = moment(jsObj.time).format("MMMM Do YYYY, hh:mm:ss a") + ' | ';
    }
    if (program.expression) {
      try {
        var result = eval('jsObj.' + program.expression);
        if (result) {
          if (typeof result === 'boolean') {
            var subExps = program.expression.split(' ');
            text += eval('jsObj.' + subExps[0]);
            if (program.source) {
              text = JSON.stringify(jsObj, undefined, 2);
            }
          } else if (typeof result === 'string' || typeof result === 'number') {
            text += result;
          } else if (typeof result === 'object') {
            text += JSON.stringify(result);
          }
          output = text;
        }
      } catch (e) {
        output = '';
      }
    } else {
      output = text + JSON.stringify(jsObj, undefined, 2);
    }
  } catch (e) {
    displayError(e);
    process.exit(-1);
  }
  return output;
}

/**
 * main
 */
function main() {
  program
    .version('0.0.1')
    .usage('[options] bunyan.log')
    .option('-a, --array', 'Output results in array format')
    .option('-e, --expression [expression]', 'Filter using expression predicate')
    .option('-s, --source', 'Extract source (JSON) object')
    .option('-t, --timestamp', 'Show timestamp in results')
    .option('-p, --prettydate', 'Show pretty timestamp in results')
    .parse(process.argv);

  if (!program.args.length) {
    program.help();
  } else {
    var arrayOutput = (program['array'] && program.source)
      , source = fs.createReadStream(program.args[0]);

    if (arrayOutput) {
      console.log('[');
    }

    source.pipe(liner);
    source.on('error', function(err) {
      if (err.errno === 34) {
        displayError('Can\'t open ' + err.path);
      } else {
        displayError(err);
      }
      process.exit(-1);
    });
    liner.on('readable', function() {
      var lineIn, lineOut;
      while (lineIn = liner.read()) {
        lineOut = processLine(lineIn);
        console.log(lineOut + ((arrayOutput) ? ',' : ''));
      }
    });
    process.on('exit', function() {
      if (arrayOutput) {
        console.log(']');
      }
    });
  }
}

main();

@@ -178,16 +178,42 @@
 ner');%0A%0A
+var dateStart, dateEnd;%0A%0A%0A
 /**%0A * d
@@ -679,24 +679,202 @@
  %7C ';%0A    %7D%0A
+%0A    if (program.dates) %7B%0A      var logEntryDate = moment(jsObj.time).unix();%0A      if (logEntryDate %3C dateStart %7C%7C logEntryDate %3E dateEnd) %7B%0A        return null;%0A      %7D%0A    %7D%0A%0A
     if (prog
@@ -1859,24 +1859,87 @@
 ay format')%0A
+    .option('-d, --dates %5Bstart,end%5D', 'Specify a date range')%0A
     .option(
@@ -2449,24 +2449,391 @@
 %5B');%0A    %7D%0A%0A
+    if (program.dates) %7B%0A      var dates = program.dates.split(',');%0A      if (dates.length !== 2) %7B%0A        displayError('date range should consist of two commas separated dates');%0A        process.exit(-1);%0A      %7D%0A      dateStart = moment(dates%5B0%5D.trim()).unix();%0A      dateEnd = (dates%5B1%5D.trim()==='now') ? moment().unix() : moment(dates%5B1%5D.trim()).unix();%0A    %7D%0A%0A
     source.p
@@ -3182,24 +3182,49 @@
 ne(lineIn);%0A
+        if (lineOut) %7B%0A  
         cons
@@ -3270,16 +3270,26 @@
 : ''));%0A
+        %7D%0A
       %7D%0A

Support for date range queries.