MCPcopy Index your code
hub / github.com/ChatLab/ChatLab / promptUser

Function promptUser

apps/cli/src/update-checker.ts:89–159  ·  view source on GitHub ↗
(question: string, choices: string[])

Source from the content-addressed store, hash-verified

87}
88
89function promptUser(question: string, choices: string[]): Promise<number> {
90 return new Promise((resolve) => {
91 let selected = 0
92
93 const render = () => {
94 // Move cursor up to rewrite choices (skip on first draw)
95 if (rendered) process.stderr.write(`\x1b[${choices.length}A`)
96 choices.forEach((c, i) => {
97 process.stderr.write(`\x1b[2K${i === selected ? '› ' : ' '}${i + 1}. ${c}\n`)
98 })
99 }
100
101 process.stderr.write(`${question}\n\n`)
102
103 if (!process.stdin.isTTY || !process.stdin.setRawMode) {
104 resolve(2)
105 return
106 }
107
108 let rendered = false
109 render()
110 rendered = true
111 process.stderr.write('\n')
112
113 process.stdin.setRawMode(true)
114 process.stdin.resume()
115
116 const cleanup = () => {
117 process.stdin.removeListener('data', onData)
118 process.stdin.setRawMode!(false)
119 process.stdin.pause()
120 }
121
122 const onData = (data: Buffer) => {
123 const key = data.toString()
124 if (key === '\x03') {
125 cleanup()
126 process.exit(0)
127 }
128 // Arrow up / k
129 if (key === '\x1b[A' || key === 'k') {
130 selected = (selected - 1 + choices.length) % choices.length
131 render()
132 return
133 }
134 // Arrow down / j
135 if (key === '\x1b[B' || key === 'j') {
136 selected = (selected + 1) % choices.length
137 render()
138 return
139 }
140 // Enter — confirm current selection
141 if (key === '\r' || key === '\n') {
142 cleanup()
143 process.stderr.write('\n')
144 resolve(selected + 1)
145 return
146 }

Callers 1

Calls 4

resolveFunction · 0.85
onMethod · 0.80
renderFunction · 0.70
writeMethod · 0.65

Tested by

no test coverage detected