function REPLServer()

in shell/jrepl.js [71:283]


function REPLServer(prompt, stream, eval, useGlobal, ignoreUndefined) {
  var self = this;

  self.useGlobal = useGlobal;

  self.eval = eval || function(code, context, file, cb) {
    var err, result;
    try {
      if (useGlobal) {
        result = vm.runInThisContext(code, file);
      } else {
        result = vm.runInContext(code, context, file);
      }
    } catch (e) {
      err = e;
    }
    cb(err, result);
  };

  self.resetContext();
  self.bufferedCommand = '';

  if (stream) {
    // We're given a duplex socket
    if (stream.stdin || stream.stdout) {
      self.outputStream = stream.stdout;
      self.inputStream = stream.stdin;
    } else {
      self.outputStream = stream;
      self.inputStream = stream;
    }
  } else {
    self.outputStream = process.stdout;
    self.inputStream = process.stdin;
    process.stdin.resume();
  }

  self.prompt = (prompt != undefined ? prompt : '===> ');

  function complete(text, callback) {
    self.complete(text, callback);
  }

  var rli = rl.createInterface(self.inputStream, self.outputStream, complete);
  self.rli = rli;

  this.commands = {};
  defineDefaultCommands(this);

  if (rli.enabled && !exports.disableColors &&
      exports.writer === util.inspect) {
    // Turn on ANSI coloring.
    exports.writer = function(obj, showHidden, depth) {
      return util.inspect(obj, showHidden, depth, true);
    };
  }

  rli.setPrompt(self.prompt);

  var sawSIGINT = false;
  rli.on('SIGINT', function() {
    if (sawSIGINT) {
      rli.close();
      process.exit();
    }

    rli.line = '';

    if (!(self.bufferedCommand && self.bufferedCommand.length > 0) &&
        rli.line.length === 0) {
      rli.output.write('\n(^C again if you really want to quit)\n');
      sawSIGINT = true;
    } else {
      rli.output.write('\n');
    }

    self.bufferedCommand = '';
    self.displayPrompt();
  });

  rli.addListener('line', function(cmd) {

    
    
    
    function isPromise(ret) {
//      console.log('isPromise', ret);
      if (ret && ret.constructor && ret.constructor.name == 'Promise') {
        ret.then(function(result) {
//          console.log('=========================Promise.then with result:', result);
          if (result && result.constructor && result.constructor.name == 'Session') {
//            console.log('=========================Sesssion');
            context.session = result;
            context.sessionFactory = context.session.sessionFactory;
            context.session.allowCreateUnmappedTable = true;
            context.db = context.sessionFactory.db();
          } else {
//            console.log("----------------not a session--------");
//            console.log(result);
          }
//          console.log('isPromise.then calling finish(null, result)');
          finish(null, result);
          }, function(e) {
//            console.log('isPromise found', e);
            finish(e);
            });
        return true;
      }
      return false;
    }
    sawSIGINT = false;
    var skipCatchall = false;
    cmd = trimWhitespace(cmd);

    // Check to see if a REPL keyword was used. If it returns true,
    // display next prompt and return.
    if (cmd && cmd.charAt(0) === '.') {
      var matches = cmd.match(/^(\.[^\s]+)\s*(.*)$/);
      var keyword = matches && matches[1];
      var rest = matches && matches[2];
      if (self.parseREPLKeyword(keyword, rest) === true) {
        return;
      } else {
        self.outputStream.write('Invalid REPL keyword\n');
        skipCatchall = true;
      }
    }

    if (!skipCatchall) {
      var evalCmd = self.bufferedCommand + cmd + '\n';

      // This try is for determining if the command is complete, or should
      // continue onto the next line.
      // We try to evaluate both expressions e.g.
      //  '{ a : 1 }'
      // and statements e.g.
      //  'for (var i = 0; i < 10; i++) console.log(i);'

      // First we attempt to eval as expression with parens.
      // This catches '{a : 1}' properly.
      self.eval('(' + evalCmd + ')',
                self.context,
                'repl',
                function(e, ret) {
//        console.log('eval(self.context) complete', e);
        if (isPromise(ret)) return;
            if (e && !isSyntaxError(e)) return finish(e);

            if (typeof ret === 'function' || e) {
              // Now as statement without parens.
//console.log('==============now as a statement without parens.', e);
              self.eval(evalCmd, self.context, 'repl', function(err, ret) {
                console.log('eval self.context complete', e);
                if (isPromise(ret)) return;
                
              });
            } else {
              finish(null, ret);
            }
          });

    } else {
      finish(null);
    }

    function isSyntaxError(e) {
      // Convert error to string
      e = e && (e.stack || e.toString());
      return e && e.match(/^SyntaxError/) &&
             !(e.match(/^SyntaxError: Unexpected token .*\n/) &&
             e.match(/\n    at Object.parse \(native\)\n/));
    }

    function finish(e, ret) {
//      console.log('finish e:', e, 'ret', ret&&ret.toString());

      self.memory(cmd);

      // If error was SyntaxError and not JSON.parse error
      if (isSyntaxError(e)) {
        // Start buffering data like that:
        // {
        // ...  x: 1
        // ... }
        self.bufferedCommand += cmd + '\n';
        self.displayPrompt();
        return;
      } else if (e) {
//        console.log('finish not isSyntaxError e:', e, 'e.stack', e.stack, '(e.stack || e)', (e.stack || e), ret&&ret.toString());
        self.outputStream.write(util.inspect(e.stack || e) + '\n');
      }

      // Clear buffer if no SyntaxErrors
      self.bufferedCommand = '';

      // If we got any output - print it (if no error)
      if (!e && (!ignoreUndefined || ret !== undefined)) {
//        console.log('finish write ret', e, ret&&ret.toString());
        self.context._ = ret;
        self.outputStream.write(exports.writer(ret) + '\n');
      }

      // Display prompt again
      self.displayPrompt();
    };
  });

  rli.addListener('close', function() {
    self.inputStream.destroy();
  });

  self.displayPrompt();
}