• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1var Stream = require('stream')
2
3module.exports = MuteStream
4
5// var out = new MuteStream(process.stdout)
6// argument auto-pipes
7function 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
22MuteStream.prototype = Object.create(Stream.prototype)
23
24Object.defineProperty(MuteStream.prototype, 'constructor', {
25  value: MuteStream,
26  enumerable: false
27})
28
29MuteStream.prototype.mute = function () {
30  this.muted = true
31}
32
33MuteStream.prototype.unmute = function () {
34  this.muted = false
35}
36
37Object.defineProperty(MuteStream.prototype, '_onpipe', {
38  value: onPipe,
39  enumerable: false,
40  writable: true,
41  configurable: true
42})
43
44function onPipe (src) {
45  this._src = src
46}
47
48Object.defineProperty(MuteStream.prototype, 'isTTY', {
49  get: getIsTTY,
50  set: setIsTTY,
51  enumerable: true,
52  configurable: true
53})
54
55function 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
63function setIsTTY (isTTY) {
64  Object.defineProperty(this, 'isTTY', {
65    value: isTTY,
66    enumerable: true,
67    writable: true,
68    configurable: true
69  })
70}
71
72Object.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
79Object.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
87MuteStream.prototype.pipe = function (dest, options) {
88  this._dest = dest
89  return Stream.prototype.pipe.call(this, dest, options)
90}
91
92MuteStream.prototype.pause = function () {
93  if (this._src) return this._src.pause()
94}
95
96MuteStream.prototype.resume = function () {
97  if (this._src) return this._src.resume()
98}
99
100MuteStream.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
124MuteStream.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
136function 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
143MuteStream.prototype.destroy = proxy('destroy')
144MuteStream.prototype.destroySoon = proxy('destroySoon')
145MuteStream.prototype.close = proxy('close')
146