(
message: string,
indicator: string,
values: PromptEntry<V>[],
clear: boolean | undefined,
visibleLinesInit: number | undefined,
fitToRemainingHeight: boolean | undefined,
valueChange: (active: boolean, absoluteIndex: number) => string | void,
handleInput: (str: string, absoluteIndex: number | undefined, actions: {
etx(): "return";
up(): void;
down(): void;
remove(): void;
inputStr(): void;
}) => boolean | "return",
)
| 27 | * @param handleInput A function that handles the input from the user. If it returns false, the prompt will continue. If it returns true, the prompt will exit with clean ups of terminal state (Use this for finalizing the selection). If it returns "return", the prompt will exit immediately without clean ups of terminal state (Use this for exiting the program). |
| 28 | */ |
| 29 | export function handlePromptSelect<V>( |
| 30 | message: string, |
| 31 | indicator: string, |
| 32 | values: PromptEntry<V>[], |
| 33 | clear: boolean | undefined, |
| 34 | visibleLinesInit: number | undefined, |
| 35 | fitToRemainingHeight: boolean | undefined, |
| 36 | valueChange: (active: boolean, absoluteIndex: number) => string | void, |
| 37 | handleInput: (str: string, absoluteIndex: number | undefined, actions: { |
| 38 | etx(): "return"; |
| 39 | up(): void; |
| 40 | down(): void; |
| 41 | remove(): void; |
| 42 | inputStr(): void; |
| 43 | }) => boolean | "return", |
| 44 | ) { |
| 45 | const input = Deno.stdin; |
| 46 | const output = Deno.stdout; |
| 47 | const indexedValues = values.map((value, absoluteIndex) => ({ |
| 48 | value, |
| 49 | absoluteIndex, |
| 50 | })); |
| 51 | let clearLength = indexedValues.length + 1; |
| 52 | |
| 53 | const indicatorLength = stripAnsiCode(indicator).length; |
| 54 | const PADDING = " ".repeat(indicatorLength); |
| 55 | const ARROW_PADDING = " ".repeat(indicatorLength + 1); |
| 56 | |
| 57 | let activeIndex = 0; |
| 58 | let offset = 0; |
| 59 | let searchBuffer = ""; |
| 60 | const buffer = new Uint8Array(4); |
| 61 | |
| 62 | input.setRaw(true); |
| 63 | output.writeSync(HIDE_CURSOR); |
| 64 | |
| 65 | let availableHeight = Deno.consoleSize().rows - SAFE_PADDING; |
| 66 | if (fitToRemainingHeight) { |
| 67 | const cursorRow = getCursorRow(input, output); |
| 68 | if (cursorRow !== undefined) { |
| 69 | availableHeight = Deno.consoleSize().rows - cursorRow - SAFE_PADDING + 1; |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | let visibleLines = visibleLinesInit ?? Math.max( |
| 74 | 1, |
| 75 | Math.min(availableHeight, values.length), |
| 76 | ); |
| 77 | |
| 78 | while (true) { |
| 79 | output.writeSync( |
| 80 | encoder.encode( |
| 81 | `${message + (searchBuffer ? ` (filter: ${searchBuffer})` : "")}\r\n`, |
| 82 | ), |
| 83 | ); |
| 84 | const filteredChunks = indexedValues.filter((item) => { |
| 85 | if (searchBuffer === "") { |
| 86 | return true; |
no test coverage detected