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/index.js
CHANGED
|
@@ -20,3 +20,39 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
21
|
__exportStar(require("./types"), exports);
|
|
22
22
|
__exportStar(require("./core"), exports);
|
|
23
|
+
__exportStar(require("./prompts/map"), exports);
|
|
24
|
+
__exportStar(require("./prompts/semver"), exports);
|
|
25
|
+
__exportStar(require("./prompts/ip"), exports);
|
|
26
|
+
__exportStar(require("./prompts/kanban"), exports);
|
|
27
|
+
__exportStar(require("./prompts/time"), exports);
|
|
28
|
+
__exportStar(require("./prompts/heatmap"), exports);
|
|
29
|
+
__exportStar(require("./prompts/byte"), exports);
|
|
30
|
+
__exportStar(require("./prompts/slot"), exports);
|
|
31
|
+
__exportStar(require("./prompts/gauge"), exports);
|
|
32
|
+
__exportStar(require("./prompts/calculator"), exports);
|
|
33
|
+
__exportStar(require("./prompts/emoji"), exports);
|
|
34
|
+
__exportStar(require("./prompts/match"), exports);
|
|
35
|
+
__exportStar(require("./prompts/diff"), exports);
|
|
36
|
+
__exportStar(require("./prompts/dial"), exports);
|
|
37
|
+
__exportStar(require("./prompts/draw"), exports);
|
|
38
|
+
__exportStar(require("./prompts/multi-column-select"), exports);
|
|
39
|
+
__exportStar(require("./prompts/fuzzy"), exports);
|
|
40
|
+
__exportStar(require("./prompts/miller"), exports);
|
|
41
|
+
__exportStar(require("./prompts/pattern"), exports);
|
|
42
|
+
__exportStar(require("./prompts/region"), exports);
|
|
43
|
+
__exportStar(require("./prompts/spreadsheet"), exports);
|
|
44
|
+
__exportStar(require("./prompts/scroll"), exports);
|
|
45
|
+
__exportStar(require("./prompts/breadcrumb"), exports);
|
|
46
|
+
__exportStar(require("./prompts/schedule"), exports);
|
|
47
|
+
__exportStar(require("./prompts/data-inspector"), exports);
|
|
48
|
+
__exportStar(require("./prompts/exec"), exports);
|
|
49
|
+
__exportStar(require("./prompts/shortcut"), exports);
|
|
50
|
+
__exportStar(require("./prompts/seat"), exports);
|
|
51
|
+
__exportStar(require("./prompts/select-range"), exports);
|
|
52
|
+
__exportStar(require("./prompts/sort-grid"), exports);
|
|
53
|
+
__exportStar(require("./prompts/dependency"), exports);
|
|
54
|
+
__exportStar(require("./prompts/license"), exports);
|
|
55
|
+
__exportStar(require("./prompts/regex"), exports);
|
|
56
|
+
__exportStar(require("./prompts/box"), exports);
|
|
57
|
+
__exportStar(require("./prompts/connection-string"), exports);
|
|
58
|
+
__exportStar(require("./prompts/curl"), exports);
|
package/dist/input.js
CHANGED
|
@@ -146,9 +146,6 @@ class InputParser extends events_1.EventEmitter {
|
|
|
146
146
|
// Normalize Enter
|
|
147
147
|
if (key === '\r')
|
|
148
148
|
key = '\n';
|
|
149
|
-
// We emit both the raw sequence and a normalized representation if needed,
|
|
150
|
-
// but existing prompt logic handles raw strings like \x1b[A.
|
|
151
|
-
// So we just emit the reconstructed sequence.
|
|
152
149
|
this.emit('keypress', key, Buffer.from(key));
|
|
153
150
|
}
|
|
154
151
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Prompt } from '../base';
|
|
2
|
+
import { BoxOptions, MouseEvent } from '../types';
|
|
3
|
+
interface BoxValues {
|
|
4
|
+
top: number;
|
|
5
|
+
right: number;
|
|
6
|
+
bottom: number;
|
|
7
|
+
left: number;
|
|
8
|
+
}
|
|
9
|
+
export declare class BoxPrompt extends Prompt<BoxValues, BoxOptions> {
|
|
10
|
+
private values;
|
|
11
|
+
private focus;
|
|
12
|
+
private inputBuffer;
|
|
13
|
+
constructor(options: BoxOptions);
|
|
14
|
+
private commitBuffer;
|
|
15
|
+
private changeFocus;
|
|
16
|
+
private increment;
|
|
17
|
+
protected render(_firstRender: boolean): void;
|
|
18
|
+
protected handleMouse(event: MouseEvent): void;
|
|
19
|
+
protected handleInput(char: string, _key: Buffer): void;
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BoxPrompt = void 0;
|
|
4
|
+
const base_1 = require("../base");
|
|
5
|
+
const ansi_1 = require("../ansi");
|
|
6
|
+
const theme_1 = require("../theme");
|
|
7
|
+
class BoxPrompt extends base_1.Prompt {
|
|
8
|
+
constructor(options) {
|
|
9
|
+
super(options);
|
|
10
|
+
this.focus = 'top';
|
|
11
|
+
this.inputBuffer = '';
|
|
12
|
+
const initial = options.initial;
|
|
13
|
+
if (typeof initial === 'number') {
|
|
14
|
+
this.values = { top: initial, right: initial, bottom: initial, left: initial };
|
|
15
|
+
}
|
|
16
|
+
else if (typeof initial === 'object') {
|
|
17
|
+
this.values = {
|
|
18
|
+
top: initial.top ?? 0,
|
|
19
|
+
right: initial.right ?? 0,
|
|
20
|
+
bottom: initial.bottom ?? 0,
|
|
21
|
+
left: initial.left ?? 0
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
this.values = { top: 0, right: 0, bottom: 0, left: 0 };
|
|
26
|
+
}
|
|
27
|
+
this.inputBuffer = this.values.top.toString();
|
|
28
|
+
}
|
|
29
|
+
commitBuffer() {
|
|
30
|
+
let val = parseInt(this.inputBuffer, 10);
|
|
31
|
+
if (isNaN(val))
|
|
32
|
+
val = 0;
|
|
33
|
+
// Apply constraints
|
|
34
|
+
if (this.options.min !== undefined && val < this.options.min)
|
|
35
|
+
val = this.options.min;
|
|
36
|
+
if (this.options.max !== undefined && val > this.options.max)
|
|
37
|
+
val = this.options.max;
|
|
38
|
+
this.values[this.focus] = val;
|
|
39
|
+
this.inputBuffer = val.toString(); // Normalize buffer
|
|
40
|
+
}
|
|
41
|
+
changeFocus(newFocus) {
|
|
42
|
+
this.commitBuffer(); // Save current
|
|
43
|
+
this.focus = newFocus;
|
|
44
|
+
this.inputBuffer = this.values[newFocus].toString();
|
|
45
|
+
}
|
|
46
|
+
increment(amount) {
|
|
47
|
+
let val = parseInt(this.inputBuffer, 10);
|
|
48
|
+
if (isNaN(val))
|
|
49
|
+
val = 0;
|
|
50
|
+
val += amount;
|
|
51
|
+
if (this.options.min !== undefined && val < this.options.min)
|
|
52
|
+
val = this.options.min;
|
|
53
|
+
if (this.options.max !== undefined && val > this.options.max)
|
|
54
|
+
val = this.options.max;
|
|
55
|
+
this.inputBuffer = val.toString();
|
|
56
|
+
}
|
|
57
|
+
render(_firstRender) {
|
|
58
|
+
const title = `${theme_1.theme.success}? ${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET} (Arrows to navigate, Numbers to edit)`;
|
|
59
|
+
// Format value function
|
|
60
|
+
const formatVal = (side) => {
|
|
61
|
+
const isFocused = this.focus === side;
|
|
62
|
+
const text = isFocused ? this.inputBuffer : this.values[side].toString();
|
|
63
|
+
if (isFocused) {
|
|
64
|
+
return `${ansi_1.ANSI.FG_CYAN}${ansi_1.ANSI.BOLD}[ ${text} ]${ansi_1.ANSI.RESET}`;
|
|
65
|
+
}
|
|
66
|
+
return ` ${text} `;
|
|
67
|
+
};
|
|
68
|
+
const vTop = formatVal('top');
|
|
69
|
+
const vRight = formatVal('right');
|
|
70
|
+
const vBottom = formatVal('bottom');
|
|
71
|
+
const vLeft = formatVal('left');
|
|
72
|
+
// Layout
|
|
73
|
+
// [ Top ]
|
|
74
|
+
// [ Left ] [ Right ]
|
|
75
|
+
// [ Bottom ]
|
|
76
|
+
// We need to pad to align them nicely.
|
|
77
|
+
// Simple manual padding for MVP.
|
|
78
|
+
// Calculate center padding based on longest string?
|
|
79
|
+
// Keep it simple.
|
|
80
|
+
let output = title + '\n\n';
|
|
81
|
+
// Top Row (Centered)
|
|
82
|
+
output += ` ${vTop}\n`;
|
|
83
|
+
// Middle Row
|
|
84
|
+
output += ` ${vLeft} ${vRight}\n`;
|
|
85
|
+
// Bottom Row
|
|
86
|
+
output += ` ${vBottom}\n`;
|
|
87
|
+
this.renderFrame(output);
|
|
88
|
+
}
|
|
89
|
+
handleMouse(event) {
|
|
90
|
+
if (event.name === 'mouse' && event.action === 'scroll') {
|
|
91
|
+
const order = ['top', 'right', 'bottom', 'left'];
|
|
92
|
+
const idx = order.indexOf(this.focus);
|
|
93
|
+
if (event.scroll === 'down') {
|
|
94
|
+
// Next (Down usually means going forward/down in list)
|
|
95
|
+
this.changeFocus(order[(idx + 1) % 4]);
|
|
96
|
+
}
|
|
97
|
+
else if (event.scroll === 'up') {
|
|
98
|
+
// Previous
|
|
99
|
+
this.changeFocus(order[(idx + 3) % 4]); // +3 is same as -1 in mod 4
|
|
100
|
+
}
|
|
101
|
+
this.render(false);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
handleInput(char, _key) {
|
|
105
|
+
// Enter -> Submit
|
|
106
|
+
if (char === '\r' || char === '\n') {
|
|
107
|
+
this.commitBuffer();
|
|
108
|
+
this.submit(this.values);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
// Navigation
|
|
112
|
+
if (this.isUp(char)) {
|
|
113
|
+
if (this.focus === 'bottom' || this.focus === 'left' || this.focus === 'right') {
|
|
114
|
+
this.changeFocus('top');
|
|
115
|
+
}
|
|
116
|
+
this.render(false);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (this.isDown(char)) {
|
|
120
|
+
if (this.focus === 'top' || this.focus === 'left' || this.focus === 'right') {
|
|
121
|
+
this.changeFocus('bottom');
|
|
122
|
+
}
|
|
123
|
+
this.render(false);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (this.isLeft(char)) {
|
|
127
|
+
if (this.focus === 'right' || this.focus === 'top' || this.focus === 'bottom') {
|
|
128
|
+
this.changeFocus('left');
|
|
129
|
+
}
|
|
130
|
+
this.render(false);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (this.isRight(char)) {
|
|
134
|
+
if (this.focus === 'left' || this.focus === 'top' || this.focus === 'bottom') {
|
|
135
|
+
this.changeFocus('right');
|
|
136
|
+
}
|
|
137
|
+
this.render(false);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// Tab Cycling
|
|
141
|
+
if (char === '\t') {
|
|
142
|
+
const order = ['top', 'right', 'bottom', 'left'];
|
|
143
|
+
const idx = order.indexOf(this.focus);
|
|
144
|
+
this.changeFocus(order[(idx + 1) % 4]);
|
|
145
|
+
this.render(false);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
// Shift+Tab Cycling (\u001b[Z)
|
|
149
|
+
if (char === '\u001b[Z') {
|
|
150
|
+
const order = ['top', 'right', 'bottom', 'left'];
|
|
151
|
+
const idx = order.indexOf(this.focus);
|
|
152
|
+
this.changeFocus(order[(idx + 3) % 4]); // (idx - 1) % 4 handling negative
|
|
153
|
+
this.render(false);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
// Increment/Decrement (+ / -)
|
|
157
|
+
const step = this.options.step || 1;
|
|
158
|
+
if (char === '+' || char === '=') { // = is usually unshifted +
|
|
159
|
+
this.increment(step);
|
|
160
|
+
this.render(false);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (char === '-' || char === '_') {
|
|
164
|
+
this.increment(-step);
|
|
165
|
+
this.render(false);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
// Typing Numbers
|
|
169
|
+
if (/^[0-9]$/.test(char)) {
|
|
170
|
+
// Special case: if buffer is "0", replace it unless we are appending
|
|
171
|
+
if (this.inputBuffer === '0') {
|
|
172
|
+
this.inputBuffer = char;
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
this.inputBuffer += char;
|
|
176
|
+
}
|
|
177
|
+
this.render(false);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
// Backspace
|
|
181
|
+
if (char === '\u0008' || char === '\x7f') {
|
|
182
|
+
if (this.inputBuffer.length > 0) {
|
|
183
|
+
this.inputBuffer = this.inputBuffer.slice(0, -1);
|
|
184
|
+
if (this.inputBuffer === '')
|
|
185
|
+
this.inputBuffer = '0'; // default to 0
|
|
186
|
+
}
|
|
187
|
+
this.render(false);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
exports.BoxPrompt = BoxPrompt;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Prompt } from '../base';
|
|
2
|
+
import { BreadcrumbOptions, MouseEvent } from '../types';
|
|
3
|
+
export declare class BreadcrumbPrompt extends Prompt<string, BreadcrumbOptions> {
|
|
4
|
+
private stack;
|
|
5
|
+
private currentEntries;
|
|
6
|
+
private cursor;
|
|
7
|
+
private scrollTop;
|
|
8
|
+
private root;
|
|
9
|
+
private currentPath;
|
|
10
|
+
private separator;
|
|
11
|
+
private showHidden;
|
|
12
|
+
private isLoading;
|
|
13
|
+
private error;
|
|
14
|
+
private readonly pageSize;
|
|
15
|
+
constructor(options: BreadcrumbOptions);
|
|
16
|
+
private loadDirectory;
|
|
17
|
+
private drillDown;
|
|
18
|
+
private goUp;
|
|
19
|
+
protected render(_firstRender: boolean): void;
|
|
20
|
+
protected handleInput(char: string, _key: Buffer): void;
|
|
21
|
+
protected handleMouse(_event: MouseEvent): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.BreadcrumbPrompt = void 0;
|
|
37
|
+
const base_1 = require("../base");
|
|
38
|
+
const ansi_1 = require("../ansi");
|
|
39
|
+
const theme_1 = require("../theme");
|
|
40
|
+
const symbols_1 = require("../symbols");
|
|
41
|
+
const fs = __importStar(require("fs/promises"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
class BreadcrumbPrompt extends base_1.Prompt {
|
|
44
|
+
constructor(options) {
|
|
45
|
+
super(options);
|
|
46
|
+
this.stack = [];
|
|
47
|
+
this.currentEntries = [];
|
|
48
|
+
this.cursor = 0;
|
|
49
|
+
this.scrollTop = 0;
|
|
50
|
+
this.isLoading = false;
|
|
51
|
+
this.error = null;
|
|
52
|
+
this.pageSize = 10;
|
|
53
|
+
this.root = path.resolve(options.root || process.cwd());
|
|
54
|
+
this.currentPath = this.root;
|
|
55
|
+
this.separator = options.separator || ' › ';
|
|
56
|
+
this.showHidden = options.showHidden || false;
|
|
57
|
+
this.loadDirectory(this.currentPath);
|
|
58
|
+
}
|
|
59
|
+
async loadDirectory(dir) {
|
|
60
|
+
this.isLoading = true;
|
|
61
|
+
this.error = null;
|
|
62
|
+
this.render(false);
|
|
63
|
+
try {
|
|
64
|
+
await fs.access(dir);
|
|
65
|
+
const dirents = await fs.readdir(dir, { withFileTypes: true });
|
|
66
|
+
let entries = dirents.map(d => ({
|
|
67
|
+
name: d.name,
|
|
68
|
+
isDirectory: d.isDirectory()
|
|
69
|
+
}));
|
|
70
|
+
if (!this.showHidden) {
|
|
71
|
+
entries = entries.filter(e => !e.name.startsWith('.'));
|
|
72
|
+
}
|
|
73
|
+
entries.sort((a, b) => {
|
|
74
|
+
if (a.isDirectory === b.isDirectory) {
|
|
75
|
+
return a.name.localeCompare(b.name);
|
|
76
|
+
}
|
|
77
|
+
return a.isDirectory ? -1 : 1;
|
|
78
|
+
});
|
|
79
|
+
this.currentEntries = entries;
|
|
80
|
+
if (this.currentEntries.length === 0) {
|
|
81
|
+
this.cursor = 0;
|
|
82
|
+
}
|
|
83
|
+
else if (this.cursor >= this.currentEntries.length) {
|
|
84
|
+
this.cursor = this.currentEntries.length - 1;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
this.error = err.message || 'Error reading directory';
|
|
89
|
+
this.currentEntries = [];
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
this.isLoading = false;
|
|
93
|
+
this.render(false);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async drillDown() {
|
|
97
|
+
const entry = this.currentEntries[this.cursor];
|
|
98
|
+
if (!entry || !entry.isDirectory)
|
|
99
|
+
return;
|
|
100
|
+
const nextPath = path.join(this.currentPath, entry.name);
|
|
101
|
+
this.stack.push({
|
|
102
|
+
path: this.currentPath,
|
|
103
|
+
cursor: this.cursor,
|
|
104
|
+
scrollTop: this.scrollTop
|
|
105
|
+
});
|
|
106
|
+
this.currentPath = nextPath;
|
|
107
|
+
this.cursor = 0;
|
|
108
|
+
this.scrollTop = 0;
|
|
109
|
+
await this.loadDirectory(nextPath);
|
|
110
|
+
}
|
|
111
|
+
async goUp() {
|
|
112
|
+
if (this.stack.length === 0)
|
|
113
|
+
return;
|
|
114
|
+
const prevState = this.stack.pop();
|
|
115
|
+
if (prevState) {
|
|
116
|
+
this.currentPath = prevState.path;
|
|
117
|
+
this.cursor = prevState.cursor;
|
|
118
|
+
this.scrollTop = prevState.scrollTop;
|
|
119
|
+
await this.loadDirectory(this.currentPath);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
render(_firstRender) {
|
|
123
|
+
const width = this.stdout.columns || 80;
|
|
124
|
+
let output = '';
|
|
125
|
+
// --- Breadcrumb Line Construction ---
|
|
126
|
+
const relative = path.relative(this.root, this.currentPath);
|
|
127
|
+
const parts = relative ? relative.split(path.sep) : [];
|
|
128
|
+
const rootName = path.basename(this.root);
|
|
129
|
+
const segments = [rootName, ...parts];
|
|
130
|
+
// Calculate available space for path
|
|
131
|
+
// Prefix: "? Message: "
|
|
132
|
+
const prefix = `${theme_1.theme.success}?${ansi_1.ANSI.RESET} ${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET} `;
|
|
133
|
+
const prefixWidth = this.stripAnsi(prefix).length;
|
|
134
|
+
const availableWidth = Math.max(20, width - prefixWidth - 5); // Reserve 5 chars buffer
|
|
135
|
+
let breadcrumbStr = segments.join(this.separator);
|
|
136
|
+
if (breadcrumbStr.length > availableWidth) {
|
|
137
|
+
// Truncate logic: Keep root and tail segments that fit
|
|
138
|
+
// e.g., root > ... > folder > subfolder
|
|
139
|
+
let suffix = segments[segments.length - 1];
|
|
140
|
+
for (let i = segments.length - 2; i >= 1; i--) { // Stop before root (index 0)
|
|
141
|
+
const next = segments[i] + this.separator + suffix;
|
|
142
|
+
if (next.length + 4 > availableWidth)
|
|
143
|
+
break; // +4 for "... "
|
|
144
|
+
suffix = next;
|
|
145
|
+
}
|
|
146
|
+
breadcrumbStr = `${segments[0]}${this.separator}...${this.separator}${suffix}`;
|
|
147
|
+
// If even that is too long (extreme case), just truncate tail
|
|
148
|
+
if (breadcrumbStr.length > availableWidth) {
|
|
149
|
+
breadcrumbStr = '...' + breadcrumbStr.slice(-(availableWidth - 3));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
output += `${prefix}${breadcrumbStr}\n`;
|
|
153
|
+
// --- Content / List ---
|
|
154
|
+
if (this.isLoading) {
|
|
155
|
+
output += ` ${theme_1.theme.muted}Loading...${ansi_1.ANSI.RESET}`;
|
|
156
|
+
}
|
|
157
|
+
else if (this.error) {
|
|
158
|
+
output += ` ${theme_1.theme.error}${this.error}${ansi_1.ANSI.RESET}`;
|
|
159
|
+
}
|
|
160
|
+
else if (this.currentEntries.length === 0) {
|
|
161
|
+
output += ` ${theme_1.theme.muted}(Empty directory)${ansi_1.ANSI.RESET}\n ${theme_1.theme.muted}(Backspace to go back)${ansi_1.ANSI.RESET}`;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
// Adjust Scroll Top
|
|
165
|
+
if (this.cursor < this.scrollTop) {
|
|
166
|
+
this.scrollTop = this.cursor;
|
|
167
|
+
}
|
|
168
|
+
else if (this.cursor >= this.scrollTop + this.pageSize) {
|
|
169
|
+
this.scrollTop = this.cursor - this.pageSize + 1;
|
|
170
|
+
}
|
|
171
|
+
// Sanity check
|
|
172
|
+
if (this.scrollTop > this.currentEntries.length - 1) {
|
|
173
|
+
this.scrollTop = Math.max(0, this.currentEntries.length - this.pageSize);
|
|
174
|
+
}
|
|
175
|
+
const visibleEntries = this.currentEntries.slice(this.scrollTop, this.scrollTop + this.pageSize);
|
|
176
|
+
visibleEntries.forEach((entry, index) => {
|
|
177
|
+
const absoluteIndex = this.scrollTop + index;
|
|
178
|
+
const isSelected = absoluteIndex === this.cursor;
|
|
179
|
+
const icon = entry.isDirectory ? '📂' : '📄';
|
|
180
|
+
let line = '';
|
|
181
|
+
if (isSelected) {
|
|
182
|
+
line += `${theme_1.theme.main}${symbols_1.symbols.pointer} ${icon} ${entry.name}${ansi_1.ANSI.RESET}`;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
line += ` ${icon} ${entry.name}`;
|
|
186
|
+
}
|
|
187
|
+
if (index > 0 || index === 0)
|
|
188
|
+
output += line;
|
|
189
|
+
if (index < visibleEntries.length - 1)
|
|
190
|
+
output += '\n';
|
|
191
|
+
});
|
|
192
|
+
// Add a hint about navigation if plenty of space?
|
|
193
|
+
// Optional: output += `\n${theme.muted}(Use Arrow Keys, Enter to Select, Backspace to Up)${ANSI.RESET}`;
|
|
194
|
+
}
|
|
195
|
+
this.renderFrame(output);
|
|
196
|
+
}
|
|
197
|
+
handleInput(char, _key) {
|
|
198
|
+
if (this.isLoading)
|
|
199
|
+
return;
|
|
200
|
+
// Enter
|
|
201
|
+
if (char === '\r' || char === '\n') {
|
|
202
|
+
if (this.currentEntries.length === 0)
|
|
203
|
+
return;
|
|
204
|
+
const entry = this.currentEntries[this.cursor];
|
|
205
|
+
if (entry.isDirectory) {
|
|
206
|
+
this.drillDown();
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
const fullPath = path.join(this.currentPath, entry.name);
|
|
210
|
+
this.submit(fullPath);
|
|
211
|
+
}
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
// Backspace or Left Arrow
|
|
215
|
+
if (char === '\x7f' || char === '\x08' || this.isLeft(char)) {
|
|
216
|
+
this.goUp();
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
// Right Arrow
|
|
220
|
+
if (this.isRight(char)) {
|
|
221
|
+
const entry = this.currentEntries[this.cursor];
|
|
222
|
+
if (entry && entry.isDirectory) {
|
|
223
|
+
this.drillDown();
|
|
224
|
+
}
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
// Tab (Next)
|
|
228
|
+
if (char === '\t') {
|
|
229
|
+
if (this.currentEntries.length === 0)
|
|
230
|
+
return;
|
|
231
|
+
this.cursor = (this.cursor + 1) % this.currentEntries.length;
|
|
232
|
+
this.render(false);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
// Shift+Tab (Prev)
|
|
236
|
+
if (char === '\x1b[Z') {
|
|
237
|
+
if (this.currentEntries.length === 0)
|
|
238
|
+
return;
|
|
239
|
+
this.cursor = (this.cursor - 1 + this.currentEntries.length) % this.currentEntries.length;
|
|
240
|
+
this.render(false);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
// Up
|
|
244
|
+
if (this.isUp(char)) {
|
|
245
|
+
if (this.cursor > 0) {
|
|
246
|
+
this.cursor--;
|
|
247
|
+
this.render(false);
|
|
248
|
+
}
|
|
249
|
+
else if (this.currentEntries.length > 0) {
|
|
250
|
+
// Cycle to bottom?
|
|
251
|
+
this.cursor = this.currentEntries.length - 1;
|
|
252
|
+
this.render(false);
|
|
253
|
+
}
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
// Down
|
|
257
|
+
if (this.isDown(char)) {
|
|
258
|
+
if (this.cursor < this.currentEntries.length - 1) {
|
|
259
|
+
this.cursor++;
|
|
260
|
+
this.render(false);
|
|
261
|
+
}
|
|
262
|
+
else if (this.currentEntries.length > 0) {
|
|
263
|
+
// Cycle to top?
|
|
264
|
+
this.cursor = 0;
|
|
265
|
+
this.render(false);
|
|
266
|
+
}
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
// Page Up
|
|
270
|
+
if (char === '\x1b[5~') {
|
|
271
|
+
this.cursor = Math.max(0, this.cursor - this.pageSize);
|
|
272
|
+
this.render(false);
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
// Page Down
|
|
276
|
+
if (char === '\x1b[6~') {
|
|
277
|
+
this.cursor = Math.min(this.currentEntries.length - 1, this.cursor + this.pageSize);
|
|
278
|
+
this.render(false);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
handleMouse(_event) {
|
|
283
|
+
// Scroll up and down
|
|
284
|
+
if (this.isLoading)
|
|
285
|
+
return;
|
|
286
|
+
if (_event.action === 'scroll') {
|
|
287
|
+
if (_event.scroll === 'up') {
|
|
288
|
+
if (this.cursor > 0) {
|
|
289
|
+
this.cursor--;
|
|
290
|
+
this.render(false);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
else if (_event.scroll === 'down') {
|
|
294
|
+
if (this.cursor < this.currentEntries.length - 1) {
|
|
295
|
+
this.cursor++;
|
|
296
|
+
this.render(false);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
exports.BreadcrumbPrompt = BreadcrumbPrompt;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Prompt } from '../base';
|
|
2
|
+
import { ByteOptions, MouseEvent } from '../types';
|
|
3
|
+
export declare class BytePrompt extends Prompt<number, ByteOptions> {
|
|
4
|
+
private inputValue;
|
|
5
|
+
private buffer;
|
|
6
|
+
private unitIndex;
|
|
7
|
+
private errorMsg;
|
|
8
|
+
constructor(options: ByteOptions);
|
|
9
|
+
protected render(_firstRender: boolean): void;
|
|
10
|
+
protected handleInput(char: string): void;
|
|
11
|
+
private formatBytes;
|
|
12
|
+
protected handleMouse(event: MouseEvent): void;
|
|
13
|
+
}
|