Node 命令行交互 选项
const EventsEmitter = require('events')
const readline = require('readline')
const MuteStream = require('mute-stream')
const ansiEscapes = require('ansi-escapes')
const option = {
type: 'list',
name: 'name',
message: 'your chioce: ',
chioces: [
{
name: '1000',
value: 1000,
},
{
name: '2000',
value: 2000,
},
{
name: '3000',
value: 3000,
}
]
}
function prompt(option) {
return new Promise(function (resolve, reject) {
try {
const list = new List(option);
list.render();
list.on('exit', function (answer) {
resolve(answer)
})
} catch (e) {
reject(e)
}
})
}
class List extends EventsEmitter {
constructor(option) {
super()
this.name = option.name
this.message = option.message
this.chioces = option.chioces
this.input = process.stdin
const ms = new MuteStream()
ms.pipe(process.stdout)
this.output = ms
this.rl = readline.createInterface({
input: this.input,
output: this.output,
})
this.selected = 0
this.heigth = 0
this.keypress = this.rl.input.on('keypress', this.onKeypress)
this.haveSelected = false
}
onKeypress = (...keymap) => {
let key = keymap[1]
if (key.name == 'up') {
this.selected--
if (this.selected < 0) {
this.selected = this.chioces.length - 1
}
this.render()
} else if (key.name == 'down') {
this.selected++
if (this.selected > this.chioces.length - 1) {
this.selected = 0
}
this.render()
} else if (key.name === 'return') {
this.haveSelected = true
this.render()
this.close()
this.emit('exit', this.chioces[this.selected])
}
}
render() {
this.output.unmute()
this.clear()
this.output.write(this.getContent())
this.output.mute()
}
getContent = () => {
if (!this.haveSelected) {
let title = '\x1B[32m?\x1B[39m \x1B[1m' + this.message +
'\x1B[22m(Use arrow Keys)\x1B[0m\n'
this.chioces.forEach((chioce, index) => {
if (this.selected === index) {
if (index === this.chioces.length - 1) {
title += '\x1B[36m> ' + chioce.name + '\x1B[0m'
} else {
title += '\x1B[36m> ' + chioce.name + '\x1B[0m\n'
}
} else {
if (index === this.chioces.length - 1) {
title += ' ' + chioce.name
} else {
title += ' ' + chioce.name + '\n'
}
}
})
this.heigth = this.chioces.length + 1
return title
} else {
const name = this.chioces[this.selected].name
let title = '\x1B[32m?\x1B[39m \x1B[1m' + this.message +
'\x1B[22m\x1B[0m\x1B[36m' + name + '\x1B[39m\x1B[0m \n'
return title
}
}
clear() {
const emptyLines = ansiEscapes.eraseLines(this.heigth)
this.output.write(emptyLines)
}
close() {
this.output.unmute()
this.rl.output.end()
this.rl.pause()
this.rl.close()
}
}
prompt(option).then(answer => {
console.log(answer)
})