Skip to content

Commit

Permalink
refactor: more cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
hi-ogawa committed Dec 25, 2023
1 parent 38ff588 commit 00817d1
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 90 deletions.
13 changes: 4 additions & 9 deletions packages/utils-node/src/fixtures/prompt-debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,11 @@ async function main() {
const manual = createManualPromise<void>();
const { rl, dispose } = subscribePromptEvent((e) => {
console.log([rl.line, rl.cursor], JSON.stringify(e));
if (e.type === "keypress") {
const special = getSpecialKey(e.data);
if (e.data.input === "q" || special === "abort") {
manual.resolve();
}
}
if (e.type === "input") {
console.log(e.data);
console.log(colors.dim("> ") + formatInputCursor(e.data));
if (e.input === "q" || getSpecialKey(e) === "abort") {
manual.resolve();
return;
}
console.log(colors.dim("> ") + formatInputCursor(rl));
});
console.log(":: echo keypress event ('q' to quit)");
try {
Expand Down
57 changes: 21 additions & 36 deletions packages/utils-node/src/prompt-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,7 @@ const SPECIAL_KEYS = [
export function getSpecialKey({
input,
key,
}: PromptEventMap["keypress"]):
| (typeof SPECIAL_KEYS)[number]
| "abort"
| undefined {
}: ReadlineKeypressEvent): (typeof SPECIAL_KEYS)[number] | "abort" | undefined {
// ctrl-c ctrl-z
if (input === "\x03" || input === "\x1A") {
return "abort";
Expand All @@ -95,29 +92,14 @@ export interface KeyInfo {
shift: boolean;
}

export interface PromptEventMap {
keypress: {
input?: string;
key: KeyInfo;
};
input: {
input: string;
cursor: number;
};
export interface ReadlineKeypressEvent {
input?: string;
key: KeyInfo;
}

export type PromptEvent =
| {
type: "keypress";
data: PromptEventMap["keypress"];
}
| {
type: "input";
data: PromptEventMap["input"];
};

// TODO: rename to setupReadlineKeypress
export function subscribePromptEvent(handler: (e: PromptEvent) => void) {
export function subscribePromptEvent(
handler: (e: ReadlineKeypressEvent) => void
) {
// cf.
// https://github.com/natemoo-re/clack/blob/90f8e3d762e96fde614fdf8da0529866649fafe2/packages/core/src/prompts/prompt.ts#L93
// https://github.com/terkelg/prompts/blob/735603af7c7990ac9efcfba6146967a7dbb15f50/lib/elements/prompt.js#L22-L23
Expand Down Expand Up @@ -145,11 +127,8 @@ export function subscribePromptEvent(handler: (e: PromptEvent) => void) {

function onKeypress(input: string | undefined, key: KeyInfo) {
handler({
type: "keypress",
data: {
input,
key,
},
input,
key,
});
}
stdin.on("keypress", onKeypress);
Expand All @@ -166,12 +145,18 @@ export function subscribePromptEvent(handler: (e: PromptEvent) => void) {
return { rl, dispose };
}

export function formatInputCursor({ input, cursor }: PromptEventMap["input"]) {
if (cursor >= input.length) {
input += " ".repeat(input.length - cursor + 1);
export function formatInputCursor({
line,
cursor,
}: {
line: string;
cursor: number;
}) {
if (cursor >= line.length) {
line += " ".repeat(line.length - cursor + 1);
}
const p1 = input.slice(0, cursor);
const p2 = input.slice(cursor, cursor + 1);
const p3 = input.slice(cursor + 1);
const p1 = line.slice(0, cursor);
const p2 = line.slice(cursor, cursor + 1);
const p3 = line.slice(cursor + 1);
return p1 + colors.inverse(p2) + p3;
}
75 changes: 30 additions & 45 deletions packages/utils-node/src/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { promisify } from "node:util";
import { createManualPromise } from "@hiogawa/utils";
import {
CSI,
type PromptEvent,
computeHeight,
formatInputCursor,
getSpecialKey,
Expand Down Expand Up @@ -82,7 +81,7 @@ export async function promptAutocomplete(options: {
return;
}

let content = options.message + formatInputCursor({ input, cursor });
let content = options.message + formatInputCursor({ line: input, cursor });
content += "\n";
content += suggestions
.slice(offset, offset + limit)
Expand All @@ -104,54 +103,40 @@ export async function promptAutocomplete(options: {
}

// TODO: async handler race condition
async function onPromptEvent(e: PromptEvent) {
// if (e.type === "input") {
// // skip same event which happens on "enter"
// if (input === e.data.input && cursor === e.data.cursor) {
// return;
// }
// input = e.data.input;
// cursor = e.data.cursor;
// await updateSuggestions();
// await render();
// }
if (e.type === "keypress") {
switch (getSpecialKey(e.data)) {
case "abort":
case "escape": {
value = undefined;
done = true;
manual.resolve();
return;
}
case "enter":
case "return": {
done = true;
manual.resolve();
return;
}
case "up": {
moveSelection(-1);
await render();
return;
}
case "down": {
moveSelection(1);
await render();
return;
}
const { rl, dispose } = subscribePromptEvent(async (e) => {
switch (getSpecialKey(e)) {
case "abort":
case "escape": {
value = undefined;
done = true;
manual.resolve();
return;
}
if (input !== rl.line || cursor !== rl.cursor) {
input = rl.line;
cursor = rl.cursor;
await updateSuggestions();
case "enter":
case "return": {
done = true;
manual.resolve();
return;
}
case "up": {
moveSelection(-1);
await render();
return;
}
case "down": {
moveSelection(1);
await render();
return;
}
}
}
if (input !== rl.line || cursor !== rl.cursor) {
input = rl.line;
cursor = rl.cursor;
await updateSuggestions();
await render();
}
});

// let dispose: (() => void) | undefined;
const { rl, dispose } = subscribePromptEvent(onPromptEvent);
try {
if (hideCursor) {
await write(`${CSI}?25l`); // hide cursor
Expand Down

0 comments on commit 00817d1

Please # to comment.