mepcli 0.5.0 → 0.6.0

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.
Files changed (76) hide show
  1. package/README.md +182 -6
  2. package/dist/ansi.d.ts +1 -0
  3. package/dist/ansi.js +1 -0
  4. package/dist/base.d.ts +1 -1
  5. package/dist/base.js +1 -10
  6. package/dist/core.d.ts +26 -1
  7. package/dist/core.js +72 -0
  8. package/dist/highlight.d.ts +1 -0
  9. package/dist/highlight.js +40 -0
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.js +1 -1
  12. package/dist/input.js +26 -14
  13. package/dist/prompts/autocomplete.d.ts +1 -1
  14. package/dist/prompts/autocomplete.js +2 -7
  15. package/dist/prompts/calendar.d.ts +20 -0
  16. package/dist/prompts/calendar.js +329 -0
  17. package/dist/prompts/checkbox.d.ts +1 -1
  18. package/dist/prompts/checkbox.js +38 -8
  19. package/dist/prompts/code.d.ts +17 -0
  20. package/dist/prompts/code.js +210 -0
  21. package/dist/prompts/color.d.ts +14 -0
  22. package/dist/prompts/color.js +147 -0
  23. package/dist/prompts/confirm.d.ts +1 -1
  24. package/dist/prompts/confirm.js +1 -1
  25. package/dist/prompts/cron.d.ts +13 -0
  26. package/dist/prompts/cron.js +176 -0
  27. package/dist/prompts/date.d.ts +1 -1
  28. package/dist/prompts/date.js +15 -5
  29. package/dist/prompts/editor.d.ts +14 -0
  30. package/dist/prompts/editor.js +207 -0
  31. package/dist/prompts/file.d.ts +7 -0
  32. package/dist/prompts/file.js +56 -60
  33. package/dist/prompts/form.d.ts +17 -0
  34. package/dist/prompts/form.js +225 -0
  35. package/dist/prompts/grid.d.ts +14 -0
  36. package/dist/prompts/grid.js +178 -0
  37. package/dist/prompts/keypress.d.ts +7 -0
  38. package/dist/prompts/keypress.js +57 -0
  39. package/dist/prompts/list.d.ts +1 -1
  40. package/dist/prompts/list.js +42 -22
  41. package/dist/prompts/multi-select.d.ts +1 -1
  42. package/dist/prompts/multi-select.js +39 -4
  43. package/dist/prompts/number.d.ts +1 -1
  44. package/dist/prompts/number.js +2 -2
  45. package/dist/prompts/range.d.ts +9 -0
  46. package/dist/prompts/range.js +140 -0
  47. package/dist/prompts/rating.d.ts +1 -1
  48. package/dist/prompts/rating.js +1 -1
  49. package/dist/prompts/select.d.ts +1 -1
  50. package/dist/prompts/select.js +1 -1
  51. package/dist/prompts/slider.d.ts +1 -1
  52. package/dist/prompts/slider.js +1 -1
  53. package/dist/prompts/snippet.d.ts +18 -0
  54. package/dist/prompts/snippet.js +203 -0
  55. package/dist/prompts/sort.d.ts +1 -1
  56. package/dist/prompts/sort.js +1 -4
  57. package/dist/prompts/spam.d.ts +17 -0
  58. package/dist/prompts/spam.js +62 -0
  59. package/dist/prompts/table.d.ts +1 -1
  60. package/dist/prompts/table.js +1 -1
  61. package/dist/prompts/text.d.ts +1 -0
  62. package/dist/prompts/text.js +14 -32
  63. package/dist/prompts/toggle.d.ts +1 -1
  64. package/dist/prompts/toggle.js +1 -1
  65. package/dist/prompts/transfer.d.ts +18 -0
  66. package/dist/prompts/transfer.js +203 -0
  67. package/dist/prompts/tree-select.d.ts +32 -0
  68. package/dist/prompts/tree-select.js +277 -0
  69. package/dist/prompts/tree.d.ts +20 -0
  70. package/dist/prompts/tree.js +231 -0
  71. package/dist/prompts/wait.d.ts +18 -0
  72. package/dist/prompts/wait.js +62 -0
  73. package/dist/types.d.ts +105 -0
  74. package/dist/utils.js +6 -2
  75. package/example.ts +213 -27
  76. package/package.json +14 -4
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TreePrompt = void 0;
4
+ const ansi_1 = require("../ansi");
5
+ const base_1 = require("../base");
6
+ const theme_1 = require("../theme");
7
+ const symbols_1 = require("../symbols");
8
+ class TreePrompt extends base_1.Prompt {
9
+ constructor(options) {
10
+ super(options);
11
+ this.cursor = 0;
12
+ this.expandedNodes = new Set();
13
+ this.flatList = [];
14
+ this.scrollTop = 0;
15
+ this.pageSize = 15;
16
+ // Icons
17
+ this.ICON_CLOSED = symbols_1.symbols.pointer === '>' ? '+' : '▸';
18
+ this.ICON_OPEN = symbols_1.symbols.pointer === '>' ? '-' : '▾';
19
+ this.initializeExpanded(this.options.data);
20
+ if (this.options.initial !== undefined) {
21
+ this.expandPathTo(this.options.initial);
22
+ }
23
+ this.recalculateFlatList();
24
+ if (this.options.initial !== undefined) {
25
+ const index = this.flatList.findIndex(item => item.node.value === this.options.initial);
26
+ if (index !== -1) {
27
+ this.cursor = index;
28
+ }
29
+ }
30
+ }
31
+ expandPathTo(value) {
32
+ const find = (nodes) => {
33
+ for (const node of nodes) {
34
+ if (node.value === value)
35
+ return true;
36
+ if (node.children) {
37
+ if (find(node.children)) {
38
+ this.expandedNodes.add(node);
39
+ return true;
40
+ }
41
+ }
42
+ }
43
+ return false;
44
+ };
45
+ find(this.options.data);
46
+ }
47
+ initializeExpanded(nodes) {
48
+ for (const node of nodes) {
49
+ if (node.expanded) {
50
+ this.expandedNodes.add(node);
51
+ }
52
+ if (node.children) {
53
+ this.initializeExpanded(node.children);
54
+ }
55
+ }
56
+ }
57
+ recalculateFlatList() {
58
+ this.flatList = [];
59
+ this.traverse(this.options.data, 0, null);
60
+ if (this.cursor >= this.flatList.length) {
61
+ this.cursor = Math.max(0, this.flatList.length - 1);
62
+ }
63
+ }
64
+ traverse(nodes, depth, parent) {
65
+ for (const node of nodes) {
66
+ this.flatList.push({
67
+ node,
68
+ depth,
69
+ parent
70
+ });
71
+ if (node.children && node.children.length > 0 && this.expandedNodes.has(node)) {
72
+ this.traverse(node.children, depth + 1, node);
73
+ }
74
+ }
75
+ }
76
+ toggleRecursive(node, expand) {
77
+ if (expand)
78
+ this.expandedNodes.add(node);
79
+ else
80
+ this.expandedNodes.delete(node);
81
+ if (node.children) {
82
+ node.children.forEach(child => this.toggleRecursive(child, expand));
83
+ }
84
+ }
85
+ render(_firstRender) {
86
+ 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`;
87
+ if (this.flatList.length === 0) {
88
+ output += ` ${theme_1.theme.muted}No data${ansi_1.ANSI.RESET}`;
89
+ this.renderFrame(output);
90
+ return;
91
+ }
92
+ if (this.cursor < this.scrollTop) {
93
+ this.scrollTop = this.cursor;
94
+ }
95
+ else if (this.cursor >= this.scrollTop + this.pageSize) {
96
+ this.scrollTop = this.cursor - this.pageSize + 1;
97
+ }
98
+ const visible = this.flatList.slice(this.scrollTop, this.scrollTop + this.pageSize);
99
+ visible.forEach((item, index) => {
100
+ const actualIndex = this.scrollTop + index;
101
+ const isSelected = actualIndex === this.cursor;
102
+ const indentSize = this.options.indent || 2;
103
+ const indentation = ' '.repeat(item.depth * indentSize);
104
+ let linePrefix = '';
105
+ if (isSelected) {
106
+ linePrefix = `${theme_1.theme.main}${symbols_1.symbols.pointer} `;
107
+ }
108
+ else {
109
+ linePrefix = ' ';
110
+ }
111
+ let icon = ' ';
112
+ const hasChildren = item.node.children && item.node.children.length > 0;
113
+ if (hasChildren) {
114
+ if (this.expandedNodes.has(item.node)) {
115
+ icon = `${this.ICON_OPEN} `;
116
+ }
117
+ else {
118
+ icon = `${this.ICON_CLOSED} `;
119
+ }
120
+ }
121
+ let title = item.node.title;
122
+ if (item.node.disabled) {
123
+ title = `${theme_1.theme.muted}${title} (disabled)${ansi_1.ANSI.RESET}`;
124
+ }
125
+ let line = `${indentation}${icon}${title}`;
126
+ if (isSelected) {
127
+ line = `${theme_1.theme.main}${line}${ansi_1.ANSI.RESET}`;
128
+ }
129
+ output += linePrefix + line;
130
+ if (index < visible.length - 1)
131
+ output += '\n';
132
+ });
133
+ output += `\n${theme_1.theme.muted}(Arrows: Nav, e: Expand All, c: Collapse All)${ansi_1.ANSI.RESET}`;
134
+ this.renderFrame(output);
135
+ }
136
+ handleInput(char, _key) {
137
+ if (this.flatList.length === 0)
138
+ return;
139
+ if (this.isUp(char)) {
140
+ this.cursor = (this.cursor - 1 + this.flatList.length) % this.flatList.length;
141
+ this.render(false);
142
+ return;
143
+ }
144
+ if (this.isDown(char)) {
145
+ this.cursor = (this.cursor + 1) % this.flatList.length;
146
+ this.render(false);
147
+ return;
148
+ }
149
+ const currentItem = this.flatList[this.cursor];
150
+ const node = currentItem.node;
151
+ const hasChildren = node.children && node.children.length > 0;
152
+ // Recursive Expand (e)
153
+ if (char === 'e' && hasChildren) {
154
+ this.toggleRecursive(node, true);
155
+ this.recalculateFlatList();
156
+ this.render(false);
157
+ return;
158
+ }
159
+ // Recursive Collapse (c)
160
+ if (char === 'c' && hasChildren) {
161
+ this.toggleRecursive(node, false);
162
+ this.recalculateFlatList();
163
+ this.render(false);
164
+ return;
165
+ }
166
+ if (this.isRight(char)) {
167
+ if (hasChildren) {
168
+ if (!this.expandedNodes.has(node)) {
169
+ this.expandedNodes.add(node);
170
+ this.recalculateFlatList();
171
+ }
172
+ else {
173
+ if (this.cursor + 1 < this.flatList.length) {
174
+ this.cursor++;
175
+ }
176
+ }
177
+ this.render(false);
178
+ return;
179
+ }
180
+ }
181
+ if (this.isLeft(char)) {
182
+ if (hasChildren && this.expandedNodes.has(node)) {
183
+ this.expandedNodes.delete(node);
184
+ this.recalculateFlatList();
185
+ this.render(false);
186
+ return;
187
+ }
188
+ else {
189
+ if (currentItem.parent) {
190
+ const parentIndex = this.flatList.findIndex(x => x.node === currentItem.parent);
191
+ if (parentIndex !== -1) {
192
+ this.cursor = parentIndex;
193
+ this.render(false);
194
+ return;
195
+ }
196
+ }
197
+ }
198
+ }
199
+ if (char === ' ') {
200
+ if (hasChildren) {
201
+ if (this.expandedNodes.has(node)) {
202
+ this.expandedNodes.delete(node);
203
+ }
204
+ else {
205
+ this.expandedNodes.add(node);
206
+ }
207
+ this.recalculateFlatList();
208
+ this.render(false);
209
+ }
210
+ return;
211
+ }
212
+ if (char === '\r' || char === '\n') {
213
+ if (!node.disabled) {
214
+ this.submit(node.value);
215
+ }
216
+ }
217
+ }
218
+ handleMouse(event) {
219
+ if (event.action === 'scroll') {
220
+ if (event.scroll === 'up') {
221
+ this.cursor = (this.cursor - 1 + this.flatList.length) % this.flatList.length;
222
+ this.render(false);
223
+ }
224
+ else if (event.scroll === 'down') {
225
+ this.cursor = (this.cursor + 1) % this.flatList.length;
226
+ this.render(false);
227
+ }
228
+ }
229
+ }
230
+ }
231
+ exports.TreePrompt = TreePrompt;
@@ -0,0 +1,18 @@
1
+ import { Prompt } from '../base';
2
+ import { BaseOptions } from '../types';
3
+ interface WaitOptions extends BaseOptions {
4
+ seconds: number;
5
+ autoSubmit?: boolean;
6
+ }
7
+ export declare class WaitPrompt extends Prompt<void, WaitOptions> {
8
+ private remaining;
9
+ private timer?;
10
+ private isDone;
11
+ constructor(options: WaitOptions);
12
+ run(): Promise<void>;
13
+ private stopTimer;
14
+ protected cleanup(): void;
15
+ protected render(_firstRender: boolean): void;
16
+ protected handleInput(char: string): void;
17
+ }
18
+ export {};
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WaitPrompt = void 0;
4
+ // src/prompts/wait.ts
5
+ const ansi_1 = require("../ansi");
6
+ const base_1 = require("../base");
7
+ const theme_1 = require("../theme");
8
+ class WaitPrompt extends base_1.Prompt {
9
+ constructor(options) {
10
+ super(options);
11
+ this.isDone = false;
12
+ this.remaining = options.seconds;
13
+ }
14
+ run() {
15
+ // Start the countdown immediately upon running
16
+ this.timer = setInterval(() => {
17
+ this.remaining--;
18
+ if (this.remaining <= 0) {
19
+ this.isDone = true;
20
+ this.stopTimer();
21
+ if (this.options.autoSubmit) {
22
+ this.submit();
23
+ }
24
+ else {
25
+ this.render(false);
26
+ }
27
+ }
28
+ else {
29
+ this.render(false);
30
+ }
31
+ }, 1000);
32
+ return super.run();
33
+ }
34
+ stopTimer() {
35
+ if (this.timer) {
36
+ clearInterval(this.timer);
37
+ this.timer = undefined;
38
+ }
39
+ }
40
+ cleanup() {
41
+ this.stopTimer();
42
+ super.cleanup();
43
+ }
44
+ render(_firstRender) {
45
+ let output = `${theme_1.theme.title}${this.options.message}${ansi_1.ANSI.RESET} `;
46
+ if (this.isDone) {
47
+ output += `${theme_1.theme.success}Done! Press Enter to continue.${ansi_1.ANSI.RESET}`;
48
+ }
49
+ else {
50
+ // Fun countdown visualization
51
+ output += `${theme_1.theme.muted}Please wait... ${this.remaining}s${ansi_1.ANSI.RESET}`;
52
+ }
53
+ this.renderFrame(output);
54
+ }
55
+ handleInput(char) {
56
+ if (this.isDone && (char === '\r' || char === '\n')) {
57
+ this.submit();
58
+ }
59
+ // Else: Ignore all input while waiting
60
+ }
61
+ }
62
+ exports.WaitPrompt = WaitPrompt;
package/dist/types.d.ts CHANGED
@@ -19,6 +19,9 @@ export interface MouseEvent {
19
19
  button: number;
20
20
  action: 'press' | 'release' | 'move' | 'scroll';
21
21
  scroll?: 'up' | 'down';
22
+ shift?: boolean;
23
+ ctrl?: boolean;
24
+ meta?: boolean;
22
25
  }
23
26
  export interface TextOptions extends BaseOptions {
24
27
  placeholder?: string;
@@ -26,6 +29,7 @@ export interface TextOptions extends BaseOptions {
26
29
  validate?: (value: string) => string | boolean | Promise<string | boolean>;
27
30
  isPassword?: boolean;
28
31
  multiline?: boolean;
32
+ mask?: string;
29
33
  }
30
34
  export interface Separator {
31
35
  separator: true;
@@ -39,6 +43,14 @@ export interface SelectChoice<V> {
39
43
  export interface SelectOptions<V> extends BaseOptions {
40
44
  choices: (SelectChoice<V> | Separator)[];
41
45
  }
46
+ export interface TransferOptions<V> extends BaseOptions {
47
+ source: (string | SelectChoice<V>)[];
48
+ target?: (string | SelectChoice<V>)[];
49
+ }
50
+ export interface CronOptions extends BaseOptions {
51
+ initial?: string;
52
+ placeholder?: string;
53
+ }
42
54
  export interface CheckboxChoice<V> extends SelectChoice<V> {
43
55
  selected?: boolean;
44
56
  }
@@ -74,6 +86,13 @@ export interface SliderOptions extends BaseOptions {
74
86
  step?: number;
75
87
  unit?: string;
76
88
  }
89
+ export interface RangeOptions extends BaseOptions {
90
+ min: number;
91
+ max: number;
92
+ initial?: [number, number];
93
+ step?: number;
94
+ unit?: string;
95
+ }
77
96
  export interface RatingOptions extends BaseOptions {
78
97
  min?: number;
79
98
  max?: number;
@@ -100,6 +119,11 @@ export interface AutocompleteOptions<V> extends BaseOptions {
100
119
  export interface SortOptions extends BaseOptions {
101
120
  items: string[];
102
121
  }
122
+ export interface EditorOptions extends BaseOptions {
123
+ initial?: string;
124
+ extension?: string;
125
+ waitUserInput?: boolean;
126
+ }
103
127
  export interface TableRow<V> {
104
128
  value: V;
105
129
  row: string[];
@@ -109,3 +133,84 @@ export interface TableOptions<V> extends BaseOptions {
109
133
  data: TableRow<V>[];
110
134
  rows?: number;
111
135
  }
136
+ export interface TreeNode<V> {
137
+ title: string;
138
+ value: V;
139
+ children?: TreeNode<V>[];
140
+ expanded?: boolean;
141
+ disabled?: boolean;
142
+ selected?: boolean | 'indeterminate';
143
+ }
144
+ export interface TreeOptions<V> extends BaseOptions {
145
+ data: TreeNode<V>[];
146
+ initial?: V;
147
+ indent?: number;
148
+ }
149
+ export interface KeypressOptions extends BaseOptions {
150
+ keys?: string[];
151
+ showInvisible?: boolean;
152
+ }
153
+ export interface FormField {
154
+ name: string;
155
+ message: string;
156
+ initial?: string;
157
+ validate?: (value: string) => string | boolean | Promise<string | boolean>;
158
+ }
159
+ export interface FormOptions extends BaseOptions {
160
+ fields: FormField[];
161
+ }
162
+ export interface SnippetOptions extends BaseOptions {
163
+ template: string;
164
+ values?: Record<string, string>;
165
+ fields?: Record<string, {
166
+ message?: string;
167
+ validate?: (value: string) => string | boolean;
168
+ }>;
169
+ }
170
+ export interface SpamOptions extends BaseOptions {
171
+ threshold: number;
172
+ spamKey?: string;
173
+ decay?: boolean;
174
+ }
175
+ export interface WaitOptions extends BaseOptions {
176
+ seconds: number;
177
+ autoSubmit?: boolean;
178
+ }
179
+ export interface CodeOptions extends BaseOptions {
180
+ template: string;
181
+ language?: 'json' | 'yaml';
182
+ /**
183
+ * Enable syntax highlighting (Experimental).
184
+ * @default true
185
+ */
186
+ highlight?: boolean;
187
+ }
188
+ export interface TreeSelectNode<V> {
189
+ title: string;
190
+ value: V;
191
+ children?: TreeSelectNode<V>[];
192
+ expanded?: boolean;
193
+ disabled?: boolean;
194
+ selected?: boolean | 'indeterminate';
195
+ }
196
+ export interface TreeSelectOptions<V> extends BaseOptions {
197
+ data: TreeSelectNode<V>[];
198
+ initial?: V[];
199
+ indent?: number;
200
+ }
201
+ export interface ColorOptions extends BaseOptions {
202
+ initial?: string;
203
+ format?: 'hex' | 'rgb' | 'hsl';
204
+ }
205
+ export interface GridOptions extends BaseOptions {
206
+ rows: string[];
207
+ columns: string[];
208
+ initial?: boolean[][];
209
+ }
210
+ export interface CalendarOptions extends BaseOptions {
211
+ mode?: 'single' | 'range';
212
+ initial?: Date | [Date, Date];
213
+ min?: Date;
214
+ max?: Date;
215
+ weekStart?: 0 | 1;
216
+ }
package/dist/utils.js CHANGED
@@ -13,7 +13,7 @@ function detectCapabilities() {
13
13
  // Check for CI
14
14
  const isCI = !!env.CI;
15
15
  // Check for True Color support
16
- const hasTrueColor = env.COLORTERM === 'truecolor';
16
+ const hasTrueColor = env.COLORTERM === 'truecolor' || !!env.WT_SESSION;
17
17
  // Check if it is a TTY
18
18
  const isTTY = process.stdout.isTTY;
19
19
  const isWindows = process.platform === 'win32';
@@ -131,7 +131,11 @@ function stringWidth(str) {
131
131
  continue;
132
132
  }
133
133
  if (inAnsi) {
134
- if ((str[i] >= '@' && str[i] <= '~') || (str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z')) {
134
+ if (str[i] === '[') {
135
+ // Continue, this is the start of CSI
136
+ continue;
137
+ }
138
+ if ((str[i] >= '@' && str[i] <= '~')) {
135
139
  inAnsi = false;
136
140
  }
137
141
  continue;