85 lines
2.3 KiB
TypeScript
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 => {
|
|
}
|