144 lines
3.2 KiB
JavaScript
144 lines
3.2 KiB
JavaScript
|
'use strict'
|
||
|
|
||
|
const logQueue = require('./log-queue')
|
||
|
|
||
|
let questions
|
||
|
let currentQuestion
|
||
|
let answers
|
||
|
let currentOptions
|
||
|
let currentOptionsPointer
|
||
|
let currentQuestionId
|
||
|
let done
|
||
|
|
||
|
class StateMachine {
|
||
|
constructor (rli, colors) {
|
||
|
this.rli = rli
|
||
|
this.colors = colors
|
||
|
}
|
||
|
|
||
|
showPrompt () {
|
||
|
this.rli.write(this.colors.ANSWER)
|
||
|
this.rli.prompt()
|
||
|
}
|
||
|
|
||
|
onKeypress (key) {
|
||
|
if (!currentOptions || !key) {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if (key.name === 'tab' || key.name === 'right' || key.name === 'down') {
|
||
|
this.suggestOption(currentOptionsPointer + 1)
|
||
|
} else if (key.name === 'left' || key.name === 'up') {
|
||
|
this.suggestOption(currentOptionsPointer - 1)
|
||
|
}
|
||
|
|
||
|
if (!key.ctrl && !key.meta && key.name !== 'enter' && key.name !== 'return') {
|
||
|
key.name = 'escape'
|
||
|
}
|
||
|
}
|
||
|
|
||
|
suggestOption (index) {
|
||
|
if (!currentOptions) {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if (index === -1) {
|
||
|
currentOptionsPointer = currentOptions.length - 1
|
||
|
} else if (index === currentOptions.length) {
|
||
|
currentOptionsPointer = 0
|
||
|
} else {
|
||
|
currentOptionsPointer = index
|
||
|
}
|
||
|
|
||
|
this.rli._deleteLineLeft()
|
||
|
this.rli._deleteLineRight()
|
||
|
this.rli.write(currentOptions[currentOptionsPointer])
|
||
|
}
|
||
|
|
||
|
kill () {
|
||
|
currentOptions = null
|
||
|
currentQuestionId = null
|
||
|
this.rli.write('\n' + this.colors.RESET + '\n')
|
||
|
this.rli.close()
|
||
|
}
|
||
|
|
||
|
onLine (line) {
|
||
|
if (currentQuestionId) {
|
||
|
this.rli.write(this.colors.RESET)
|
||
|
line = line.trim().replace(this.colors.ANSWER, '').replace(this.colors.RESET, '')
|
||
|
|
||
|
if (currentOptions) {
|
||
|
currentOptionsPointer = currentOptions.indexOf(line)
|
||
|
if (currentOptionsPointer === -1) {
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (line === '') {
|
||
|
line = null
|
||
|
}
|
||
|
|
||
|
if (currentQuestion.boolean) {
|
||
|
line = (line === 'yes' || line === 'true' || line === 'on')
|
||
|
}
|
||
|
|
||
|
if (line !== null && currentQuestion.validate) {
|
||
|
currentQuestion.validate(line)
|
||
|
}
|
||
|
|
||
|
if (currentQuestion.multiple) {
|
||
|
answers[currentQuestionId] = answers[currentQuestionId] || []
|
||
|
if (line !== null) {
|
||
|
answers[currentQuestionId].push(line)
|
||
|
this.showPrompt()
|
||
|
|
||
|
if (currentOptions) {
|
||
|
currentOptions.splice(currentOptionsPointer, 1)
|
||
|
currentOptionsPointer = -1
|
||
|
}
|
||
|
} else {
|
||
|
this.nextQuestion()
|
||
|
}
|
||
|
} else {
|
||
|
answers[currentQuestionId] = line
|
||
|
this.nextQuestion()
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
nextQuestion () {
|
||
|
currentQuestion = questions.shift()
|
||
|
|
||
|
while (currentQuestion && currentQuestion.condition && !currentQuestion.condition(answers)) {
|
||
|
currentQuestion = questions.shift()
|
||
|
}
|
||
|
|
||
|
logQueue.printLogQueue()
|
||
|
|
||
|
if (currentQuestion) {
|
||
|
currentQuestionId = null
|
||
|
|
||
|
this.rli.write('\n' + this.colors.question(currentQuestion.question) + '\n')
|
||
|
this.rli.write(currentQuestion.hint + '\n')
|
||
|
this.showPrompt()
|
||
|
|
||
|
currentOptions = currentQuestion.options || null
|
||
|
currentQuestionId = currentQuestion.id
|
||
|
this.suggestOption(0)
|
||
|
} else {
|
||
|
this.kill()
|
||
|
done(answers)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
process (_questions, _done) {
|
||
|
questions = _questions
|
||
|
answers = {}
|
||
|
done = _done
|
||
|
|
||
|
this.nextQuestion()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
module.exports = StateMachine
|