readline: custom streams support
authorFedor Indutny <fedor.indutny@gmail.com>
Thu, 22 Sep 2011 16:49:59 +0000 (23:49 +0700)
committerRyan Dahl <ry@tinyclouds.org>
Fri, 23 Sep 2011 20:42:41 +0000 (13:42 -0700)
lib/_debugger.js
lib/repl.js

index ff34341..aba63a0 100644 (file)
@@ -29,13 +29,23 @@ var util = require('util'),
 
 exports.port = 5858;
 
-exports.start = function() {
-  if (process.argv.length < 3) {
+exports.start = function(argv, stdin, stdout) {
+  argv || (argv = process.argv.slice(2));
+
+  if (argv.length < 1) {
     console.error('Usage: node debug script.js');
     process.exit(1);
   }
 
-  var interface = new Interface();
+  // Setup input/output streams
+  stdin = stdin || process.openStdin();
+  stdout = stdout || process.stdout;
+
+  var args = ['--debug-brk'].concat(argv),
+      interface = new Interface(stdin, stdout, args);
+
+  stdin.resume();
+
   process.on('uncaughtException', function(e) {
     console.error("There was an internal error in Node's debugger. " +
         'Please report this bug.');
@@ -653,14 +663,14 @@ var helpMessage = 'Commands: ' + commands.map(function(group) {
 }).join(',\n');
 
 
-function SourceUnderline(sourceText, position) {
+function SourceUnderline(sourceText, position, tty) {
   if (!sourceText) return '';
 
   var head = sourceText.slice(0, position),
       tail = sourceText.slice(position);
 
   // Colourize char if stdout supports colours
-  if (process.stdout.isTTY) {
+  if (tty) {
     tail = tail.replace(/(.+?)([^\w]|$)/, '\033[32m$1\033[39m$2');
   }
 
@@ -698,13 +708,21 @@ function SourceInfo(body) {
 
 // This class is the repl-enabled debugger interface which is invoked on
 // "node debug"
-function Interface() {
+function Interface(stdin, stdout) {
   var self = this,
       child;
 
+  this.stdin = stdin;
+  this.stdout = stdout;
+
+  var streams = {
+    stdin: stdin,
+    stdout: stdout
+  };
+
   // Two eval modes are available: controlEval and debugEval
   // But controlEval is used by default
-  this.repl = new repl.REPLServer('debug> ', null,
+  this.repl = new repl.REPLServer('debug> ', streams,
                                   this.controlEval.bind(this));
 
   // Kill child process when repl closed or main process is dead
@@ -788,7 +806,7 @@ function Interface() {
 Interface.prototype.pause = function() {
   if (this.killed || this.paused++ > 0) return false;
   this.repl.rli.pause();
-  process.stdin.pause();
+  this.stdin.pause();
 };
 
 Interface.prototype.resume = function(silent) {
@@ -797,7 +815,7 @@ Interface.prototype.resume = function(silent) {
   if (silent !== true) {
     this.repl.displayPrompt();
   }
-  process.stdin.resume();
+  this.stdin.resume();
 
   if (this.waiting) {
     this.waiting();
@@ -808,9 +826,9 @@ Interface.prototype.resume = function(silent) {
 
 // Clear current line
 Interface.prototype.clearline = function() {
-  if (process.stdout.isTTY) {
-    process.stdout.cursorTo(0);
-    process.stdout.clearLine(1);
+  if (this.stdout.isTTY) {
+    this.stdout.cursorTo(0);
+    this.stdout.clearLine(1);
   }
 };
 
@@ -819,10 +837,10 @@ Interface.prototype.print = function(text, oneline) {
   if (this.killed) return;
   this.clearline();
 
-  process.stdout.write(typeof text === 'string' ? text : util.inspect(text));
+  this.stdout.write(typeof text === 'string' ? text : util.inspect(text));
 
   if (oneline !== true) {
-    process.stdout.write('\n');
+    this.stdout.write('\n');
   }
 };
 
@@ -1062,7 +1080,9 @@ Interface.prototype.list = function(delta) {
       // Highlight executing statement
       var line;
       if (current) {
-        line = SourceUnderline(lines[i], client.currentSourceColumn)
+        line = SourceUnderline(lines[i],
+                               client.currentSourceColumn,
+                               self.stdout.isTTY);
       } else {
         line = lines[i];
       }
@@ -1404,7 +1424,7 @@ Interface.prototype.trySpawn = function(cb) {
       connectionAttempts = 0;
 
   client.once('ready', function() {
-    process.stdout.write(' ok\n');
+    self.stdout.write(' ok\n');
 
     // since we did debug-brk, we're hitting a break point immediately
     // continue before anything else.
@@ -1449,7 +1469,7 @@ Interface.prototype.trySpawn = function(cb) {
 
   function attemptConnect() {
     ++connectionAttempts;
-    process.stdout.write('.');
+    self.stdout.write('.');
     client.connect(exports.port);
   }
 
index fc1eb54..915afcd 100644 (file)
@@ -89,8 +89,13 @@ function REPLServer(prompt, stream, eval) {
 
   if (stream) {
     // We're given a duplex socket
-    self.outputStream = stream;
-    self.inputStream = stream;
+    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;