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
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DiffPrompt = void 0;
|
|
4
|
+
const base_1 = require("../base");
|
|
5
|
+
const theme_1 = require("../theme");
|
|
6
|
+
const ansi_1 = require("../ansi");
|
|
7
|
+
const editor_1 = require("./editor");
|
|
8
|
+
class DiffPrompt extends base_1.Prompt {
|
|
9
|
+
constructor(options) {
|
|
10
|
+
super(options);
|
|
11
|
+
this.activeAction = 0; // 0: Original, 1: Modified, 2: Edit
|
|
12
|
+
this.actions = ['Use Original', 'Use Modified', 'Edit'];
|
|
13
|
+
}
|
|
14
|
+
render(_firstRender) {
|
|
15
|
+
let output = `${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET}\n`;
|
|
16
|
+
// Render Diff
|
|
17
|
+
const originalLines = this.options.original ? this.options.original.split('\n') : [];
|
|
18
|
+
const modifiedLines = this.options.modified ? this.options.modified.split('\n') : [];
|
|
19
|
+
const width = Math.max(40, (this.stdout.columns || 80) - 4);
|
|
20
|
+
const borderTop = `${ansi_1.ANSI.FG_GRAY}┌${'─'.repeat(width)}┐${ansi_1.ANSI.RESET}`;
|
|
21
|
+
const borderMid = `${ansi_1.ANSI.FG_GRAY}├${'─'.repeat(width)}┤${ansi_1.ANSI.RESET}`;
|
|
22
|
+
const borderBot = `${ansi_1.ANSI.FG_GRAY}└${'─'.repeat(width)}┘${ansi_1.ANSI.RESET}`;
|
|
23
|
+
output += borderTop + '\n';
|
|
24
|
+
// Original (Red)
|
|
25
|
+
if (originalLines.length === 0) {
|
|
26
|
+
output += `${ansi_1.ANSI.FG_GRAY}│ ${ansi_1.ANSI.DIM}(empty)${ansi_1.ANSI.RESET}\n`;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
originalLines.forEach(line => {
|
|
30
|
+
const truncated = this.truncate(line, width - 4);
|
|
31
|
+
output += `${ansi_1.ANSI.FG_GRAY}│ ${ansi_1.ANSI.FG_RED}- ${truncated}${ansi_1.ANSI.RESET}\n`;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
output += borderMid + '\n';
|
|
35
|
+
// Modified (Green)
|
|
36
|
+
if (modifiedLines.length === 0) {
|
|
37
|
+
output += `${ansi_1.ANSI.FG_GRAY}│ ${ansi_1.ANSI.DIM}(empty)${ansi_1.ANSI.RESET}\n`;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
modifiedLines.forEach(line => {
|
|
41
|
+
const truncated = this.truncate(line, width - 4);
|
|
42
|
+
output += `${ansi_1.ANSI.FG_GRAY}│ ${ansi_1.ANSI.FG_GREEN}+ ${truncated}${ansi_1.ANSI.RESET}\n`;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
output += borderBot + '\n';
|
|
46
|
+
// Render Actions
|
|
47
|
+
output += '\n';
|
|
48
|
+
this.actions.forEach((action, index) => {
|
|
49
|
+
if (index === this.activeAction) {
|
|
50
|
+
output += `${ansi_1.ANSI.REVERSE} ${action} ${ansi_1.ANSI.RESET} `;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
output += `[ ${action} ] `;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
this.renderFrame(output);
|
|
57
|
+
}
|
|
58
|
+
handleInput(char, _key) {
|
|
59
|
+
if (this.isLeft(char)) {
|
|
60
|
+
this.activeAction = (this.activeAction - 1 + this.actions.length) % this.actions.length;
|
|
61
|
+
this.render(false);
|
|
62
|
+
}
|
|
63
|
+
else if (this.isRight(char)) {
|
|
64
|
+
this.activeAction = (this.activeAction + 1) % this.actions.length;
|
|
65
|
+
this.render(false);
|
|
66
|
+
}
|
|
67
|
+
else if (char === '\r' || char === '\n') {
|
|
68
|
+
this.handleSubmit();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
handleSubmit() {
|
|
72
|
+
if (this.activeAction === 0) {
|
|
73
|
+
this.submit(this.options.original);
|
|
74
|
+
}
|
|
75
|
+
else if (this.activeAction === 1) {
|
|
76
|
+
this.submit(this.options.modified);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// Edit
|
|
80
|
+
this.cleanup(); // Stop listening to input for this prompt
|
|
81
|
+
// Prepare initial content for editor
|
|
82
|
+
const initial = `<<<<<<< ORIGINAL
|
|
83
|
+
${this.options.original}
|
|
84
|
+
=======
|
|
85
|
+
${this.options.modified}
|
|
86
|
+
>>>>>>> MODIFIED`;
|
|
87
|
+
// We delegate to EditorPrompt
|
|
88
|
+
new editor_1.EditorPrompt({
|
|
89
|
+
message: 'Resolve conflict (Edit)',
|
|
90
|
+
initial: initial,
|
|
91
|
+
extension: '.txt',
|
|
92
|
+
waitUserInput: false // Launch immediately
|
|
93
|
+
}).run().then(result => {
|
|
94
|
+
this.submit(result);
|
|
95
|
+
}).catch(_err => {
|
|
96
|
+
this.submit(initial);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.DiffPrompt = DiffPrompt;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Prompt } from '../base';
|
|
2
|
+
import { DrawOptions, MouseEvent } from '../types';
|
|
3
|
+
export declare class DrawPrompt extends Prompt<string | boolean[][], DrawOptions> {
|
|
4
|
+
private grid;
|
|
5
|
+
private cursorX;
|
|
6
|
+
private cursorY;
|
|
7
|
+
private gridWidth;
|
|
8
|
+
private gridHeight;
|
|
9
|
+
private lastMouse;
|
|
10
|
+
constructor(options: DrawOptions);
|
|
11
|
+
private getBrailleChar;
|
|
12
|
+
private getPixel;
|
|
13
|
+
private setPixel;
|
|
14
|
+
protected render(_firstRender: boolean): void;
|
|
15
|
+
protected handleInput(char: string, _key: Buffer): void;
|
|
16
|
+
protected handleMouse(event: MouseEvent): void;
|
|
17
|
+
private clearGrid;
|
|
18
|
+
private invertGrid;
|
|
19
|
+
private handleSubmit;
|
|
20
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DrawPrompt = void 0;
|
|
4
|
+
const base_1 = require("../base");
|
|
5
|
+
const theme_1 = require("../theme");
|
|
6
|
+
const ansi_1 = require("../ansi");
|
|
7
|
+
class DrawPrompt extends base_1.Prompt {
|
|
8
|
+
constructor(options) {
|
|
9
|
+
super(options);
|
|
10
|
+
this.cursorX = 0;
|
|
11
|
+
this.cursorY = 0;
|
|
12
|
+
this.lastMouse = null;
|
|
13
|
+
this.gridWidth = options.width * 2;
|
|
14
|
+
this.gridHeight = options.height * 4;
|
|
15
|
+
if (options.initial) {
|
|
16
|
+
// Deep copy to avoid mutating original if passed
|
|
17
|
+
this.grid = options.initial.map(row => [...row]);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
this.grid = [];
|
|
21
|
+
for (let y = 0; y < this.gridHeight; y++) {
|
|
22
|
+
const row = new Array(this.gridWidth).fill(false);
|
|
23
|
+
this.grid.push(row);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
getBrailleChar(x, y) {
|
|
28
|
+
const baseX = x * 2;
|
|
29
|
+
const baseY = y * 4;
|
|
30
|
+
let code = 0x2800; // Base Braille
|
|
31
|
+
// Column 0
|
|
32
|
+
if (this.getPixel(baseX, baseY))
|
|
33
|
+
code |= 0x1; // Dot 1
|
|
34
|
+
if (this.getPixel(baseX, baseY + 1))
|
|
35
|
+
code |= 0x2; // Dot 2
|
|
36
|
+
if (this.getPixel(baseX, baseY + 2))
|
|
37
|
+
code |= 0x4; // Dot 3
|
|
38
|
+
if (this.getPixel(baseX, baseY + 3))
|
|
39
|
+
code |= 0x40; // Dot 7 (Bottom-left)
|
|
40
|
+
// Column 1
|
|
41
|
+
if (this.getPixel(baseX + 1, baseY))
|
|
42
|
+
code |= 0x8; // Dot 4
|
|
43
|
+
if (this.getPixel(baseX + 1, baseY + 1))
|
|
44
|
+
code |= 0x10; // Dot 5
|
|
45
|
+
if (this.getPixel(baseX + 1, baseY + 2))
|
|
46
|
+
code |= 0x20; // Dot 6
|
|
47
|
+
if (this.getPixel(baseX + 1, baseY + 3))
|
|
48
|
+
code |= 0x80; // Dot 8 (Bottom-right)
|
|
49
|
+
return String.fromCharCode(code);
|
|
50
|
+
}
|
|
51
|
+
getPixel(x, y) {
|
|
52
|
+
if (y >= 0 && y < this.gridHeight && x >= 0 && x < this.gridWidth) {
|
|
53
|
+
return this.grid[y][x];
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
setPixel(x, y, val) {
|
|
58
|
+
if (y >= 0 && y < this.gridHeight && x >= 0 && x < this.gridWidth) {
|
|
59
|
+
this.grid[y][x] = val;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
render(_firstRender) {
|
|
63
|
+
let output = `${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET}\n`;
|
|
64
|
+
output += `${ansi_1.ANSI.FG_GRAY}┌${'─'.repeat(this.options.width + 2)}┐${ansi_1.ANSI.RESET}\n`;
|
|
65
|
+
for (let y = 0; y < this.options.height; y++) {
|
|
66
|
+
let line = '';
|
|
67
|
+
for (let x = 0; x < this.options.width; x++) {
|
|
68
|
+
const char = this.getBrailleChar(x, y);
|
|
69
|
+
// Highlight cursor position (pixel level approximation)
|
|
70
|
+
// If cursor is within this character block
|
|
71
|
+
const containsCursor = Math.floor(this.cursorX / 2) === x &&
|
|
72
|
+
Math.floor(this.cursorY / 4) === y;
|
|
73
|
+
if (containsCursor) {
|
|
74
|
+
line += ansi_1.ANSI.REVERSE + char + ansi_1.ANSI.RESET;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
line += char;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
output += `${ansi_1.ANSI.FG_GRAY}│ ${ansi_1.ANSI.RESET}${line} ${ansi_1.ANSI.FG_GRAY}│${ansi_1.ANSI.RESET}\n`;
|
|
81
|
+
}
|
|
82
|
+
output += `${ansi_1.ANSI.FG_GRAY}└${'─'.repeat(this.options.width + 2)}┘${ansi_1.ANSI.RESET}\n`;
|
|
83
|
+
output += `\n${ansi_1.ANSI.FG_GRAY}(Arrows: move, Space: toggle, Mouse: drag, 'c': clear, 'i': invert, Enter: done)${ansi_1.ANSI.RESET}`;
|
|
84
|
+
this.renderFrame(output);
|
|
85
|
+
}
|
|
86
|
+
handleInput(char, _key) {
|
|
87
|
+
if (this.isLeft(char)) {
|
|
88
|
+
this.cursorX = Math.max(0, this.cursorX - 1);
|
|
89
|
+
this.render(false);
|
|
90
|
+
}
|
|
91
|
+
else if (this.isRight(char)) {
|
|
92
|
+
this.cursorX = Math.min(this.gridWidth - 1, this.cursorX + 1);
|
|
93
|
+
this.render(false);
|
|
94
|
+
}
|
|
95
|
+
else if (this.isUp(char)) {
|
|
96
|
+
this.cursorY = Math.max(0, this.cursorY - 1);
|
|
97
|
+
this.render(false);
|
|
98
|
+
}
|
|
99
|
+
else if (this.isDown(char)) {
|
|
100
|
+
this.cursorY = Math.min(this.gridHeight - 1, this.cursorY + 1);
|
|
101
|
+
this.render(false);
|
|
102
|
+
}
|
|
103
|
+
else if (char === ' ') {
|
|
104
|
+
const current = this.getPixel(this.cursorX, this.cursorY);
|
|
105
|
+
this.setPixel(this.cursorX, this.cursorY, !current);
|
|
106
|
+
this.render(false);
|
|
107
|
+
}
|
|
108
|
+
else if (char === 'c') {
|
|
109
|
+
this.clearGrid();
|
|
110
|
+
this.render(false);
|
|
111
|
+
}
|
|
112
|
+
else if (char === 'i') {
|
|
113
|
+
this.invertGrid();
|
|
114
|
+
this.render(false);
|
|
115
|
+
}
|
|
116
|
+
else if (char === '\r' || char === '\n') {
|
|
117
|
+
this.handleSubmit();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
handleMouse(event) {
|
|
121
|
+
if (event.action === 'release') {
|
|
122
|
+
this.lastMouse = null;
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (this.lastMouse) {
|
|
126
|
+
const dx = event.x - this.lastMouse.x;
|
|
127
|
+
const dy = event.y - this.lastMouse.y;
|
|
128
|
+
// Relative movement: scale to grid density
|
|
129
|
+
// X: 1 char = 2 pixels
|
|
130
|
+
// Y: 1 char = 4 pixels
|
|
131
|
+
if (dx !== 0 || dy !== 0) {
|
|
132
|
+
this.cursorX += dx * 2;
|
|
133
|
+
this.cursorY += dy * 4;
|
|
134
|
+
// Clamp
|
|
135
|
+
this.cursorX = Math.max(0, Math.min(this.gridWidth - 1, this.cursorX));
|
|
136
|
+
this.cursorY = Math.max(0, Math.min(this.gridHeight - 1, this.cursorY));
|
|
137
|
+
// Draw if pressing (Left Button = 0)
|
|
138
|
+
if (event.action === 'press' || (event.action === 'move' && event.button === 0)) {
|
|
139
|
+
this.setPixel(this.cursorX, this.cursorY, true);
|
|
140
|
+
}
|
|
141
|
+
// Eraser (Right Button = 2)
|
|
142
|
+
if ((event.action === 'press' || event.action === 'move') && event.button === 2) {
|
|
143
|
+
this.setPixel(this.cursorX, this.cursorY, false);
|
|
144
|
+
}
|
|
145
|
+
this.render(false);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
if (event.action === 'press' && event.button === 0) {
|
|
150
|
+
this.setPixel(this.cursorX, this.cursorY, true);
|
|
151
|
+
this.render(false);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
this.lastMouse = { x: event.x, y: event.y };
|
|
155
|
+
}
|
|
156
|
+
clearGrid() {
|
|
157
|
+
for (let y = 0; y < this.gridHeight; y++) {
|
|
158
|
+
for (let x = 0; x < this.gridWidth; x++) {
|
|
159
|
+
this.grid[y][x] = false;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
invertGrid() {
|
|
164
|
+
for (let y = 0; y < this.gridHeight; y++) {
|
|
165
|
+
for (let x = 0; x < this.gridWidth; x++) {
|
|
166
|
+
this.grid[y][x] = !this.grid[y][x];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
handleSubmit() {
|
|
171
|
+
if (this.options.exportType === 'text') {
|
|
172
|
+
// Render to string
|
|
173
|
+
let result = '';
|
|
174
|
+
for (let y = 0; y < this.options.height; y++) {
|
|
175
|
+
for (let x = 0; x < this.options.width; x++) {
|
|
176
|
+
result += this.getBrailleChar(x, y);
|
|
177
|
+
}
|
|
178
|
+
result += '\n';
|
|
179
|
+
}
|
|
180
|
+
this.submit(result.trim());
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
// Default: return matrix
|
|
184
|
+
this.submit(this.grid);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
exports.DrawPrompt = DrawPrompt;
|
package/dist/prompts/editor.js
CHANGED
|
@@ -180,10 +180,6 @@ class EditorPrompt extends base_1.Prompt {
|
|
|
180
180
|
}
|
|
181
181
|
// Success
|
|
182
182
|
this.status = 'done';
|
|
183
|
-
// Trim trailing newline which editors often add
|
|
184
|
-
// We only trim the *last* newline added by the editor if it wasn't there?
|
|
185
|
-
// Usually editors ensure a final newline.
|
|
186
|
-
// If the user entered "abc", vim saves "abc\n". We probably want "abc".
|
|
187
183
|
if (content.endsWith('\n')) {
|
|
188
184
|
content = content.slice(0, -1);
|
|
189
185
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Prompt } from '../base';
|
|
2
|
+
import { EmojiOptions, MouseEvent } from '../types';
|
|
3
|
+
export declare class EmojiPrompt extends Prompt<string, EmojiOptions> {
|
|
4
|
+
private search;
|
|
5
|
+
private cursor;
|
|
6
|
+
private filtered;
|
|
7
|
+
private sortedEmojis;
|
|
8
|
+
private cols;
|
|
9
|
+
private scrollTop;
|
|
10
|
+
private pageSize;
|
|
11
|
+
constructor(options: EmojiOptions);
|
|
12
|
+
private calculateLayout;
|
|
13
|
+
private updateFilter;
|
|
14
|
+
protected render(_firstRender: boolean): void;
|
|
15
|
+
protected handleInput(char: string): void;
|
|
16
|
+
protected handleMouse(event: MouseEvent): void;
|
|
17
|
+
private adjustScroll;
|
|
18
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EmojiPrompt = void 0;
|
|
4
|
+
const ansi_1 = require("../ansi");
|
|
5
|
+
const base_1 = require("../base");
|
|
6
|
+
const theme_1 = require("../theme");
|
|
7
|
+
const utils_1 = require("../utils");
|
|
8
|
+
class EmojiPrompt extends base_1.Prompt {
|
|
9
|
+
constructor(options) {
|
|
10
|
+
super(options);
|
|
11
|
+
this.search = '';
|
|
12
|
+
this.cursor = 0; // Index in the filtered list
|
|
13
|
+
this.filtered = [];
|
|
14
|
+
this.sortedEmojis = [];
|
|
15
|
+
this.cols = 0;
|
|
16
|
+
this.scrollTop = 0;
|
|
17
|
+
this.pageSize = 8; // Number of rows to display
|
|
18
|
+
// Sort emojis by recent
|
|
19
|
+
this.sortedEmojis = [...options.emojis];
|
|
20
|
+
if (options.recent && options.recent.length > 0) {
|
|
21
|
+
const recentSet = new Set(options.recent);
|
|
22
|
+
this.sortedEmojis.sort((a, b) => {
|
|
23
|
+
const aRecent = recentSet.has(a.name);
|
|
24
|
+
const bRecent = recentSet.has(b.name);
|
|
25
|
+
if (aRecent && !bRecent)
|
|
26
|
+
return -1;
|
|
27
|
+
if (!aRecent && bRecent)
|
|
28
|
+
return 1;
|
|
29
|
+
return 0;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
this.checkWindowsAttention();
|
|
33
|
+
// Initial filter
|
|
34
|
+
this.filtered = this.sortedEmojis;
|
|
35
|
+
// Calculate layout
|
|
36
|
+
this.calculateLayout();
|
|
37
|
+
}
|
|
38
|
+
calculateLayout() {
|
|
39
|
+
if (this.options.cols) {
|
|
40
|
+
this.cols = this.options.cols;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// Auto-detect based on terminal width
|
|
44
|
+
// Assume each emoji cell takes ~4 chars (2 char emoji + 2 padding)
|
|
45
|
+
const termWidth = process.stdout.columns || 80;
|
|
46
|
+
this.cols = Math.floor((termWidth - 4) / 4); // -4 for margin
|
|
47
|
+
if (this.cols < 1)
|
|
48
|
+
this.cols = 1;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
updateFilter() {
|
|
52
|
+
if (!this.search) {
|
|
53
|
+
this.filtered = this.sortedEmojis;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
const lowerSearch = this.search.toLowerCase();
|
|
57
|
+
this.filtered = this.sortedEmojis.filter(e => e.name.toLowerCase().includes(lowerSearch) ||
|
|
58
|
+
(e.description && e.description.toLowerCase().includes(lowerSearch)) ||
|
|
59
|
+
e.char === this.search // Allow searching by exact char
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
this.cursor = 0;
|
|
63
|
+
this.scrollTop = 0;
|
|
64
|
+
}
|
|
65
|
+
render(_firstRender) {
|
|
66
|
+
// Prepare header (Search bar)
|
|
67
|
+
const icon = `${theme_1.theme.success}?`;
|
|
68
|
+
const title = `${ansi_1.ANSI.BOLD}${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET}`;
|
|
69
|
+
const searchDisplay = this.search ? `${theme_1.theme.main}${this.search}${ansi_1.ANSI.RESET}` : `${theme_1.theme.muted}Type to search...${ansi_1.ANSI.RESET}`;
|
|
70
|
+
let output = `${icon} ${title} ${searchDisplay}\n`;
|
|
71
|
+
// Render Grid
|
|
72
|
+
if (this.filtered.length === 0) {
|
|
73
|
+
output += `\n${theme_1.theme.error}No results found.${ansi_1.ANSI.RESET}\n`;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
const totalRows = Math.ceil(this.filtered.length / this.cols);
|
|
77
|
+
const startRow = this.scrollTop;
|
|
78
|
+
const endRow = Math.min(totalRows, startRow + this.pageSize);
|
|
79
|
+
for (let r = startRow; r < endRow; r++) {
|
|
80
|
+
let rowStr = ' '; // Left margin
|
|
81
|
+
for (let c = 0; c < this.cols; c++) {
|
|
82
|
+
const idx = r * this.cols + c;
|
|
83
|
+
if (idx >= this.filtered.length)
|
|
84
|
+
break;
|
|
85
|
+
const item = this.filtered[idx];
|
|
86
|
+
const isSelected = idx === this.cursor;
|
|
87
|
+
// Render Emoji
|
|
88
|
+
// Align center in 4 chars
|
|
89
|
+
// Emoji width is typically 2.
|
|
90
|
+
const emoji = item.char;
|
|
91
|
+
const width = (0, utils_1.stringWidth)(emoji);
|
|
92
|
+
const padding = 4 - width;
|
|
93
|
+
const leftPad = Math.floor(padding / 2);
|
|
94
|
+
const rightPad = padding - leftPad;
|
|
95
|
+
let cell = `${' '.repeat(leftPad)}${emoji}${' '.repeat(rightPad)}`;
|
|
96
|
+
if (isSelected) {
|
|
97
|
+
cell = `${ansi_1.ANSI.REVERSE}${cell}${ansi_1.ANSI.RESET}`;
|
|
98
|
+
}
|
|
99
|
+
rowStr += cell;
|
|
100
|
+
}
|
|
101
|
+
output += rowStr + '\n';
|
|
102
|
+
}
|
|
103
|
+
// Footer (Preview of selected)
|
|
104
|
+
if (this.filtered.length > 0) {
|
|
105
|
+
const selectedItem = this.filtered[this.cursor];
|
|
106
|
+
output += `\n${ansi_1.ANSI.BOLD}${selectedItem.char} ${selectedItem.name}${ansi_1.ANSI.RESET}`;
|
|
107
|
+
if (selectedItem.description) {
|
|
108
|
+
output += ` - ${theme_1.theme.muted}${selectedItem.description}${ansi_1.ANSI.RESET}`;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
output += '\n'; // Spacer
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Navigation hints
|
|
116
|
+
// output += `\n${theme.muted}Arrows to navigate, Enter to select${ANSI.RESET}`;
|
|
117
|
+
this.renderFrame(output);
|
|
118
|
+
}
|
|
119
|
+
handleInput(char) {
|
|
120
|
+
// Navigation
|
|
121
|
+
if (this.isUp(char)) {
|
|
122
|
+
if (this.filtered.length === 0)
|
|
123
|
+
return;
|
|
124
|
+
const newCursor = this.cursor - this.cols;
|
|
125
|
+
if (newCursor >= 0) {
|
|
126
|
+
this.cursor = newCursor;
|
|
127
|
+
}
|
|
128
|
+
this.adjustScroll();
|
|
129
|
+
this.render(false);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (this.isDown(char)) {
|
|
133
|
+
if (this.filtered.length === 0)
|
|
134
|
+
return;
|
|
135
|
+
const newCursor = this.cursor + this.cols;
|
|
136
|
+
if (newCursor < this.filtered.length) {
|
|
137
|
+
this.cursor = newCursor;
|
|
138
|
+
}
|
|
139
|
+
this.adjustScroll();
|
|
140
|
+
this.render(false);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (this.isLeft(char)) {
|
|
144
|
+
if (this.filtered.length === 0)
|
|
145
|
+
return;
|
|
146
|
+
if (this.cursor > 0) {
|
|
147
|
+
this.cursor--;
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
// Wrap to end?
|
|
151
|
+
this.cursor = this.filtered.length - 1;
|
|
152
|
+
}
|
|
153
|
+
this.adjustScroll();
|
|
154
|
+
this.render(false);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (this.isRight(char)) {
|
|
158
|
+
if (this.filtered.length === 0)
|
|
159
|
+
return;
|
|
160
|
+
if (this.cursor < this.filtered.length - 1) {
|
|
161
|
+
this.cursor++;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
// Wrap to start?
|
|
165
|
+
this.cursor = 0;
|
|
166
|
+
}
|
|
167
|
+
this.adjustScroll();
|
|
168
|
+
this.render(false);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
// Enter
|
|
172
|
+
if (char === '\r' || char === '\n') {
|
|
173
|
+
if (this.filtered.length > 0) {
|
|
174
|
+
this.submit(this.filtered[this.cursor].char);
|
|
175
|
+
}
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
// Backspace
|
|
179
|
+
if (char === '\u0008' || char === '\x7f') {
|
|
180
|
+
if (this.search.length > 0) {
|
|
181
|
+
this.search = this.search.slice(0, -1);
|
|
182
|
+
this.updateFilter();
|
|
183
|
+
this.render(false);
|
|
184
|
+
}
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
// Typing
|
|
188
|
+
if (!/^[\x00-\x1F]/.test(char) && !char.startsWith('\x1b')) {
|
|
189
|
+
this.search += char;
|
|
190
|
+
this.updateFilter();
|
|
191
|
+
this.render(false);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
handleMouse(event) {
|
|
195
|
+
if (event.action === 'scroll' && this.filtered.length > 0) {
|
|
196
|
+
if (event.scroll === 'up') {
|
|
197
|
+
// Left / Previous
|
|
198
|
+
if (this.cursor > 0) {
|
|
199
|
+
this.cursor--;
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
this.cursor = this.filtered.length - 1;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
// Right / Next
|
|
207
|
+
if (this.cursor < this.filtered.length - 1) {
|
|
208
|
+
this.cursor++;
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
this.cursor = 0;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
this.adjustScroll();
|
|
215
|
+
this.render(false);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
adjustScroll() {
|
|
219
|
+
const cursorRow = Math.floor(this.cursor / this.cols);
|
|
220
|
+
if (cursorRow < this.scrollTop) {
|
|
221
|
+
this.scrollTop = cursorRow;
|
|
222
|
+
}
|
|
223
|
+
else if (cursorRow >= this.scrollTop + this.pageSize) {
|
|
224
|
+
this.scrollTop = cursorRow - this.pageSize + 1;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
exports.EmojiPrompt = EmojiPrompt;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Prompt } from '../base';
|
|
2
|
+
import { ExecOptions } from '../types';
|
|
3
|
+
export declare class ExecPrompt extends Prompt<void, ExecOptions> {
|
|
4
|
+
private child?;
|
|
5
|
+
private status;
|
|
6
|
+
private timer?;
|
|
7
|
+
constructor(options: ExecOptions);
|
|
8
|
+
run(): Promise<void>;
|
|
9
|
+
private killChild;
|
|
10
|
+
protected cleanup(): void;
|
|
11
|
+
protected render(_firstRender: boolean): void;
|
|
12
|
+
protected handleInput(_char: string, _key: Buffer): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExecPrompt = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const base_1 = require("../base");
|
|
6
|
+
const theme_1 = require("../theme");
|
|
7
|
+
const symbols_1 = require("../symbols");
|
|
8
|
+
const ansi_1 = require("../ansi");
|
|
9
|
+
class ExecPrompt extends base_1.Prompt {
|
|
10
|
+
constructor(options) {
|
|
11
|
+
super(options);
|
|
12
|
+
this.status = 'running';
|
|
13
|
+
this.warnExperimental();
|
|
14
|
+
}
|
|
15
|
+
run() {
|
|
16
|
+
this.child = (0, child_process_1.spawn)(this.options.command, [], {
|
|
17
|
+
cwd: this.options.cwd || process.cwd(),
|
|
18
|
+
shell: true,
|
|
19
|
+
stdio: this.options.streamOutput ? 'inherit' : 'ignore'
|
|
20
|
+
});
|
|
21
|
+
if (this.options.timeout && this.options.timeout > 0) {
|
|
22
|
+
this.timer = setTimeout(() => {
|
|
23
|
+
if (this.status !== 'running')
|
|
24
|
+
return;
|
|
25
|
+
this.status = 'error';
|
|
26
|
+
this.render(false);
|
|
27
|
+
this.cancel(new Error(`Timeout after ${this.options.timeout}ms`));
|
|
28
|
+
}, this.options.timeout);
|
|
29
|
+
}
|
|
30
|
+
this.child.on('exit', (code) => {
|
|
31
|
+
if (this.status !== 'running')
|
|
32
|
+
return;
|
|
33
|
+
if (code === 0) {
|
|
34
|
+
this.status = 'done';
|
|
35
|
+
this.render(false);
|
|
36
|
+
this.submit();
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
this.status = 'error';
|
|
40
|
+
this.render(false);
|
|
41
|
+
this.cancel(new Error(`Command failed with exit code ${code}`));
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
this.child.on('error', (err) => {
|
|
45
|
+
if (this.status !== 'running')
|
|
46
|
+
return;
|
|
47
|
+
this.status = 'error';
|
|
48
|
+
this.render(false);
|
|
49
|
+
this.cancel(err);
|
|
50
|
+
});
|
|
51
|
+
return super.run();
|
|
52
|
+
}
|
|
53
|
+
killChild() {
|
|
54
|
+
if (this.child && !this.child.killed) {
|
|
55
|
+
this.child.kill();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
cleanup() {
|
|
59
|
+
this.status = 'done';
|
|
60
|
+
if (this.timer)
|
|
61
|
+
clearTimeout(this.timer);
|
|
62
|
+
this.killChild();
|
|
63
|
+
super.cleanup();
|
|
64
|
+
}
|
|
65
|
+
render(_firstRender) {
|
|
66
|
+
let symbol = '';
|
|
67
|
+
if (this.status === 'running') {
|
|
68
|
+
symbol = theme_1.theme.muted + '...' + ansi_1.ANSI.RESET;
|
|
69
|
+
}
|
|
70
|
+
else if (this.status === 'done') {
|
|
71
|
+
symbol = theme_1.theme.success + symbols_1.symbols.tick + ansi_1.ANSI.RESET;
|
|
72
|
+
}
|
|
73
|
+
else if (this.status === 'error') {
|
|
74
|
+
symbol = theme_1.theme.error + symbols_1.symbols.cross + ansi_1.ANSI.RESET;
|
|
75
|
+
}
|
|
76
|
+
const output = `${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET} ${symbol}`;
|
|
77
|
+
this.renderFrame(output);
|
|
78
|
+
}
|
|
79
|
+
handleInput(_char, _key) {
|
|
80
|
+
// Ignore input
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
exports.ExecPrompt = ExecPrompt;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SelectPrompt } from './select';
|
|
2
|
+
import { FuzzySelectOptions } from '../types';
|
|
3
|
+
export declare class FuzzySelectPrompt<V> extends SelectPrompt<V, FuzzySelectOptions<V>> {
|
|
4
|
+
private filteredResults;
|
|
5
|
+
private debounceTimer;
|
|
6
|
+
constructor(options: FuzzySelectOptions<V>);
|
|
7
|
+
protected getFilteredChoices(): any[];
|
|
8
|
+
protected handleInput(char: string): void;
|
|
9
|
+
private performSearch;
|
|
10
|
+
private highlight;
|
|
11
|
+
protected render(_firstRender: boolean): void;
|
|
12
|
+
}
|