-
-
Notifications
You must be signed in to change notification settings - Fork 64
/
select.ts
133 lines (107 loc) · 3.52 KB
/
select.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
import type { KeyEvent } from "../keycode/key_event.ts";
import { blue, dim } from "./deps.ts";
import { Figures } from "./figures.ts";
import {
GenericList,
GenericListOption,
GenericListOptions,
GenericListOptionSettings,
GenericListSettings,
} from "./_generic_list.ts";
import { GenericPrompt } from "./_generic_prompt.ts";
export type SelectOption = GenericListOption;
export type SelectOptionSettings = GenericListOptionSettings;
export type SelectValueOptions = (string | SelectOption)[];
export type SelectValueSettings = SelectOptionSettings[];
export interface SelectKeys {
previous?: string[];
next?: string[];
submit?: string[];
}
type SelectKeysSettings = Required<SelectKeys>;
export interface SelectOptions extends GenericListOptions<string, string> {
options: SelectValueOptions;
keys?: SelectKeys;
}
export interface SelectSettings extends GenericListSettings<string, string> {
options: SelectValueSettings;
keys: SelectKeysSettings;
}
export class Select extends GenericList<string, string, SelectSettings> {
protected selected: number = typeof this.settings.default !== "undefined"
? this.settings.options.findIndex((item) =>
item.name === this.settings.default
) || 0
: 0;
public static inject(value: string): void {
GenericPrompt.inject(value);
}
public static async prompt(options: SelectOptions): Promise<string> {
return new this({
pointer: blue(Figures.POINTER_SMALL),
listPointer: blue(Figures.POINTER),
indent: " ",
maxRows: 10,
...options,
keys: {
previous: ["up", "u"],
next: ["down", "d"],
submit: ["return", "enter"],
...(options.keys ?? {}),
},
options: Select.mapOptions(options),
}).prompt();
}
protected static mapOptions(options: SelectOptions): SelectValueSettings {
return this.mapValues(options.options).map((item) => this.mapItem(item));
}
protected static mapValues(optValues: SelectValueOptions): SelectOption[] {
return super.mapValues(optValues) as SelectOption[];
}
protected static mapItem(item: SelectOption): SelectOptionSettings {
return super.mapItem(item) as SelectOptionSettings;
}
protected async handleEvent(event: KeyEvent): Promise<boolean> {
switch (true) {
case event.name === "c":
if (event.ctrl) {
this.screen.cursorShow();
return Deno.exit(0);
}
break;
case this.isKey(this.settings.keys, "previous", event):
await this.selectPrevious();
break;
case this.isKey(this.settings.keys, "next", event):
await this.selectNext();
break;
case this.isKey(this.settings.keys, "submit", event):
return true;
}
return false;
}
protected getValue(): string {
return this.settings.options[this.selected].value;
}
protected writeListItem(item: SelectOptionSettings, isSelected?: boolean) {
let line = this.settings.indent;
// pointer
line += isSelected ? `${this.settings.listPointer} ` : " ";
// value
const value: string = item.name;
line += `${isSelected ? value : dim(value)}`;
this.writeLine(line);
}
protected validate(value: string): boolean | string {
return typeof value === "string" &&
value.length > 0 &&
this.settings.options.findIndex((option) => option.value === value) !==
-1;
}
protected transform(value: string): string {
return value.trim();
}
protected format(value: string): string {
return this.getOptionByValue(value)?.name ?? value;
}
}