cli-framework/src/lib/promptsmith/select-options.ts

85 lines
2.3 KiB
TypeScript

import type { Key } from 'node:readline'
import {
exit as EXIT,
type PainterEffect,
type PainterState,
type PainterTask,
task as TASK,
} from '../painter/lifecycle'
import {
type AnsiBufferKey,
ansiText,
emptyBytes,
writeAnsiU,
} from '../util/ansi'
import { DoEither, type Either, left, right } from '../util/basic/either'
import { some } from '../util/basic/option'
import type { Tag } from '../util/basic/utility'
interface SelectOptions {
keyup: Array<Key>
keydown: Array<Key>
exit: Array<Key>
accept: Array<Key>
selector: {selected: string, default: string}
selected: number
options: Array<string>
header?: {text: string, format: Array<AnsiBufferKey | Uint8Array>}
format: {
text: {
default: Array<AnsiBufferKey | Uint8Array>,
defaultSelected: Array<AnsiBufferKey | Uint8Array>,
},
selector: {
default: Array<AnsiBufferKey | Uint8Array>,
defaultSelected: Array<AnsiBufferKey | Uint8Array>,
},
}
}
interface Event extends Tag<'KEYUP' | 'KEYDOWN' | 'EXIT' | 'ACCEPT'> {
value?: any
}
const EVENT: Record<string, Event | ((...args: any[]) => Event)> = {
keyup: {_tag: 'KEYUP'},
keydown: {_tag: 'KEYDOWN'},
exit: <T>(x: T): Event => ({_tag: 'EXIT', value: x}),
accept: (x: number): Event => ({_tag: 'ACCEPT', value: x}),
}
type RenderText =
(x: SelectOptions & Tag<'PainterState'>) => Promise<Either<number, Error>>
const renderText: RenderText = async (x) => {
try {
return right(
await writeAnsiU([
...(!x.header ? [emptyBytes]
: [...x.header.format, ansiText(x.header.text)]),
...x.options.flatMap(i =>
(x.options[x.selected] === i)
? [
...x.format.selector.defaultSelected,
ansiText(x.selector.selected),
'RESET' as AnsiBufferKey,
...x.format.text.defaultSelected,
ansiText(i),
'RESET' as AnsiBufferKey,
] : [
...x.format.selector.default,
ansiText(x.selector.default),
'RESET' as AnsiBufferKey,
...x.format.text.default,
ansiText(i),
'RESET' as AnsiBufferKey,
]
),
]),
)
} catch (e) {
return left(e as Error)
}
}
const selectOptions: PainterEffect<SelectOptions> = x => {
}