oh-aicoding-tool 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +55 -33
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -108,26 +108,38 @@ function rawKeySeq(raw) {
|
|
|
108
108
|
return String(raw ?? "");
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
function
|
|
112
|
-
|
|
113
|
-
if (
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (
|
|
119
|
-
if (
|
|
120
|
-
|
|
121
|
-
|
|
111
|
+
function readKeyFromBuffer(buffer) {
|
|
112
|
+
if (!buffer) return { pending: true, rest: "" };
|
|
113
|
+
if (buffer === "\x1b" || buffer === "\x1b[" || buffer === "\x1bO" || buffer === "\x00" || buffer === "\xe0") {
|
|
114
|
+
return { pending: true, rest: buffer };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const three = buffer.slice(0, 3);
|
|
118
|
+
if (three === "\x1b[A" || three === "\x1bOA") return { key: { name: "up", sequence: three }, rest: buffer.slice(3) };
|
|
119
|
+
if (three === "\x1b[B" || three === "\x1bOB") return { key: { name: "down", sequence: three }, rest: buffer.slice(3) };
|
|
120
|
+
|
|
121
|
+
const two = buffer.slice(0, 2);
|
|
122
|
+
if (two === "\x00H" || two === "\xe0H") return { key: { name: "up", sequence: two }, rest: buffer.slice(2) };
|
|
123
|
+
if (two === "\x00P" || two === "\xe0P") return { key: { name: "down", sequence: two }, rest: buffer.slice(2) };
|
|
124
|
+
if (two === "\r\n") return { key: { name: "enter", sequence: two }, rest: buffer.slice(2) };
|
|
125
|
+
|
|
126
|
+
const seq = buffer[0];
|
|
127
|
+
if (seq === "\x03") return { key: { name: "ctrl-c", sequence: seq }, rest: buffer.slice(1) };
|
|
128
|
+
if (seq === "\r" || seq === "\n") return { key: { name: "enter", sequence: seq }, rest: buffer.slice(1) };
|
|
129
|
+
if (seq === " ") return { key: { name: "space", sequence: seq }, rest: buffer.slice(1) };
|
|
130
|
+
if (seq === "\x1b") return { key: { name: "escape", sequence: seq }, rest: buffer.slice(1) };
|
|
131
|
+
if (/^[1-9]$/.test(seq)) return { key: { name: "number", number: Number.parseInt(seq, 10), sequence: seq }, rest: buffer.slice(1) };
|
|
132
|
+
return { key: { name: seq.toLowerCase(), sequence: seq }, rest: buffer.slice(1) };
|
|
122
133
|
}
|
|
123
134
|
|
|
124
135
|
async function askMultiChoice(rl, title, choices, subtitle) {
|
|
125
136
|
if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
126
137
|
rl.pause();
|
|
127
138
|
return await new Promise((resolve) => {
|
|
128
|
-
let index = 0;
|
|
129
|
-
|
|
130
|
-
const
|
|
139
|
+
let index = 0;
|
|
140
|
+
let keyBuffer = "";
|
|
141
|
+
const selected = new Set(choices.filter((choice) => choice.selected).map((choice) => choice.value));
|
|
142
|
+
const stdin = process.stdin;
|
|
131
143
|
|
|
132
144
|
function cleanup(value) {
|
|
133
145
|
stdin.off("data", onData);
|
|
@@ -146,25 +158,35 @@ async function askMultiChoice(rl, title, choices, subtitle) {
|
|
|
146
158
|
}
|
|
147
159
|
|
|
148
160
|
function onData(raw) {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
return;
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
161
|
+
keyBuffer += rawKeySeq(raw);
|
|
162
|
+
while (keyBuffer) {
|
|
163
|
+
const result = readKeyFromBuffer(keyBuffer);
|
|
164
|
+
if (result.pending) {
|
|
165
|
+
keyBuffer = result.rest;
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
keyBuffer = result.rest;
|
|
169
|
+
const key = result.key;
|
|
170
|
+
|
|
171
|
+
if (key.name === "ctrl-c") return cleanup([]);
|
|
172
|
+
if (key.name === "up") {
|
|
173
|
+
index = (index - 1 + choices.length) % choices.length;
|
|
174
|
+
renderMultiChoice(title, choices, index, selected, subtitle);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (key.name === "down") {
|
|
178
|
+
index = (index + 1) % choices.length;
|
|
179
|
+
renderMultiChoice(title, choices, index, selected, subtitle);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (key.name === "q" || key.name === "escape") return cleanup([]);
|
|
183
|
+
if (key.name === "space") return toggle();
|
|
184
|
+
if (key.name === "enter") return cleanup([...selected]);
|
|
185
|
+
const number = key.name === "number" ? key.number : Number.NaN;
|
|
186
|
+
if (Number.isInteger(number) && choices[number - 1]) {
|
|
187
|
+
index = number - 1;
|
|
188
|
+
toggle();
|
|
189
|
+
}
|
|
168
190
|
}
|
|
169
191
|
}
|
|
170
192
|
|