node.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /**
  2. * Module dependencies.
  3. */
  4. var tty = require('tty');
  5. var util = require('util');
  6. /**
  7. * This is the Node.js implementation of `debug()`.
  8. *
  9. * Expose `debug()` as the module.
  10. */
  11. exports = module.exports = require('./debug');
  12. exports.log = log;
  13. exports.formatArgs = formatArgs;
  14. exports.save = save;
  15. exports.load = load;
  16. exports.useColors = useColors;
  17. /**
  18. * Colors.
  19. */
  20. exports.colors = [6, 2, 3, 4, 5, 1];
  21. /**
  22. * The file descriptor to write the `debug()` calls to.
  23. * Set the `DEBUG_FD` env variable to override with another value. i.e.:
  24. *
  25. * $ DEBUG_FD=3 node script.js 3>debug.log
  26. */
  27. var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
  28. var stream = 1 === fd ? process.stdout :
  29. 2 === fd ? process.stderr :
  30. createWritableStdioStream(fd);
  31. /**
  32. * Is stdout a TTY? Colored output is enabled when `true`.
  33. */
  34. function useColors() {
  35. var debugColors = (process.env.DEBUG_COLORS || '').trim().toLowerCase();
  36. if (0 === debugColors.length) {
  37. return tty.isatty(fd);
  38. } else {
  39. return '0' !== debugColors
  40. && 'no' !== debugColors
  41. && 'false' !== debugColors
  42. && 'disabled' !== debugColors;
  43. }
  44. }
  45. /**
  46. * Map %o to `util.inspect()`, since Node doesn't do that out of the box.
  47. */
  48. var inspect = (4 === util.inspect.length ?
  49. // node <= 0.8.x
  50. function (v, colors) {
  51. return util.inspect(v, void 0, void 0, colors);
  52. } :
  53. // node > 0.8.x
  54. function (v, colors) {
  55. return util.inspect(v, { colors: colors });
  56. }
  57. );
  58. exports.formatters.o = function(v) {
  59. return inspect(v, this.useColors)
  60. .replace(/\s*\n\s*/g, ' ');
  61. };
  62. /**
  63. * Adds ANSI color escape codes if enabled.
  64. *
  65. * @api public
  66. */
  67. function formatArgs() {
  68. var args = arguments;
  69. var useColors = this.useColors;
  70. var name = this.namespace;
  71. if (useColors) {
  72. var c = this.color;
  73. args[0] = ' \u001b[3' + c + ';1m' + name + ' '
  74. + '\u001b[0m'
  75. + args[0] + '\u001b[3' + c + 'm'
  76. + ' +' + exports.humanize(this.diff) + '\u001b[0m';
  77. } else {
  78. args[0] = new Date().toUTCString()
  79. + ' ' + name + ' ' + args[0];
  80. }
  81. return args;
  82. }
  83. /**
  84. * Invokes `console.error()` with the specified arguments.
  85. */
  86. function log() {
  87. return stream.write(util.format.apply(this, arguments) + '\n');
  88. }
  89. /**
  90. * Save `namespaces`.
  91. *
  92. * @param {String} namespaces
  93. * @api private
  94. */
  95. function save(namespaces) {
  96. if (null == namespaces) {
  97. // If you set a process.env field to null or undefined, it gets cast to the
  98. // string 'null' or 'undefined'. Just delete instead.
  99. delete process.env.DEBUG;
  100. } else {
  101. process.env.DEBUG = namespaces;
  102. }
  103. }
  104. /**
  105. * Load `namespaces`.
  106. *
  107. * @return {String} returns the previously persisted debug modes
  108. * @api private
  109. */
  110. function load() {
  111. return process.env.DEBUG;
  112. }
  113. /**
  114. * Copied from `node/src/node.js`.
  115. *
  116. * XXX: It's lame that node doesn't expose this API out-of-the-box. It also
  117. * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame.
  118. */
  119. function createWritableStdioStream (fd) {
  120. var stream;
  121. var tty_wrap = process.binding('tty_wrap');
  122. // Note stream._type is used for test-module-load-list.js
  123. switch (tty_wrap.guessHandleType(fd)) {
  124. case 'TTY':
  125. stream = new tty.WriteStream(fd);
  126. stream._type = 'tty';
  127. // Hack to have stream not keep the event loop alive.
  128. // See https://github.com/joyent/node/issues/1726
  129. if (stream._handle && stream._handle.unref) {
  130. stream._handle.unref();
  131. }
  132. break;
  133. case 'FILE':
  134. var fs = require('fs');
  135. stream = new fs.SyncWriteStream(fd, { autoClose: false });
  136. stream._type = 'fs';
  137. break;
  138. case 'PIPE':
  139. case 'TCP':
  140. var net = require('net');
  141. stream = new net.Socket({
  142. fd: fd,
  143. readable: false,
  144. writable: true
  145. });
  146. // FIXME Should probably have an option in net.Socket to create a
  147. // stream from an existing fd which is writable only. But for now
  148. // we'll just add this hack and set the `readable` member to false.
  149. // Test: ./node test/fixtures/echo.js < /etc/passwd
  150. stream.readable = false;
  151. stream.read = null;
  152. stream._type = 'pipe';
  153. // FIXME Hack to have stream not keep the event loop alive.
  154. // See https://github.com/joyent/node/issues/1726
  155. if (stream._handle && stream._handle.unref) {
  156. stream._handle.unref();
  157. }
  158. break;
  159. default:
  160. // Probably an error on in uv_guess_handle()
  161. throw new Error('Implement me. Unknown stream file type!');
  162. }
  163. // For supporting legacy API we put the FD here.
  164. stream.fd = fd;
  165. stream._isStdio = true;
  166. return stream;
  167. }
  168. /**
  169. * Enable namespaces listed in `process.env.DEBUG` initially.
  170. */
  171. exports.enable(load());