/
controlSequenceIntroducer.ts
55 lines (54 loc) 路 1.75 KB
/
controlSequenceIntroducer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import { EMPTY_STRING } from "@lou.codes/constants/empty.js";
import type { EmptyString, Maybe } from "@lou.codes/types";
import { escapeSequence } from "./escapeSequence.js";
/**
* CSI sequence generator.
*
* @category Common
* @remarks
* Takes a `code` and an `input` number and returns the CSI sequence.
* @example
* ```typescript
* const selectGraphicRendition = controlSequenceIntroducer("m");
* selectGraphicRendition(13); // "\u001B[13m"
* selectGraphicRendition(42); // "\u001B[42m"
* ```
* @see {@link escapeSequence}
* @see [CSI (Control Sequence Introducer) sequences](https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_.28Control_Sequence_Introducer.29_sequences)
*
* @template Code CSI code generic.
* @param code CSI code.
* @returns Curried function with `code` in context.
*/
export const controlSequenceIntroducer =
<const Code extends string>(code: Code) =>
/**
* Takes an `input` number and returns the CSI sequence.
*
* @see {@link controlSequenceIntroducer}
* @see [CSI (Control Sequence Introducer) sequences](https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_.28Control_Sequence_Introducer.29_sequences)
*
* @template Input CSI input generic.
* @param input CSI input.
* @returns CSI sequence.
*/
<
const Input extends
| number
| readonly [open: Maybe<number>, close: Maybe<number>],
>(
input: Input,
) =>
escapeSequence(
`[${
typeof input === "number" ? input : (
(`${input[0] ?? EMPTY_STRING};${input[1] ?? EMPTY_STRING}` as const)
)
}${code}` as `[${Input extends (
readonly [open: Maybe<number>, close: Maybe<number>]
) ?
`${Input[0] extends number ? Input[0]
: EmptyString};${Input[1] extends number ? Input[1]
: EmptyString}`
: `${Input & number}`}${Code}`,
);