mepcli 0.6.1 → 1.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +512 -326
- package/dist/ansi.d.ts +8 -0
- package/dist/ansi.js +8 -0
- package/dist/base.d.ts +21 -0
- package/dist/base.js +57 -0
- package/dist/core.d.ts +48 -1
- package/dist/core.js +156 -0
- package/dist/data/licenses.d.ts +2 -0
- package/dist/data/licenses.js +109 -0
- package/dist/highlight.js +58 -26
- package/dist/index.d.ts +36 -0
- package/dist/index.js +36 -0
- package/dist/input.js +0 -3
- package/dist/prompts/box.d.ts +21 -0
- package/dist/prompts/box.js +192 -0
- package/dist/prompts/breadcrumb.d.ts +22 -0
- package/dist/prompts/breadcrumb.js +302 -0
- package/dist/prompts/byte.d.ts +13 -0
- package/dist/prompts/byte.js +159 -0
- package/dist/prompts/calculator.d.ts +16 -0
- package/dist/prompts/calculator.js +213 -0
- package/dist/prompts/calendar.js +0 -5
- package/dist/prompts/code.d.ts +2 -0
- package/dist/prompts/code.js +104 -70
- package/dist/prompts/connection-string.d.ts +18 -0
- package/dist/prompts/connection-string.js +97 -0
- package/dist/prompts/curl.d.ts +39 -0
- package/dist/prompts/curl.js +285 -0
- package/dist/prompts/data-inspector.d.ts +22 -0
- package/dist/prompts/data-inspector.js +256 -0
- package/dist/prompts/dependency.d.ts +16 -0
- package/dist/prompts/dependency.js +265 -0
- package/dist/prompts/dial.d.ts +10 -0
- package/dist/prompts/dial.js +110 -0
- package/dist/prompts/diff.d.ts +10 -0
- package/dist/prompts/diff.js +101 -0
- package/dist/prompts/draw.d.ts +20 -0
- package/dist/prompts/draw.js +188 -0
- package/dist/prompts/editor.js +0 -4
- package/dist/prompts/emoji.d.ts +18 -0
- package/dist/prompts/emoji.js +228 -0
- package/dist/prompts/exec.d.ts +13 -0
- package/dist/prompts/exec.js +83 -0
- package/dist/prompts/fuzzy.d.ts +12 -0
- package/dist/prompts/fuzzy.js +136 -0
- package/dist/prompts/gauge.d.ts +21 -0
- package/dist/prompts/gauge.js +130 -0
- package/dist/prompts/heatmap.d.ts +13 -0
- package/dist/prompts/heatmap.js +141 -0
- package/dist/prompts/ip.d.ts +11 -0
- package/dist/prompts/ip.js +118 -0
- package/dist/prompts/kanban.d.ts +17 -0
- package/dist/prompts/kanban.js +228 -0
- package/dist/prompts/keypress.js +0 -2
- package/dist/prompts/license.d.ts +9 -0
- package/dist/prompts/license.js +105 -0
- package/dist/prompts/map.d.ts +15 -0
- package/dist/prompts/map.js +199 -0
- package/dist/prompts/match.d.ts +19 -0
- package/dist/prompts/match.js +275 -0
- package/dist/prompts/miller.d.ts +15 -0
- package/dist/prompts/miller.js +221 -0
- package/dist/prompts/multi-column-select.d.ts +10 -0
- package/dist/prompts/multi-column-select.js +166 -0
- package/dist/prompts/number.js +0 -2
- package/dist/prompts/otp.d.ts +10 -0
- package/dist/prompts/otp.js +91 -0
- package/dist/prompts/pattern.d.ts +22 -0
- package/dist/prompts/pattern.js +249 -0
- package/dist/prompts/quiz-select.d.ts +10 -0
- package/dist/prompts/quiz-select.js +104 -0
- package/dist/prompts/quiz-text.d.ts +11 -0
- package/dist/prompts/quiz-text.js +82 -0
- package/dist/prompts/regex.d.ts +13 -0
- package/dist/prompts/regex.js +131 -0
- package/dist/prompts/region.d.ts +11 -0
- package/dist/prompts/region.js +164 -0
- package/dist/prompts/schedule.d.ts +18 -0
- package/dist/prompts/schedule.js +221 -0
- package/dist/prompts/scroll.d.ts +13 -0
- package/dist/prompts/scroll.js +152 -0
- package/dist/prompts/seat.d.ts +17 -0
- package/dist/prompts/seat.js +165 -0
- package/dist/prompts/select-range.d.ts +8 -0
- package/dist/prompts/select-range.js +136 -0
- package/dist/prompts/select.d.ts +9 -9
- package/dist/prompts/semver.d.ts +6 -0
- package/dist/prompts/semver.js +32 -0
- package/dist/prompts/shortcut.d.ts +9 -0
- package/dist/prompts/shortcut.js +135 -0
- package/dist/prompts/slot.d.ts +16 -0
- package/dist/prompts/slot.js +107 -0
- package/dist/prompts/snippet.js +0 -3
- package/dist/prompts/sort-grid.d.ts +16 -0
- package/dist/prompts/sort-grid.js +146 -0
- package/dist/prompts/sort.js +0 -1
- package/dist/prompts/spreadsheet.d.ts +21 -0
- package/dist/prompts/spreadsheet.js +239 -0
- package/dist/prompts/text.d.ts +9 -7
- package/dist/prompts/text.js +52 -0
- package/dist/prompts/time.d.ts +12 -0
- package/dist/prompts/time.js +202 -0
- package/dist/prompts/tree-select.d.ts +0 -1
- package/dist/prompts/tree-select.js +1 -5
- package/dist/symbols.d.ts +12 -0
- package/dist/symbols.js +14 -2
- package/dist/theme.js +10 -1
- package/dist/types.d.ts +264 -1
- package/dist/utils.d.ts +53 -0
- package/dist/utils.js +252 -0
- package/package.json +51 -47
- package/example.ts +0 -390
package/dist/prompts/number.js
CHANGED
|
@@ -48,8 +48,6 @@ class NumberPrompt extends base_1.Prompt {
|
|
|
48
48
|
if (char === '\r' || char === '\n') {
|
|
49
49
|
const num = parseFloat(this.stringValue);
|
|
50
50
|
if (this.stringValue.trim() === '' || isNaN(num)) {
|
|
51
|
-
// Check if empty is allowed?
|
|
52
|
-
// If not required? Assuming required for number prompt usually
|
|
53
51
|
this.errorMsg = 'Please enter a valid number.';
|
|
54
52
|
this.render(false);
|
|
55
53
|
return;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Prompt } from '../base';
|
|
2
|
+
import { OTPOptions } from '../types';
|
|
3
|
+
export declare class OTPPrompt extends Prompt<string, OTPOptions> {
|
|
4
|
+
private slots;
|
|
5
|
+
private cursor;
|
|
6
|
+
private readonly length;
|
|
7
|
+
constructor(options: OTPOptions);
|
|
8
|
+
protected render(_firstRender: boolean): void;
|
|
9
|
+
protected handleInput(char: string): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OTPPrompt = void 0;
|
|
4
|
+
const ansi_1 = require("../ansi");
|
|
5
|
+
const base_1 = require("../base");
|
|
6
|
+
const theme_1 = require("../theme");
|
|
7
|
+
class OTPPrompt extends base_1.Prompt {
|
|
8
|
+
constructor(options) {
|
|
9
|
+
super(options);
|
|
10
|
+
this.cursor = 0;
|
|
11
|
+
this.length = options.length || 6;
|
|
12
|
+
this.slots = new Array(this.length).fill('');
|
|
13
|
+
}
|
|
14
|
+
render(_firstRender) {
|
|
15
|
+
const mask = this.options.mask || '_';
|
|
16
|
+
let output = `${theme_1.theme.success}?${ansi_1.ANSI.RESET} ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET}\n`;
|
|
17
|
+
output += ' '; // Indent
|
|
18
|
+
for (let i = 0; i < this.length; i++) {
|
|
19
|
+
const val = this.slots[i];
|
|
20
|
+
let charToDisplay = mask;
|
|
21
|
+
if (val) {
|
|
22
|
+
charToDisplay = this.options.secure ? '*' : val;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
// Use placeholder char if available at this index
|
|
26
|
+
if (this.options.placeholder && i < this.options.placeholder.length) {
|
|
27
|
+
charToDisplay = this.options.placeholder[i];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (i === this.cursor) {
|
|
31
|
+
output += `${ansi_1.ANSI.REVERSE}${charToDisplay}${ansi_1.ANSI.RESET} `;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
if (!val) {
|
|
35
|
+
output += `${theme_1.theme.muted}${charToDisplay}${ansi_1.ANSI.RESET} `;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
output += `${theme_1.theme.main}${charToDisplay}${ansi_1.ANSI.RESET} `;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
this.renderFrame(output);
|
|
43
|
+
}
|
|
44
|
+
handleInput(char) {
|
|
45
|
+
// Digits
|
|
46
|
+
if (/^\d$/.test(char)) {
|
|
47
|
+
this.slots[this.cursor] = char;
|
|
48
|
+
// If we are at the last slot
|
|
49
|
+
if (this.cursor === this.length - 1) {
|
|
50
|
+
// Only submit if all slots are filled
|
|
51
|
+
if (this.slots.every(s => s !== '')) {
|
|
52
|
+
this.render(false); // Update view first
|
|
53
|
+
this.submit(this.slots.join(''));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
this.cursor++;
|
|
58
|
+
this.render(false);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// Backspace
|
|
62
|
+
if (char === '\u0008' || char === '\x7f') {
|
|
63
|
+
if (this.slots[this.cursor] !== '') {
|
|
64
|
+
this.slots[this.cursor] = '';
|
|
65
|
+
}
|
|
66
|
+
else if (this.cursor > 0) {
|
|
67
|
+
this.cursor--;
|
|
68
|
+
this.slots[this.cursor] = '';
|
|
69
|
+
}
|
|
70
|
+
this.render(false);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
// Left Arrow
|
|
74
|
+
if (this.isLeft(char)) {
|
|
75
|
+
if (this.cursor > 0) {
|
|
76
|
+
this.cursor--;
|
|
77
|
+
this.render(false);
|
|
78
|
+
}
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// Right Arrow
|
|
82
|
+
if (this.isRight(char)) {
|
|
83
|
+
if (this.cursor < this.length - 1) {
|
|
84
|
+
this.cursor++;
|
|
85
|
+
this.render(false);
|
|
86
|
+
}
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
exports.OTPPrompt = OTPPrompt;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Prompt } from '../base';
|
|
2
|
+
import { PatternOptions, MouseEvent } from '../types';
|
|
3
|
+
export declare class PatternPrompt extends Prompt<number[], PatternOptions> {
|
|
4
|
+
private path;
|
|
5
|
+
private cursor;
|
|
6
|
+
private isDragging;
|
|
7
|
+
private errorMsg;
|
|
8
|
+
private rows;
|
|
9
|
+
private cols;
|
|
10
|
+
private nodeChar;
|
|
11
|
+
private nodeSpacingX;
|
|
12
|
+
private nodeSpacingY;
|
|
13
|
+
private lastMouse;
|
|
14
|
+
constructor(options: PatternOptions);
|
|
15
|
+
private getIndex;
|
|
16
|
+
private getPoint;
|
|
17
|
+
protected render(firstRender: boolean): void;
|
|
18
|
+
private drawLine;
|
|
19
|
+
protected handleInput(char: string, _key: Buffer): void;
|
|
20
|
+
private addToPath;
|
|
21
|
+
protected handleMouse(event: MouseEvent): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PatternPrompt = void 0;
|
|
4
|
+
const ansi_1 = require("../ansi");
|
|
5
|
+
const base_1 = require("../base");
|
|
6
|
+
const theme_1 = require("../theme");
|
|
7
|
+
class PatternPrompt extends base_1.Prompt {
|
|
8
|
+
constructor(options) {
|
|
9
|
+
super(options);
|
|
10
|
+
this.path = [];
|
|
11
|
+
this.cursor = { r: 0, c: 0 };
|
|
12
|
+
this.isDragging = false;
|
|
13
|
+
this.errorMsg = '';
|
|
14
|
+
// Layout
|
|
15
|
+
this.nodeSpacingX = 4;
|
|
16
|
+
this.nodeSpacingY = 2;
|
|
17
|
+
this.lastMouse = null;
|
|
18
|
+
this.rows = options.rows || 3;
|
|
19
|
+
this.cols = options.cols || 3;
|
|
20
|
+
this.nodeChar = options.nodeChar || '●';
|
|
21
|
+
}
|
|
22
|
+
getIndex(r, c) {
|
|
23
|
+
return r * this.cols + c;
|
|
24
|
+
}
|
|
25
|
+
getPoint(index) {
|
|
26
|
+
return {
|
|
27
|
+
r: Math.floor(index / this.cols),
|
|
28
|
+
c: index % this.cols
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
render(firstRender) {
|
|
32
|
+
let output = '';
|
|
33
|
+
// Title
|
|
34
|
+
const icon = this.errorMsg ? `${theme_1.theme.error}✖` : `${theme_1.theme.success}?`;
|
|
35
|
+
output += `${icon} ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET}\n`;
|
|
36
|
+
// Instructions
|
|
37
|
+
if (firstRender) {
|
|
38
|
+
output += `${ansi_1.ANSI.DIM}(Draw pattern with mouse or use Arrows + Space)${ansi_1.ANSI.RESET}\n`;
|
|
39
|
+
}
|
|
40
|
+
// Render Grid
|
|
41
|
+
// Initialize buffer with spaces
|
|
42
|
+
// Adjust height/width slightly to ensure we cover full lines
|
|
43
|
+
const bufferHeight = this.rows * this.nodeSpacingY + 1;
|
|
44
|
+
const bufferWidth = this.cols * this.nodeSpacingX + 1;
|
|
45
|
+
const buffer = Array(bufferHeight).fill(null).map(() => Array(bufferWidth).fill(' '));
|
|
46
|
+
// Draw connections
|
|
47
|
+
for (let i = 0; i < this.path.length - 1; i++) {
|
|
48
|
+
this.drawLine(buffer, this.path[i], this.path[i + 1]);
|
|
49
|
+
}
|
|
50
|
+
// Draw nodes
|
|
51
|
+
for (let r = 0; r < this.rows; r++) {
|
|
52
|
+
for (let c = 0; c < this.cols; c++) {
|
|
53
|
+
const index = this.getIndex(r, c);
|
|
54
|
+
const isSelected = this.path.includes(index);
|
|
55
|
+
// Calculate buffer position
|
|
56
|
+
const by = r * this.nodeSpacingY;
|
|
57
|
+
const bx = c * this.nodeSpacingX;
|
|
58
|
+
// Mark node in buffer (will be stylized later)
|
|
59
|
+
buffer[by][bx] = isSelected ? '●' : '○';
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Build string from buffer
|
|
63
|
+
// Limit loop to actual grid dimensions to avoid trailing empty lines
|
|
64
|
+
const displayHeight = (this.rows - 1) * this.nodeSpacingY + 1;
|
|
65
|
+
const displayWidth = (this.cols - 1) * this.nodeSpacingX + 1;
|
|
66
|
+
for (let y = 0; y < displayHeight; y++) {
|
|
67
|
+
output += ' '; // Indent
|
|
68
|
+
for (let x = 0; x < displayWidth; x++) {
|
|
69
|
+
const char = buffer[y][x];
|
|
70
|
+
// Determine coloring context
|
|
71
|
+
const isNodeRow = y % this.nodeSpacingY === 0;
|
|
72
|
+
const isNodeCol = x % this.nodeSpacingX === 0;
|
|
73
|
+
if (isNodeRow && isNodeCol) {
|
|
74
|
+
const r = y / this.nodeSpacingY;
|
|
75
|
+
const c = x / this.nodeSpacingX;
|
|
76
|
+
const idx = this.getIndex(r, c);
|
|
77
|
+
const isSelected = this.path.includes(idx);
|
|
78
|
+
const isLast = this.path.length > 0 && this.path[this.path.length - 1] === idx;
|
|
79
|
+
const isCursor = this.cursor.r === r && this.cursor.c === c;
|
|
80
|
+
let styledChar = this.nodeChar;
|
|
81
|
+
if (isSelected)
|
|
82
|
+
styledChar = theme_1.theme.main + this.nodeChar + ansi_1.ANSI.RESET;
|
|
83
|
+
if (isLast)
|
|
84
|
+
styledChar = theme_1.theme.success + this.nodeChar + ansi_1.ANSI.RESET;
|
|
85
|
+
if (isCursor) {
|
|
86
|
+
styledChar = ansi_1.ANSI.REVERSE + styledChar + ansi_1.ANSI.RESET;
|
|
87
|
+
}
|
|
88
|
+
else if (!isSelected) {
|
|
89
|
+
styledChar = theme_1.theme.muted + '○' + ansi_1.ANSI.RESET;
|
|
90
|
+
}
|
|
91
|
+
output += styledChar;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// It's a line or space
|
|
95
|
+
if (char !== ' ' && char !== '○' && char !== '●') {
|
|
96
|
+
output += theme_1.theme.main + char + ansi_1.ANSI.RESET;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
output += ' ';
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
output += '\n';
|
|
104
|
+
}
|
|
105
|
+
if (this.errorMsg) {
|
|
106
|
+
output += `\n${theme_1.theme.error}>> ${this.errorMsg}${ansi_1.ANSI.RESET}`;
|
|
107
|
+
}
|
|
108
|
+
this.renderFrame(output);
|
|
109
|
+
}
|
|
110
|
+
drawLine(buffer, fromIdx, toIdx) {
|
|
111
|
+
const p1 = this.getPoint(fromIdx);
|
|
112
|
+
const p2 = this.getPoint(toIdx);
|
|
113
|
+
const y1 = p1.r * this.nodeSpacingY;
|
|
114
|
+
const x1 = p1.c * this.nodeSpacingX;
|
|
115
|
+
const y2 = p2.r * this.nodeSpacingY;
|
|
116
|
+
const x2 = p2.c * this.nodeSpacingX;
|
|
117
|
+
const dy = y2 - y1;
|
|
118
|
+
const dx = x2 - x1;
|
|
119
|
+
const steps = Math.max(Math.abs(dx), Math.abs(dy));
|
|
120
|
+
if (steps === 0)
|
|
121
|
+
return;
|
|
122
|
+
const yInc = dy / steps;
|
|
123
|
+
const xInc = dx / steps;
|
|
124
|
+
let y = y1;
|
|
125
|
+
let x = x1;
|
|
126
|
+
for (let i = 0; i <= steps; i++) {
|
|
127
|
+
const ry = Math.round(y);
|
|
128
|
+
const rx = Math.round(x);
|
|
129
|
+
// Check bounds
|
|
130
|
+
if (ry >= 0 && ry < buffer.length && rx >= 0 && rx < buffer[0].length) {
|
|
131
|
+
const isNode = (ry % this.nodeSpacingY === 0) && (rx % this.nodeSpacingX === 0);
|
|
132
|
+
if (!isNode) {
|
|
133
|
+
// Determine char based on slope
|
|
134
|
+
// Flat horizontal
|
|
135
|
+
if (dy === 0)
|
|
136
|
+
buffer[ry][rx] = '─';
|
|
137
|
+
// Flat vertical
|
|
138
|
+
else if (dx === 0)
|
|
139
|
+
buffer[ry][rx] = '│';
|
|
140
|
+
// Diagonal
|
|
141
|
+
else if ((dx > 0 && dy > 0) || (dx < 0 && dy < 0))
|
|
142
|
+
buffer[ry][rx] = '╲';
|
|
143
|
+
else
|
|
144
|
+
buffer[ry][rx] = '╱';
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
y += yInc;
|
|
148
|
+
x += xInc;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
handleInput(char, _key) {
|
|
152
|
+
// Navigation
|
|
153
|
+
if (this.isUp(char)) {
|
|
154
|
+
this.cursor.r = Math.max(0, this.cursor.r - 1);
|
|
155
|
+
this.render(false);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (this.isDown(char)) {
|
|
159
|
+
this.cursor.r = Math.min(this.rows - 1, this.cursor.r + 1);
|
|
160
|
+
this.render(false);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (this.isLeft(char)) {
|
|
164
|
+
this.cursor.c = Math.max(0, this.cursor.c - 1);
|
|
165
|
+
this.render(false);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (this.isRight(char)) {
|
|
169
|
+
this.cursor.c = Math.min(this.cols - 1, this.cursor.c + 1);
|
|
170
|
+
this.render(false);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
// Selection (Space)
|
|
174
|
+
if (char === ' ') {
|
|
175
|
+
const index = this.getIndex(this.cursor.r, this.cursor.c);
|
|
176
|
+
this.addToPath(index);
|
|
177
|
+
this.render(false);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
// Submit (Enter)
|
|
181
|
+
if (char === '\r' || char === '\n') {
|
|
182
|
+
if (this.path.length < 2) {
|
|
183
|
+
this.errorMsg = 'Pattern too short';
|
|
184
|
+
this.render(false);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
this.submit(this.path);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
// Backspace / Reset
|
|
191
|
+
if (char === '\x7f' || char === '\b') {
|
|
192
|
+
this.path.pop();
|
|
193
|
+
this.render(false);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
addToPath(index) {
|
|
198
|
+
if (this.path.includes(index)) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
this.path.push(index);
|
|
202
|
+
}
|
|
203
|
+
handleMouse(event) {
|
|
204
|
+
if (event.action === 'release') {
|
|
205
|
+
this.isDragging = false;
|
|
206
|
+
this.lastMouse = null;
|
|
207
|
+
if (this.path.length >= 2) {
|
|
208
|
+
this.submit(this.path);
|
|
209
|
+
}
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (this.lastMouse) {
|
|
213
|
+
const dx = event.x - this.lastMouse.x;
|
|
214
|
+
const dy = event.y - this.lastMouse.y;
|
|
215
|
+
// Sensitivity threshold
|
|
216
|
+
if (dx !== 0 || dy !== 0) {
|
|
217
|
+
if (Math.abs(dx) > Math.abs(dy)) {
|
|
218
|
+
if (dx > 0)
|
|
219
|
+
this.cursor.c = Math.min(this.cols - 1, this.cursor.c + 1);
|
|
220
|
+
else if (dx < 0)
|
|
221
|
+
this.cursor.c = Math.max(0, this.cursor.c - 1);
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
if (dy > 0)
|
|
225
|
+
this.cursor.r = Math.min(this.rows - 1, this.cursor.r + 1);
|
|
226
|
+
else if (dy < 0)
|
|
227
|
+
this.cursor.r = Math.max(0, this.cursor.r - 1);
|
|
228
|
+
}
|
|
229
|
+
if (this.isDragging) {
|
|
230
|
+
const idx = this.getIndex(this.cursor.r, this.cursor.c);
|
|
231
|
+
this.addToPath(idx);
|
|
232
|
+
}
|
|
233
|
+
this.render(false);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
// Mouse Down
|
|
238
|
+
if (event.action === 'press' && event.button === 0) {
|
|
239
|
+
this.isDragging = true;
|
|
240
|
+
this.path = []; // Reset
|
|
241
|
+
const idx = this.getIndex(this.cursor.r, this.cursor.c);
|
|
242
|
+
this.addToPath(idx);
|
|
243
|
+
this.render(false);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
this.lastMouse = { x: event.x, y: event.y };
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
exports.PatternPrompt = PatternPrompt;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { QuizSelectOptions } from '../types';
|
|
2
|
+
import { SelectPrompt } from './select';
|
|
3
|
+
export declare class QuizSelectPrompt<V> extends SelectPrompt<V, QuizSelectOptions<V>> {
|
|
4
|
+
private status;
|
|
5
|
+
private isCorrect;
|
|
6
|
+
private userSelectionIndex;
|
|
7
|
+
constructor(options: QuizSelectOptions<V>);
|
|
8
|
+
protected handleInput(char: string): void;
|
|
9
|
+
protected render(firstRender: boolean): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QuizSelectPrompt = void 0;
|
|
4
|
+
const ansi_1 = require("../ansi");
|
|
5
|
+
const theme_1 = require("../theme");
|
|
6
|
+
const symbols_1 = require("../symbols");
|
|
7
|
+
const select_1 = require("./select");
|
|
8
|
+
class QuizSelectPrompt extends select_1.SelectPrompt {
|
|
9
|
+
constructor(options) {
|
|
10
|
+
super(options);
|
|
11
|
+
this.status = 'pending';
|
|
12
|
+
this.isCorrect = false;
|
|
13
|
+
this.userSelectionIndex = -1;
|
|
14
|
+
}
|
|
15
|
+
handleInput(char) {
|
|
16
|
+
if (this.status === 'revealed') {
|
|
17
|
+
// Wait for Enter to submit
|
|
18
|
+
if (char === '\r' || char === '\n') {
|
|
19
|
+
const choices = this.getFilteredChoices();
|
|
20
|
+
// Ensure index is valid, though it should be captured
|
|
21
|
+
const value = choices[this.userSelectionIndex]
|
|
22
|
+
? choices[this.userSelectionIndex].value
|
|
23
|
+
: null;
|
|
24
|
+
this.submit(value);
|
|
25
|
+
}
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (this.status === 'pending') {
|
|
29
|
+
// Intercept Enter
|
|
30
|
+
if (char === '\r' || char === '\n') {
|
|
31
|
+
const choices = this.getFilteredChoices();
|
|
32
|
+
if (choices.length === 0)
|
|
33
|
+
return;
|
|
34
|
+
if (this.isSeparator(choices[this.selectedIndex]))
|
|
35
|
+
return;
|
|
36
|
+
this.userSelectionIndex = this.selectedIndex;
|
|
37
|
+
const selectedChoice = choices[this.userSelectionIndex];
|
|
38
|
+
// Check correctness
|
|
39
|
+
this.isCorrect = selectedChoice.value === this.options.correctValue;
|
|
40
|
+
this.status = 'revealed';
|
|
41
|
+
this.render(false);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
// Delegate navigation to super
|
|
45
|
+
super.handleInput(char);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
render(firstRender) {
|
|
49
|
+
if (this.status === 'pending') {
|
|
50
|
+
super.render(firstRender);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
// Revealed State
|
|
54
|
+
let output = '';
|
|
55
|
+
const choices = this.getFilteredChoices();
|
|
56
|
+
// Header
|
|
57
|
+
const icon = this.isCorrect ? `${theme_1.theme.success}${symbols_1.symbols.tick}` : `${theme_1.theme.error}${symbols_1.symbols.cross}`;
|
|
58
|
+
output += `${icon} ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET}\n`;
|
|
59
|
+
const visibleChoices = choices.slice(this.scrollTop, this.scrollTop + this.pageSize);
|
|
60
|
+
visibleChoices.forEach((choice, index) => {
|
|
61
|
+
if (index > 0)
|
|
62
|
+
output += '\n';
|
|
63
|
+
if (this.isSeparator(choice)) {
|
|
64
|
+
output += ` ${ansi_1.ANSI.DIM}${choice.text || symbols_1.symbols.line.repeat(8)}${ansi_1.ANSI.RESET}`;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
// Determine absolute index to match with user selection
|
|
68
|
+
const actualIndex = this.scrollTop + index;
|
|
69
|
+
const isSelected = actualIndex === this.userSelectionIndex;
|
|
70
|
+
const isCorrectAnswer = choice.value === this.options.correctValue;
|
|
71
|
+
let prefix = ' ';
|
|
72
|
+
let style = ansi_1.ANSI.RESET;
|
|
73
|
+
if (isSelected) {
|
|
74
|
+
if (this.isCorrect) {
|
|
75
|
+
prefix = `${theme_1.theme.success}${symbols_1.symbols.pointer} `;
|
|
76
|
+
style = theme_1.theme.success;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
prefix = `${theme_1.theme.error}${symbols_1.symbols.cross} `;
|
|
80
|
+
style = theme_1.theme.error;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else if (isCorrectAnswer) {
|
|
84
|
+
prefix = `${theme_1.theme.success}${symbols_1.symbols.pointer} `;
|
|
85
|
+
style = theme_1.theme.success;
|
|
86
|
+
}
|
|
87
|
+
output += `${prefix}${style}${choice.title}${ansi_1.ANSI.RESET}`;
|
|
88
|
+
if (isSelected && !this.isCorrect) {
|
|
89
|
+
output += ` ${theme_1.theme.error}(Your Answer)${ansi_1.ANSI.RESET}`;
|
|
90
|
+
}
|
|
91
|
+
if (isCorrectAnswer && !isSelected) {
|
|
92
|
+
output += ` ${theme_1.theme.success}(Correct)${ansi_1.ANSI.RESET}`;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
// Explanation
|
|
97
|
+
if (this.options.explanation) {
|
|
98
|
+
output += `\n\n${ansi_1.ANSI.BOLD}Explanation:${ansi_1.ANSI.RESET}\n${theme_1.theme.muted}${this.options.explanation}${ansi_1.ANSI.RESET}`;
|
|
99
|
+
}
|
|
100
|
+
output += `\n\n${ansi_1.ANSI.DIM}(Press Enter to continue)${ansi_1.ANSI.RESET}`;
|
|
101
|
+
this.renderFrame(output);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.QuizSelectPrompt = QuizSelectPrompt;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { QuizTextOptions } from '../types';
|
|
2
|
+
import { TextPrompt } from './text';
|
|
3
|
+
export declare class QuizTextPrompt extends TextPrompt<QuizTextOptions> {
|
|
4
|
+
private status;
|
|
5
|
+
private isCorrect;
|
|
6
|
+
constructor(options: QuizTextOptions);
|
|
7
|
+
protected handleInput(char: string): void;
|
|
8
|
+
protected submit(value: string): void;
|
|
9
|
+
private checkCorrectness;
|
|
10
|
+
protected render(firstRender: boolean): void;
|
|
11
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QuizTextPrompt = void 0;
|
|
4
|
+
const ansi_1 = require("../ansi");
|
|
5
|
+
const theme_1 = require("../theme");
|
|
6
|
+
const symbols_1 = require("../symbols");
|
|
7
|
+
const text_1 = require("./text");
|
|
8
|
+
class QuizTextPrompt extends text_1.TextPrompt {
|
|
9
|
+
constructor(options) {
|
|
10
|
+
super(options);
|
|
11
|
+
this.status = 'pending';
|
|
12
|
+
this.isCorrect = false;
|
|
13
|
+
}
|
|
14
|
+
handleInput(char) {
|
|
15
|
+
if (this.status === 'revealed') {
|
|
16
|
+
if (char === '\r' || char === '\n') {
|
|
17
|
+
this.submit(this.value);
|
|
18
|
+
}
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
super.handleInput(char);
|
|
22
|
+
}
|
|
23
|
+
submit(value) {
|
|
24
|
+
if (this.status === 'pending') {
|
|
25
|
+
// We caught the submission from TextPrompt logic.
|
|
26
|
+
// Now verify correctness.
|
|
27
|
+
this.checkCorrectness(value).then(correct => {
|
|
28
|
+
this.isCorrect = correct;
|
|
29
|
+
this.status = 'revealed';
|
|
30
|
+
this.render(false);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
// If revealed (or anything else), we proceed to final submission.
|
|
35
|
+
// This calls Prompt.submit
|
|
36
|
+
super.submit(value);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async checkCorrectness(value) {
|
|
40
|
+
try {
|
|
41
|
+
if (this.options.verify) {
|
|
42
|
+
return await this.options.verify(value);
|
|
43
|
+
}
|
|
44
|
+
if (this.options.correctAnswer) {
|
|
45
|
+
return value.trim().toLowerCase() === this.options.correctAnswer.trim().toLowerCase();
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
catch (_e) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
render(firstRender) {
|
|
54
|
+
if (this.status === 'pending') {
|
|
55
|
+
super.render(firstRender);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
// Revealed State
|
|
59
|
+
let output = '';
|
|
60
|
+
const icon = this.isCorrect ? `${theme_1.theme.success}${symbols_1.symbols.tick}` : `${theme_1.theme.error}${symbols_1.symbols.cross}`;
|
|
61
|
+
output += `${icon} ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET}\n`;
|
|
62
|
+
const userValue = this.segments.join('');
|
|
63
|
+
// Display user input
|
|
64
|
+
if (this.isCorrect) {
|
|
65
|
+
output += ` ${theme_1.theme.success}${userValue}${ansi_1.ANSI.RESET} ${theme_1.theme.success}(Correct)${ansi_1.ANSI.RESET}`;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
output += ` ${theme_1.theme.error}${userValue}${ansi_1.ANSI.RESET} ${theme_1.theme.error}(Wrong)${ansi_1.ANSI.RESET}`;
|
|
69
|
+
}
|
|
70
|
+
// Show correct answer if wrong
|
|
71
|
+
if (!this.isCorrect && this.options.correctAnswer) {
|
|
72
|
+
output += `\n ${theme_1.theme.success}Correct Answer: ${this.options.correctAnswer}${ansi_1.ANSI.RESET}`;
|
|
73
|
+
}
|
|
74
|
+
// Explanation
|
|
75
|
+
if (this.options.explanation) {
|
|
76
|
+
output += `\n\n${ansi_1.ANSI.BOLD}Explanation:${ansi_1.ANSI.RESET}\n${theme_1.theme.muted}${this.options.explanation}${ansi_1.ANSI.RESET}`;
|
|
77
|
+
}
|
|
78
|
+
output += `\n\n${ansi_1.ANSI.DIM}(Press Enter to continue)${ansi_1.ANSI.RESET}`;
|
|
79
|
+
this.renderFrame(output);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.QuizTextPrompt = QuizTextPrompt;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Prompt } from '../base';
|
|
2
|
+
import { RegexOptions } from '../types';
|
|
3
|
+
export declare class RegexPrompt extends Prompt<RegExp, RegexOptions> {
|
|
4
|
+
private input;
|
|
5
|
+
private cursor;
|
|
6
|
+
private segments;
|
|
7
|
+
private error;
|
|
8
|
+
private regex;
|
|
9
|
+
constructor(options: RegexOptions);
|
|
10
|
+
private validateRegex;
|
|
11
|
+
protected render(_firstRender: boolean): void;
|
|
12
|
+
protected handleInput(char: string, _key: Buffer): void;
|
|
13
|
+
}
|