-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhelpers.ts
143 lines (128 loc) · 3.58 KB
/
helpers.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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import { Keypress } from "./deps.ts";
import { KeyMap, mapFunc } from "./mod.ts";
export function flatten(map: KeyMap) {
const flatMap = new Map<KeySpec, mapFunc>();
map.forEach((value, key) => {
if (!(key instanceof Array)) key = [key];
key.forEach((e) => {
flatMap.set(KeySpec.of(e), value);
});
});
return flatMap;
}
export type Keys = KeySpec | string | RegExp | (KeySpec | string | RegExp)[];
export class KeySpec {
key?: RegExp | string;
ctrl?: boolean;
meta?: boolean;
shift?: boolean;
sequence?: RegExp | string;
constructor({
key,
ctrl,
meta,
shift,
sequence,
}: {
key?: RegExp | string;
ctrl?: boolean;
meta?: boolean;
shift?: boolean;
sequence?: RegExp | string;
} = {}) {
this.key = key;
this.ctrl = ctrl;
this.meta = meta;
this.shift = shift;
this.sequence = sequence;
}
is(keypress: Keypress): boolean {
return (
(this.key === undefined ||
(typeof this.key === "string"
? this.key === keypress.key
: this.key.test(keypress.key ?? ""))) &&
(this.ctrl === undefined || this.ctrl === keypress.ctrlKey) &&
(this.meta === undefined || this.meta === keypress.metaKey) &&
(this.shift === undefined || this.shift === keypress.shiftKey) &&
(this.sequence === undefined ||
(typeof this.sequence === "string"
? this.sequence === keypress.sequence
: this.sequence.test(keypress.sequence)))
);
}
static of(key: KeySpec | string | RegExp): KeySpec {
if (key instanceof KeySpec) return key;
if (key instanceof RegExp) {
let source = key.source;
if (source[0] != "^") source = "^" + source;
if (source[source.length - 1] != "$") source += "$";
key = new RegExp(source, key.flags);
}
return new KeySpec({ key: key, ctrl: false, meta: false });
}
}
export enum ANSI {
CSI = "\u001B[",
CUU = "A",
CUD = "B",
CUF = "C",
CUB = "D",
CHA = "G",
ED = "J",
EL = "K",
SCP = "s",
RCP = "u",
}
export enum ASCII {
EOT = "\u0004",
}
export enum DeleteMode {
FromCursor = 0,
ToCursor = 1,
Complete = 2,
}
function isRecord(value: unknown): value is Record<PropertyKey, unknown> {
return value != undefined && value != null && typeof value === "object";
}
export function hasOwnProperty<
X extends Record<string, unknown>,
Y extends PropertyKey,
Z extends PrimitiveOrConstructor,
>(obj: unknown, prop: Y, type: Z): obj is X & Record<Y, GuardedType<Z>> {
if (isRecord(obj) && prop in obj) {
const localPrimitiveOrConstructor: PrimitiveOrConstructor = type;
if (typeof localPrimitiveOrConstructor === "string") {
return (
type === "unknown" || typeof obj[prop] === localPrimitiveOrConstructor
);
}
return obj[prop] instanceof localPrimitiveOrConstructor;
}
return false;
}
interface typeMap {
// for mapping from strings to types
string: string;
number: number;
boolean: boolean;
unknown: unknown;
}
type PrimitiveOrConstructor = // 'string' | 'number' | 'boolean' | constructor
| { new (...args: unknown[]): unknown }
| keyof typeMap;
// infer the guarded type from a specific case of PrimitiveOrConstructor
type GuardedType<T extends PrimitiveOrConstructor> = T extends {
new (...args: unknown[]): infer U;
} ? U
: T extends keyof typeMap ? typeMap[T]
: never;
export function pipe<T>(...fns: ((...args: T[]) => T)[]) {
return fns.reduce((f, g) => (...args: T[]) => g(f(...args)));
}
export type InputConf = {
reader?: Deno.Reader & { rid: number };
writer?: Deno.Writer;
bufferLength?: number;
setRaw?: boolean;
};