1 | 'use strict'
|
---|
2 |
|
---|
3 | const logQueue = require('./log-queue')
|
---|
4 |
|
---|
5 | let questions
|
---|
6 | let currentQuestion
|
---|
7 | let answers
|
---|
8 | let currentOptions
|
---|
9 | let currentOptionsPointer
|
---|
10 | let currentQuestionId
|
---|
11 | let done
|
---|
12 |
|
---|
13 | class StateMachine {
|
---|
14 | constructor (rli, colors) {
|
---|
15 | this.rli = rli
|
---|
16 | this.colors = colors
|
---|
17 | }
|
---|
18 |
|
---|
19 | showPrompt () {
|
---|
20 | this.rli.write(this.colors.ANSWER)
|
---|
21 | this.rli.prompt()
|
---|
22 | }
|
---|
23 |
|
---|
24 | onKeypress (key) {
|
---|
25 | if (!currentOptions || !key) {
|
---|
26 | return
|
---|
27 | }
|
---|
28 |
|
---|
29 | if (key.name === 'tab' || key.name === 'right' || key.name === 'down') {
|
---|
30 | this.suggestOption(currentOptionsPointer + 1)
|
---|
31 | } else if (key.name === 'left' || key.name === 'up') {
|
---|
32 | this.suggestOption(currentOptionsPointer - 1)
|
---|
33 | }
|
---|
34 |
|
---|
35 | if (!key.ctrl && !key.meta && key.name !== 'enter' && key.name !== 'return') {
|
---|
36 | key.name = 'escape'
|
---|
37 | }
|
---|
38 | }
|
---|
39 |
|
---|
40 | suggestOption (index) {
|
---|
41 | if (!currentOptions) {
|
---|
42 | return
|
---|
43 | }
|
---|
44 |
|
---|
45 | if (index === -1) {
|
---|
46 | currentOptionsPointer = currentOptions.length - 1
|
---|
47 | } else if (index === currentOptions.length) {
|
---|
48 | currentOptionsPointer = 0
|
---|
49 | } else {
|
---|
50 | currentOptionsPointer = index
|
---|
51 | }
|
---|
52 |
|
---|
53 | this.rli._deleteLineLeft()
|
---|
54 | this.rli._deleteLineRight()
|
---|
55 | this.rli.write(currentOptions[currentOptionsPointer])
|
---|
56 | }
|
---|
57 |
|
---|
58 | kill () {
|
---|
59 | currentOptions = null
|
---|
60 | currentQuestionId = null
|
---|
61 | this.rli.write('\n' + this.colors.RESET + '\n')
|
---|
62 | this.rli.close()
|
---|
63 | }
|
---|
64 |
|
---|
65 | onLine (line) {
|
---|
66 | if (currentQuestionId) {
|
---|
67 | this.rli.write(this.colors.RESET)
|
---|
68 | line = line.trim().replace(this.colors.ANSWER, '').replace(this.colors.RESET, '')
|
---|
69 |
|
---|
70 | if (currentOptions) {
|
---|
71 | currentOptionsPointer = currentOptions.indexOf(line)
|
---|
72 | if (currentOptionsPointer === -1) {
|
---|
73 | return
|
---|
74 | }
|
---|
75 | }
|
---|
76 |
|
---|
77 | if (line === '') {
|
---|
78 | line = null
|
---|
79 | }
|
---|
80 |
|
---|
81 | if (currentQuestion.boolean) {
|
---|
82 | line = (line === 'yes' || line === 'true' || line === 'on')
|
---|
83 | }
|
---|
84 |
|
---|
85 | if (line !== null && currentQuestion.validate) {
|
---|
86 | currentQuestion.validate(line)
|
---|
87 | }
|
---|
88 |
|
---|
89 | if (currentQuestion.multiple) {
|
---|
90 | answers[currentQuestionId] = answers[currentQuestionId] || []
|
---|
91 | if (line !== null) {
|
---|
92 | answers[currentQuestionId].push(line)
|
---|
93 | this.showPrompt()
|
---|
94 |
|
---|
95 | if (currentOptions) {
|
---|
96 | currentOptions.splice(currentOptionsPointer, 1)
|
---|
97 | currentOptionsPointer = -1
|
---|
98 | }
|
---|
99 | } else {
|
---|
100 | this.nextQuestion()
|
---|
101 | }
|
---|
102 | } else {
|
---|
103 | answers[currentQuestionId] = line
|
---|
104 | this.nextQuestion()
|
---|
105 | }
|
---|
106 | }
|
---|
107 | }
|
---|
108 |
|
---|
109 | nextQuestion () {
|
---|
110 | currentQuestion = questions.shift()
|
---|
111 |
|
---|
112 | while (currentQuestion && currentQuestion.condition && !currentQuestion.condition(answers)) {
|
---|
113 | currentQuestion = questions.shift()
|
---|
114 | }
|
---|
115 |
|
---|
116 | logQueue.printLogQueue()
|
---|
117 |
|
---|
118 | if (currentQuestion) {
|
---|
119 | currentQuestionId = null
|
---|
120 |
|
---|
121 | this.rli.write('\n' + this.colors.question(currentQuestion.question) + '\n')
|
---|
122 | this.rli.write(currentQuestion.hint + '\n')
|
---|
123 | this.showPrompt()
|
---|
124 |
|
---|
125 | currentOptions = currentQuestion.options || null
|
---|
126 | currentQuestionId = currentQuestion.id
|
---|
127 | this.suggestOption(0)
|
---|
128 | } else {
|
---|
129 | this.kill()
|
---|
130 | done(answers)
|
---|
131 | }
|
---|
132 | }
|
---|
133 |
|
---|
134 | process (_questions, _done) {
|
---|
135 | questions = _questions
|
---|
136 | answers = {}
|
---|
137 | done = _done
|
---|
138 |
|
---|
139 | this.nextQuestion()
|
---|
140 | }
|
---|
141 | }
|
---|
142 |
|
---|
143 | module.exports = StateMachine
|
---|