Skip to content

Commit bb00c24

Browse files
committed
fix cli in non-tty
1 parent bba5296 commit bb00c24

2 files changed

Lines changed: 91 additions & 52 deletions

File tree

packages/tools/src/commands/monitor.ts

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@ const cmd = new Command("Monitor program output", {
1212
) => {
1313
const echo = !(options["no-echo"] as boolean);
1414

15-
const rl = readline.createInterface({ input: process.stdin });
16-
readline.emitKeypressEvents(process.stdin, rl);
17-
process.stdin.setRawMode(true);
18-
1915
const port = options["port"] as string;
2016
const baudrate = options["baudrate"] as string;
2117
const socket = options["socket"] as string;
@@ -29,30 +25,51 @@ const cmd = new Command("Monitor program output", {
2925
stdout.write(chalk.red(new TextDecoder().decode(data)));
3026
});
3127

32-
await new Promise((resolve) => {
33-
process.stdin.on("keypress", (str, key) => {
34-
if (key.ctrl && key.name === "c") {
35-
device.programOutput.onData(undefined);
36-
device.programError.onData(undefined);
37-
process.stdin.setRawMode(false);
38-
rl.close();
39-
resolve(null);
40-
} else {
41-
if (echo) {
42-
if (key.sequence === "\r") {
43-
stdout.write("\r\n");
44-
} else if (str) {
45-
stdout.write(str);
28+
const cleanup = () => {
29+
device.programOutput.onData(undefined);
30+
device.programError.onData(undefined);
31+
};
32+
33+
if (process.stdin.isTTY) {
34+
const rl = readline.createInterface({ input: process.stdin });
35+
readline.emitKeypressEvents(process.stdin, rl);
36+
process.stdin.setRawMode(true);
37+
38+
await new Promise((resolve) => {
39+
process.stdin.on("keypress", (str, key) => {
40+
if (key.ctrl && key.name === "c") {
41+
cleanup();
42+
process.stdin.setRawMode(false);
43+
rl.close();
44+
resolve(null);
45+
} else {
46+
if (echo) {
47+
if (key.sequence === "\r") {
48+
stdout.write("\r\n");
49+
} else if (str) {
50+
stdout.write(str);
51+
}
4652
}
53+
let out = key.sequence;
54+
if (out === "\r") {
55+
out = "\n";
56+
}
57+
device.programInput.write(new TextEncoder().encode(out));
4758
}
48-
let out = key.sequence;
49-
if (out === "\r") {
50-
out = "\n";
51-
}
52-
device.programInput.write(new TextEncoder().encode(out));
53-
}
59+
});
5460
});
55-
});
61+
} else {
62+
const rl = readline.createInterface({ input: process.stdin });
63+
rl.on("line", (line) => {
64+
device.programInput.write(new TextEncoder().encode(line + "\n"));
65+
});
66+
await new Promise((resolve) => {
67+
rl.on("close", () => {
68+
cleanup();
69+
resolve(null);
70+
});
71+
});
72+
}
5673
},
5774
options: {
5875
"no-echo": new Opt("Echo input", { isFlag: true }),

packages/tools/src/commands/util.ts

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -169,41 +169,63 @@ export async function withDevice(
169169
}
170170

171171
export async function readPassword(prompt: string): Promise<string> {
172+
stdout.write(prompt);
173+
174+
const password = process.stdin.isTTY ? await readPasswordTty() : await readPasswordNonTty();
175+
176+
if (password.length >= 8 || password.length === 0) {
177+
return password;
178+
}
179+
180+
stderr.write("Password too short\n");
181+
throw 1;
182+
}
183+
184+
async function readPasswordTty(): Promise<string> {
172185
const rl = readline.createInterface({ input: process.stdin });
173186
readline.emitKeypressEvents(process.stdin, rl);
174187
process.stdin.setRawMode(true);
175188

176-
stdout.write(prompt);
177-
178-
let stringPassword = "";
179-
await new Promise((resolve, reject) => {
180-
process.stdin.on("keypress", (str, key) => {
181-
if (key.ctrl && key.name === "c") {
182-
process.stdin.setRawMode(false);
183-
rl.close();
184-
reject(1);
185-
return;
186-
}
187-
if (key.sequence === "\r") {
188-
if (stringPassword.length >= 8 || stringPassword.length === 0) {
189-
stdout.write("\n");
190-
resolve(null);
191-
} else {
192-
stdout.write("\n");
193-
stderr.write("Password too short\n");
189+
let password = "";
190+
try {
191+
await new Promise<void>((resolve, reject) => {
192+
process.stdin.on("keypress", (str, key) => {
193+
if (key.ctrl && key.name === "c") {
194194
reject(1);
195+
return;
195196
}
196-
} else if (key.sequence === "\b" || key.sequence === "\x7f") {
197-
if (stringPassword.length === 0) {
197+
if (key.sequence === "\r") {
198+
stdout.write("\n");
199+
resolve();
198200
return;
199201
}
200-
stdout.write("\b \b");
201-
stringPassword = stringPassword.slice(0, -1);
202-
} else {
203-
stringPassword += key.sequence;
202+
if (key.sequence === "\b" || key.sequence === "\x7f") {
203+
if (password.length === 0) {
204+
return;
205+
}
206+
stdout.write("\b \b");
207+
password = password.slice(0, -1);
208+
return;
209+
}
210+
password += key.sequence;
204211
stdout.write("*");
205-
}
212+
});
206213
});
207-
});
208-
return stringPassword;
214+
} finally {
215+
process.stdin.setRawMode(false);
216+
rl.close();
217+
}
218+
return password;
219+
}
220+
221+
async function readPasswordNonTty(): Promise<string> {
222+
const rl = readline.createInterface({ input: process.stdin, terminal: false });
223+
try {
224+
for await (const line of rl) {
225+
return line;
226+
}
227+
} finally {
228+
rl.close();
229+
}
230+
throw 1;
209231
}

0 commit comments

Comments
 (0)