mute.js
  1  var Stream = require('stream')
  2  
  3  module.exports = MuteStream
  4  
  5  // var out = new MuteStream(process.stdout)
  6  // argument auto-pipes
  7  function MuteStream (opts) {
  8    Stream.apply(this)
  9    opts = opts || {}
 10    this.writable = this.readable = true
 11    this.muted = false
 12    this.on('pipe', this._onpipe)
 13    this.replace = opts.replace
 14  
 15    // For readline-type situations
 16    // This much at the start of a line being redrawn after a ctrl char
 17    // is seen (such as backspace) won't be redrawn as the replacement
 18    this._prompt = opts.prompt || null
 19    this._hadControl = false
 20  }
 21  
 22  MuteStream.prototype = Object.create(Stream.prototype)
 23  
 24  Object.defineProperty(MuteStream.prototype, 'constructor', {
 25    value: MuteStream,
 26    enumerable: false
 27  })
 28  
 29  MuteStream.prototype.mute = function () {
 30    this.muted = true
 31  }
 32  
 33  MuteStream.prototype.unmute = function () {
 34    this.muted = false
 35  }
 36  
 37  Object.defineProperty(MuteStream.prototype, '_onpipe', {
 38    value: onPipe,
 39    enumerable: false,
 40    writable: true,
 41    configurable: true
 42  })
 43  
 44  function onPipe (src) {
 45    this._src = src
 46  }
 47  
 48  Object.defineProperty(MuteStream.prototype, 'isTTY', {
 49    get: getIsTTY,
 50    set: setIsTTY,
 51    enumerable: true,
 52    configurable: true
 53  })
 54  
 55  function getIsTTY () {
 56    return( (this._dest) ? this._dest.isTTY
 57          : (this._src) ? this._src.isTTY
 58          : false
 59          )
 60  }
 61  
 62  // basically just get replace the getter/setter with a regular value
 63  function setIsTTY (isTTY) {
 64    Object.defineProperty(this, 'isTTY', {
 65      value: isTTY,
 66      enumerable: true,
 67      writable: true,
 68      configurable: true
 69    })
 70  }
 71  
 72  Object.defineProperty(MuteStream.prototype, 'rows', {
 73    get: function () {
 74      return( this._dest ? this._dest.rows
 75            : this._src ? this._src.rows
 76            : undefined )
 77    }, enumerable: true, configurable: true })
 78  
 79  Object.defineProperty(MuteStream.prototype, 'columns', {
 80    get: function () {
 81      return( this._dest ? this._dest.columns
 82            : this._src ? this._src.columns
 83            : undefined )
 84    }, enumerable: true, configurable: true })
 85  
 86  
 87  MuteStream.prototype.pipe = function (dest, options) {
 88    this._dest = dest
 89    return Stream.prototype.pipe.call(this, dest, options)
 90  }
 91  
 92  MuteStream.prototype.pause = function () {
 93    if (this._src) return this._src.pause()
 94  }
 95  
 96  MuteStream.prototype.resume = function () {
 97    if (this._src) return this._src.resume()
 98  }
 99  
100  MuteStream.prototype.write = function (c) {
101    if (this.muted) {
102      if (!this.replace) return true
103      if (c.match(/^\u001b/)) {
104        if(c.indexOf(this._prompt) === 0) {
105          c = c.substr(this._prompt.length);
106          c = c.replace(/./g, this.replace);
107          c = this._prompt + c;
108        }
109        this._hadControl = true
110        return this.emit('data', c)
111      } else {
112        if (this._prompt && this._hadControl &&
113            c.indexOf(this._prompt) === 0) {
114          this._hadControl = false
115          this.emit('data', this._prompt)
116          c = c.substr(this._prompt.length)
117        }
118        c = c.toString().replace(/./g, this.replace)
119      }
120    }
121    this.emit('data', c)
122  }
123  
124  MuteStream.prototype.end = function (c) {
125    if (this.muted) {
126      if (c && this.replace) {
127        c = c.toString().replace(/./g, this.replace)
128      } else {
129        c = null
130      }
131    }
132    if (c) this.emit('data', c)
133    this.emit('end')
134  }
135  
136  function proxy (fn) { return function () {
137    var d = this._dest
138    var s = this._src
139    if (d && d[fn]) d[fn].apply(d, arguments)
140    if (s && s[fn]) s[fn].apply(s, arguments)
141  }}
142  
143  MuteStream.prototype.destroy = proxy('destroy')
144  MuteStream.prototype.destroySoon = proxy('destroySoon')
145  MuteStream.prototype.close = proxy('close')