114 lines
2.4 KiB
JavaScript
114 lines
2.4 KiB
JavaScript
|
|
||
|
module.exports = read
|
||
|
|
||
|
var readline = require('readline')
|
||
|
var Mute = require('mute-stream')
|
||
|
|
||
|
function read (opts, cb) {
|
||
|
if (opts.num) {
|
||
|
throw new Error('read() no longer accepts a char number limit')
|
||
|
}
|
||
|
|
||
|
if (typeof opts.default !== 'undefined' &&
|
||
|
typeof opts.default !== 'string' &&
|
||
|
typeof opts.default !== 'number') {
|
||
|
throw new Error('default value must be string or number')
|
||
|
}
|
||
|
|
||
|
var input = opts.input || process.stdin
|
||
|
var output = opts.output || process.stdout
|
||
|
var prompt = (opts.prompt || '').trim() + ' '
|
||
|
var silent = opts.silent
|
||
|
var editDef = false
|
||
|
var timeout = opts.timeout
|
||
|
|
||
|
var def = opts.default || ''
|
||
|
if (def) {
|
||
|
if (silent) {
|
||
|
prompt += '(<default hidden>) '
|
||
|
} else if (opts.edit) {
|
||
|
editDef = true
|
||
|
} else {
|
||
|
prompt += '(' + def + ') '
|
||
|
}
|
||
|
}
|
||
|
var terminal = !!(opts.terminal || output.isTTY)
|
||
|
|
||
|
var m = new Mute({ replace: opts.replace, prompt: prompt })
|
||
|
m.pipe(output, {end: false})
|
||
|
output = m
|
||
|
var rlOpts = { input: input, output: output, terminal: terminal }
|
||
|
|
||
|
if (process.version.match(/^v0\.6/)) {
|
||
|
var rl = readline.createInterface(rlOpts.input, rlOpts.output)
|
||
|
} else {
|
||
|
var rl = readline.createInterface(rlOpts)
|
||
|
}
|
||
|
|
||
|
|
||
|
output.unmute()
|
||
|
rl.setPrompt(prompt)
|
||
|
rl.prompt()
|
||
|
if (silent) {
|
||
|
output.mute()
|
||
|
} else if (editDef) {
|
||
|
rl.line = def
|
||
|
rl.cursor = def.length
|
||
|
rl._refreshLine()
|
||
|
}
|
||
|
|
||
|
var called = false
|
||
|
rl.on('line', onLine)
|
||
|
rl.on('error', onError)
|
||
|
|
||
|
rl.on('SIGINT', function () {
|
||
|
rl.close()
|
||
|
onError(new Error('canceled'))
|
||
|
})
|
||
|
|
||
|
var timer
|
||
|
if (timeout) {
|
||
|
timer = setTimeout(function () {
|
||
|
onError(new Error('timed out'))
|
||
|
}, timeout)
|
||
|
}
|
||
|
|
||
|
function done () {
|
||
|
called = true
|
||
|
rl.close()
|
||
|
|
||
|
if (process.version.match(/^v0\.6/)) {
|
||
|
rl.input.removeAllListeners('data')
|
||
|
rl.input.removeAllListeners('keypress')
|
||
|
rl.input.pause()
|
||
|
}
|
||
|
|
||
|
clearTimeout(timer)
|
||
|
output.mute()
|
||
|
output.end()
|
||
|
}
|
||
|
|
||
|
function onError (er) {
|
||
|
if (called) return
|
||
|
done()
|
||
|
return cb(er)
|
||
|
}
|
||
|
|
||
|
function onLine (line) {
|
||
|
if (called) return
|
||
|
if (silent && terminal) {
|
||
|
output.unmute()
|
||
|
output.write('\r\n')
|
||
|
}
|
||
|
done()
|
||
|
// truncate the \n at the end.
|
||
|
line = line.replace(/\r?\n$/, '')
|
||
|
var isDefault = !!(editDef && line === def)
|
||
|
if (def && !line) {
|
||
|
isDefault = true
|
||
|
line = def
|
||
|
}
|
||
|
cb(null, line, isDefault)
|
||
|
}
|
||
|
}
|