zammy 1.2.1 → 1.3.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/README.md +322 -239
- package/assets/zammy.gif +0 -0
- package/dist/chunk-LLLEINP6.js +1229 -0
- package/dist/index.js +1886 -489
- package/dist/plugins.d.ts +168 -0
- package/dist/plugins.js +47 -0
- package/package.json +20 -2
- package/packages/plugins/docker/README.md +141 -0
- package/packages/plugins/docker/dist/index.d.ts +4 -0
- package/packages/plugins/docker/dist/index.d.ts.map +1 -0
- package/packages/plugins/docker/dist/index.js +402 -0
- package/packages/plugins/docker/dist/index.js.map +1 -0
- package/packages/plugins/docker/package.json +32 -0
- package/packages/plugins/docker/zammy-plugin.json +16 -0
- package/packages/plugins/faker/README.md +65 -0
- package/packages/plugins/faker/dist/index.d.ts +4 -0
- package/packages/plugins/faker/dist/index.d.ts.map +1 -0
- package/packages/plugins/faker/dist/index.js +349 -0
- package/packages/plugins/faker/dist/index.js.map +1 -0
- package/packages/plugins/faker/package.json +32 -0
- package/packages/plugins/faker/zammy-plugin.json +14 -0
- package/packages/plugins/network/README.md +126 -0
- package/packages/plugins/network/dist/index.d.ts +4 -0
- package/packages/plugins/network/dist/index.d.ts.map +1 -0
- package/packages/plugins/network/dist/index.js +405 -0
- package/packages/plugins/network/dist/index.js.map +1 -0
- package/packages/plugins/network/package.json +32 -0
- package/packages/plugins/network/zammy-plugin.json +17 -0
- package/packages/plugins/port/README.md +74 -0
- package/packages/plugins/port/dist/index.d.ts +4 -0
- package/packages/plugins/port/dist/index.d.ts.map +1 -0
- package/packages/plugins/port/dist/index.js +331 -0
- package/packages/plugins/port/dist/index.js.map +1 -0
- package/packages/plugins/port/package.json +32 -0
- package/packages/plugins/port/zammy-plugin.json +16 -0
- package/packages/plugins/tsconfig.base.json +17 -0
package/dist/index.js
CHANGED
|
@@ -1,235 +1,42 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
box,
|
|
4
|
+
bubble,
|
|
5
|
+
categoryIcons,
|
|
6
|
+
checkConflicts,
|
|
7
|
+
detectSourceType,
|
|
8
|
+
discoverPlugins,
|
|
9
|
+
formatPermissions,
|
|
10
|
+
getAllCommands,
|
|
11
|
+
getCommand,
|
|
12
|
+
getDiscoveredPlugins,
|
|
13
|
+
getPluginCommands,
|
|
14
|
+
initPluginLoader,
|
|
15
|
+
installFromGit,
|
|
16
|
+
installFromGithub,
|
|
17
|
+
installFromLocal,
|
|
18
|
+
installFromNpm,
|
|
19
|
+
isPluginLoaded,
|
|
20
|
+
loadPlugin,
|
|
21
|
+
progressBar,
|
|
22
|
+
registerCommand,
|
|
23
|
+
registerPluginCommand,
|
|
24
|
+
removePlugin,
|
|
25
|
+
spinnerFrames,
|
|
26
|
+
symbols,
|
|
27
|
+
theme,
|
|
28
|
+
unloadPlugin
|
|
29
|
+
} from "./chunk-LLLEINP6.js";
|
|
2
30
|
|
|
3
31
|
// src/index.ts
|
|
4
32
|
import * as readline from "readline";
|
|
5
33
|
|
|
6
34
|
// src/ui/banner.ts
|
|
7
35
|
import figlet from "figlet";
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
// src/ui/colors.ts
|
|
11
|
-
import chalk from "chalk";
|
|
12
|
-
var palette = {
|
|
13
|
-
rose: "#FF6B6B",
|
|
14
|
-
coral: "#FF8E72",
|
|
15
|
-
peach: "#FFEAA7",
|
|
16
|
-
mint: "#96CEB4",
|
|
17
|
-
teal: "#4ECDC4",
|
|
18
|
-
sky: "#45B7D1",
|
|
19
|
-
lavender: "#DDA0DD",
|
|
20
|
-
purple: "#9B59B6",
|
|
21
|
-
gold: "#FFD700",
|
|
22
|
-
silver: "#C0C0C0"
|
|
23
|
-
};
|
|
24
|
-
var theme = {
|
|
25
|
-
primary: chalk.hex(palette.teal),
|
|
26
|
-
secondary: chalk.hex(palette.lavender),
|
|
27
|
-
success: chalk.hex("#2ECC71"),
|
|
28
|
-
warning: chalk.hex("#F39C12"),
|
|
29
|
-
error: chalk.hex("#E74C3C"),
|
|
30
|
-
dim: chalk.hex("#6C7A89"),
|
|
31
|
-
highlight: chalk.bold.white,
|
|
32
|
-
command: chalk.bold.hex(palette.teal),
|
|
33
|
-
prompt: chalk.bold.hex(palette.lavender),
|
|
34
|
-
accent: chalk.hex(palette.rose),
|
|
35
|
-
info: chalk.hex(palette.sky),
|
|
36
|
-
muted: chalk.dim.hex("#95A5A6"),
|
|
37
|
-
gold: chalk.hex(palette.gold),
|
|
38
|
-
rose: chalk.hex(palette.rose),
|
|
39
|
-
mint: chalk.hex(palette.mint),
|
|
40
|
-
peach: chalk.hex(palette.peach),
|
|
41
|
-
// Gradient text effects
|
|
42
|
-
gradient: (text) => {
|
|
43
|
-
const colors = [palette.rose, palette.coral, palette.peach, palette.mint, palette.teal];
|
|
44
|
-
return text.split("").map(
|
|
45
|
-
(char, i) => chalk.hex(colors[i % colors.length])(char)
|
|
46
|
-
).join("");
|
|
47
|
-
},
|
|
48
|
-
rainbow: (text) => {
|
|
49
|
-
const colors = ["#FF6B6B", "#FF8E72", "#FFEAA7", "#96CEB4", "#4ECDC4", "#45B7D1", "#DDA0DD"];
|
|
50
|
-
return text.split("").map(
|
|
51
|
-
(char, i) => chalk.hex(colors[i % colors.length])(char)
|
|
52
|
-
).join("");
|
|
53
|
-
},
|
|
54
|
-
ocean: (text) => {
|
|
55
|
-
const colors = ["#0077B6", "#00B4D8", "#48CAE4", "#90E0EF", "#CAF0F8"];
|
|
56
|
-
return text.split("").map(
|
|
57
|
-
(char, i) => chalk.hex(colors[i % colors.length])(char)
|
|
58
|
-
).join("");
|
|
59
|
-
},
|
|
60
|
-
sunset: (text) => {
|
|
61
|
-
const colors = ["#FF6B6B", "#FF8E53", "#FFA07A", "#FFB347", "#FFD700"];
|
|
62
|
-
return text.split("").map(
|
|
63
|
-
(char, i) => chalk.hex(colors[i % colors.length])(char)
|
|
64
|
-
).join("");
|
|
65
|
-
},
|
|
66
|
-
// Bold variants
|
|
67
|
-
b: {
|
|
68
|
-
primary: chalk.bold.hex(palette.teal),
|
|
69
|
-
secondary: chalk.bold.hex(palette.lavender),
|
|
70
|
-
success: chalk.bold.hex("#2ECC71"),
|
|
71
|
-
warning: chalk.bold.hex("#F39C12"),
|
|
72
|
-
error: chalk.bold.hex("#E74C3C")
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
var symbols = {
|
|
76
|
-
// Basic UI
|
|
77
|
-
arrow: "\u276F",
|
|
78
|
-
// ❯
|
|
79
|
-
check: "\u2714",
|
|
80
|
-
// ✔
|
|
81
|
-
cross: "\u2718",
|
|
82
|
-
// ✘
|
|
83
|
-
info: "\u2139",
|
|
84
|
-
// ℹ
|
|
85
|
-
warning: "\u26A0",
|
|
86
|
-
// ⚠
|
|
87
|
-
bullet: "\u2022",
|
|
88
|
-
// •
|
|
89
|
-
// Decorative
|
|
90
|
-
star: "\u2605",
|
|
91
|
-
// ★
|
|
92
|
-
heart: "\u2665",
|
|
93
|
-
// ♥
|
|
94
|
-
diamond: "\u2666",
|
|
95
|
-
// ♦
|
|
96
|
-
sparkle: "\u2728",
|
|
97
|
-
// ✨
|
|
98
|
-
lightning: "\u26A1",
|
|
99
|
-
// ⚡
|
|
100
|
-
// Emoji icons
|
|
101
|
-
fire: "\u{1F525}",
|
|
102
|
-
// 🔥
|
|
103
|
-
rocket: "\u{1F680}",
|
|
104
|
-
// 🚀
|
|
105
|
-
dice: "\u{1F3B2}",
|
|
106
|
-
// 🎲
|
|
107
|
-
coin: "\u{1FA99}",
|
|
108
|
-
// 🪙
|
|
109
|
-
lock: "\u{1F512}",
|
|
110
|
-
// 🔒
|
|
111
|
-
clock: "\u{1F552}",
|
|
112
|
-
// 🕒
|
|
113
|
-
chart: "\u{1F4CA}",
|
|
114
|
-
// 📊
|
|
115
|
-
note: "\u{1F4DD}",
|
|
116
|
-
// 📝
|
|
117
|
-
scroll: "\u{1F4DC}",
|
|
118
|
-
// 📜
|
|
119
|
-
clipboard: "\u{1F4CB}",
|
|
120
|
-
// 📋
|
|
121
|
-
palette: "\u{1F3A8}",
|
|
122
|
-
// 🎨
|
|
123
|
-
tomato: "\u{1F345}",
|
|
124
|
-
// 🍅
|
|
125
|
-
coffee: "\u2615",
|
|
126
|
-
// ☕
|
|
127
|
-
bell: "\u{1F514}",
|
|
128
|
-
// 🔔
|
|
129
|
-
gear: "\u2699",
|
|
130
|
-
// ⚙
|
|
131
|
-
folder: "\u{1F4C1}",
|
|
132
|
-
// 📁
|
|
133
|
-
terminal: "\u{1F4BB}",
|
|
134
|
-
// 💻
|
|
135
|
-
key: "\u{1F511}",
|
|
136
|
-
// 🔑
|
|
137
|
-
link: "\u{1F517}",
|
|
138
|
-
// 🔗
|
|
139
|
-
hourglass: "\u23F3"
|
|
140
|
-
// ⏳
|
|
141
|
-
};
|
|
142
|
-
var boxChars = {
|
|
143
|
-
rounded: { tl: "\u256D", tr: "\u256E", bl: "\u2570", br: "\u256F", h: "\u2500", v: "\u2502" },
|
|
144
|
-
sharp: { tl: "\u250C", tr: "\u2510", bl: "\u2514", br: "\u2518", h: "\u2500", v: "\u2502" },
|
|
145
|
-
double: { tl: "\u2554", tr: "\u2557", bl: "\u255A", br: "\u255D", h: "\u2550", v: "\u2551" },
|
|
146
|
-
heavy: { tl: "\u250F", tr: "\u2513", bl: "\u2517", br: "\u251B", h: "\u2501", v: "\u2503" }
|
|
147
|
-
};
|
|
148
|
-
var box = {
|
|
149
|
-
topLeft: "\u256D",
|
|
150
|
-
// ╭
|
|
151
|
-
topRight: "\u256E",
|
|
152
|
-
// ╮
|
|
153
|
-
bottomLeft: "\u2570",
|
|
154
|
-
// ╰
|
|
155
|
-
bottomRight: "\u256F",
|
|
156
|
-
// ╯
|
|
157
|
-
horizontal: "\u2500",
|
|
158
|
-
// ─
|
|
159
|
-
vertical: "\u2502",
|
|
160
|
-
// │
|
|
161
|
-
draw: (content, width = 50, style = "rounded") => {
|
|
162
|
-
const chars = boxChars[style];
|
|
163
|
-
const lines = [];
|
|
164
|
-
const innerWidth = width - 2;
|
|
165
|
-
lines.push(theme.dim(`${chars.tl}${chars.h.repeat(innerWidth)}${chars.tr}`));
|
|
166
|
-
content.forEach((line) => {
|
|
167
|
-
const stripped = line.replace(/\x1B\[[0-9;]*m/g, "");
|
|
168
|
-
const padding = innerWidth - stripped.length;
|
|
169
|
-
lines.push(theme.dim(chars.v) + line + " ".repeat(Math.max(0, padding)) + theme.dim(chars.v));
|
|
170
|
-
});
|
|
171
|
-
lines.push(theme.dim(`${chars.bl}${chars.h.repeat(innerWidth)}${chars.br}`));
|
|
172
|
-
return lines.join("\n");
|
|
173
|
-
},
|
|
174
|
-
// Simple title box
|
|
175
|
-
title: (title, width = 50) => {
|
|
176
|
-
const chars = boxChars.rounded;
|
|
177
|
-
const innerWidth = width - 2;
|
|
178
|
-
const titleLen = title.replace(/\x1B\[[0-9;]*m/g, "").length;
|
|
179
|
-
const leftPad = Math.floor((innerWidth - titleLen - 2) / 2);
|
|
180
|
-
const rightPad = innerWidth - titleLen - 2 - leftPad;
|
|
181
|
-
return theme.dim(`${chars.tl}${chars.h.repeat(leftPad)} `) + title + theme.dim(` ${chars.h.repeat(rightPad)}${chars.tr}`);
|
|
182
|
-
}
|
|
183
|
-
};
|
|
184
|
-
var bubble = {
|
|
185
|
-
say: (text, width = 50) => {
|
|
186
|
-
const lines = [];
|
|
187
|
-
const innerWidth = width - 4;
|
|
188
|
-
const words = text.split(" ");
|
|
189
|
-
let currentLine = "";
|
|
190
|
-
const wrappedLines = [];
|
|
191
|
-
for (const word of words) {
|
|
192
|
-
if ((currentLine + " " + word).trim().length <= innerWidth) {
|
|
193
|
-
currentLine = (currentLine + " " + word).trim();
|
|
194
|
-
} else {
|
|
195
|
-
if (currentLine) wrappedLines.push(currentLine);
|
|
196
|
-
currentLine = word;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
if (currentLine) wrappedLines.push(currentLine);
|
|
200
|
-
lines.push(theme.dim(" \u256D" + "\u2500".repeat(innerWidth + 2) + "\u256E"));
|
|
201
|
-
for (const line of wrappedLines) {
|
|
202
|
-
const padding = innerWidth - line.length;
|
|
203
|
-
lines.push(theme.dim(" \u2502 ") + line + " ".repeat(padding) + theme.dim(" \u2502"));
|
|
204
|
-
}
|
|
205
|
-
lines.push(theme.dim(" \u2570" + "\u2500".repeat(innerWidth + 2) + "\u256F"));
|
|
206
|
-
lines.push(theme.dim(" \u2572"));
|
|
207
|
-
lines.push(theme.dim(" \u2572"));
|
|
208
|
-
return lines.join("\n");
|
|
209
|
-
},
|
|
210
|
-
think: (text, width = 50) => {
|
|
211
|
-
const lines = [];
|
|
212
|
-
const innerWidth = width - 4;
|
|
213
|
-
lines.push(theme.dim(" \u256D" + "\u2500".repeat(innerWidth + 2) + "\u256E"));
|
|
214
|
-
const padding = innerWidth - text.length;
|
|
215
|
-
lines.push(theme.dim(" \u2502 ") + text + " ".repeat(Math.max(0, padding)) + theme.dim(" \u2502"));
|
|
216
|
-
lines.push(theme.dim(" \u2570" + "\u2500".repeat(innerWidth + 2) + "\u256F"));
|
|
217
|
-
lines.push(theme.dim(" \u25CB"));
|
|
218
|
-
lines.push(theme.dim(" \u25CB"));
|
|
219
|
-
return lines.join("\n");
|
|
220
|
-
}
|
|
221
|
-
};
|
|
222
|
-
var categoryIcons = {
|
|
223
|
-
"Utilities": "\u{1F527}",
|
|
224
|
-
"Fun": "\u{1F3AE}",
|
|
225
|
-
"Creative": "\u{1F3A8}",
|
|
226
|
-
"Dev": "\u{1F4BB}",
|
|
227
|
-
"Info": "\u{1F4E1}"
|
|
228
|
-
};
|
|
229
|
-
var spinnerFrames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
36
|
+
import chalk2 from "chalk";
|
|
230
37
|
|
|
231
38
|
// src/ui/slime-animated.ts
|
|
232
|
-
import
|
|
39
|
+
import chalk from "chalk";
|
|
233
40
|
var C = {
|
|
234
41
|
P1: "#4A235A",
|
|
235
42
|
// Darkest edge
|
|
@@ -256,15 +63,15 @@ var C = {
|
|
|
256
63
|
RD: "#E74C3C"
|
|
257
64
|
// Red (angry)
|
|
258
65
|
};
|
|
259
|
-
var b = (hex) =>
|
|
260
|
-
var dot =
|
|
261
|
-
var star =
|
|
262
|
-
var heart =
|
|
263
|
-
var z =
|
|
264
|
-
var Z =
|
|
265
|
-
var eye =
|
|
266
|
-
var shine =
|
|
267
|
-
var shine2 =
|
|
66
|
+
var b = (hex) => chalk.bgHex(hex)(" ");
|
|
67
|
+
var dot = chalk.hex(C.WH)("\xB7");
|
|
68
|
+
var star = chalk.hex(C.WH)("\u2726");
|
|
69
|
+
var heart = chalk.hex(C.PK)("\u2665");
|
|
70
|
+
var z = chalk.hex(C.CY)("z");
|
|
71
|
+
var Z = chalk.hex(C.CY)("Z");
|
|
72
|
+
var eye = chalk.bgHex(C.BK).hex(C.WH)(" \xB7");
|
|
73
|
+
var shine = chalk.bgHex(C.P3).hex(C.WH)(" \xB7");
|
|
74
|
+
var shine2 = chalk.bgHex(C.P4).hex(C.WH)("\xB7 ");
|
|
268
75
|
var slimeFrames = {
|
|
269
76
|
happy: () => {
|
|
270
77
|
const { P1, P2, P3, P4, P5, BK, PK } = C;
|
|
@@ -281,7 +88,7 @@ var slimeFrames = {
|
|
|
281
88
|
},
|
|
282
89
|
excited: () => {
|
|
283
90
|
const { P1, P2, P3, P4, P5, BK, PK, YL } = C;
|
|
284
|
-
const starEye =
|
|
91
|
+
const starEye = chalk.bgHex(YL).hex(C.WH)("\u2605 ");
|
|
285
92
|
return [
|
|
286
93
|
` ${star} ${dot} ${star} ${dot} ${star}`,
|
|
287
94
|
` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
|
|
@@ -295,7 +102,7 @@ var slimeFrames = {
|
|
|
295
102
|
},
|
|
296
103
|
love: () => {
|
|
297
104
|
const { P1, P2, P3, P4, P5, BK, PK } = C;
|
|
298
|
-
const heartEye =
|
|
105
|
+
const heartEye = chalk.bgHex(PK).hex(C.WH)("\u2665 ");
|
|
299
106
|
return [
|
|
300
107
|
` ${heart} ${heart}`,
|
|
301
108
|
` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
|
|
@@ -309,7 +116,7 @@ var slimeFrames = {
|
|
|
309
116
|
},
|
|
310
117
|
sleepy: () => {
|
|
311
118
|
const { P1, P2, P3, P4, P5, BK } = C;
|
|
312
|
-
const closedEye =
|
|
119
|
+
const closedEye = chalk.bgHex(P3).hex(BK)("\u2500\u2500");
|
|
313
120
|
return [
|
|
314
121
|
` ${z} ${z} ${Z}`,
|
|
315
122
|
` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
|
|
@@ -323,10 +130,10 @@ var slimeFrames = {
|
|
|
323
130
|
},
|
|
324
131
|
thinking: () => {
|
|
325
132
|
const { P1, P2, P3, P4, P5, BK, YL } = C;
|
|
326
|
-
const thinkEye =
|
|
327
|
-
const lookUpEye =
|
|
133
|
+
const thinkEye = chalk.bgHex(C.BK).hex(C.WH)(" \xB7");
|
|
134
|
+
const lookUpEye = chalk.bgHex(C.BK).hex(C.WH)("\xB7 ");
|
|
328
135
|
return [
|
|
329
|
-
` ${
|
|
136
|
+
` ${chalk.hex(YL)("?")}`,
|
|
330
137
|
` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
|
|
331
138
|
` ${b(P5)}${b(P4)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P4)}${b(P5)}`,
|
|
332
139
|
` ${b(P4)}${b(P3)}${thinkEye}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${lookUpEye}${b(P3)}${b(P4)}`,
|
|
@@ -338,9 +145,9 @@ var slimeFrames = {
|
|
|
338
145
|
},
|
|
339
146
|
surprised: () => {
|
|
340
147
|
const { P1, P2, P3, P4, P5, BK, YL } = C;
|
|
341
|
-
const bigEye =
|
|
148
|
+
const bigEye = chalk.bgHex(BK).hex(C.WH)("\u25C9 ");
|
|
342
149
|
return [
|
|
343
|
-
` ${
|
|
150
|
+
` ${chalk.hex(YL)("!!")}`,
|
|
344
151
|
` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
|
|
345
152
|
` ${b(P5)}${b(P4)}${b(P3)}${shine2}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P4)}${b(P5)}`,
|
|
346
153
|
` ${b(P4)}${b(P3)}${bigEye}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${bigEye}${b(P3)}${b(P4)}`,
|
|
@@ -352,8 +159,8 @@ var slimeFrames = {
|
|
|
352
159
|
},
|
|
353
160
|
sad: () => {
|
|
354
161
|
const { P1, P2, P3, P4, P5, BK, BL } = C;
|
|
355
|
-
const sadEye =
|
|
356
|
-
const tear =
|
|
162
|
+
const sadEye = chalk.bgHex(BK).hex(C.WH)(" \xB7");
|
|
163
|
+
const tear = chalk.bgHex(BL)(" ");
|
|
357
164
|
return [
|
|
358
165
|
` ${dot} ${dot} ${dot}`,
|
|
359
166
|
` ${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}`,
|
|
@@ -367,7 +174,7 @@ var slimeFrames = {
|
|
|
367
174
|
},
|
|
368
175
|
wink: () => {
|
|
369
176
|
const { P1, P2, P3, P4, P5, BK, PK } = C;
|
|
370
|
-
const winkEye =
|
|
177
|
+
const winkEye = chalk.bgHex(P3).hex(BK)("> ");
|
|
371
178
|
return [
|
|
372
179
|
` ${star} ${dot}`,
|
|
373
180
|
` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
|
|
@@ -381,10 +188,10 @@ var slimeFrames = {
|
|
|
381
188
|
},
|
|
382
189
|
angry: () => {
|
|
383
190
|
const { P1, P2, P3, P4, BK, RD } = C;
|
|
384
|
-
const angryEye =
|
|
385
|
-
const angryEye2 =
|
|
191
|
+
const angryEye = chalk.bgHex(BK).hex(RD)("> ");
|
|
192
|
+
const angryEye2 = chalk.bgHex(BK).hex(RD)(" <");
|
|
386
193
|
return [
|
|
387
|
-
` ${
|
|
194
|
+
` ${chalk.hex(RD)("# @!")}`,
|
|
388
195
|
` ${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}`,
|
|
389
196
|
` ${b(P4)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P4)}`,
|
|
390
197
|
` ${b(P4)}${b(P3)}${angryEye}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${angryEye2}${b(P3)}${b(P4)}`,
|
|
@@ -430,15 +237,15 @@ function getStartupMood() {
|
|
|
430
237
|
return "happy";
|
|
431
238
|
}
|
|
432
239
|
var miniSlime = {
|
|
433
|
-
happy:
|
|
434
|
-
excited:
|
|
435
|
-
love:
|
|
436
|
-
sleepy:
|
|
437
|
-
sad:
|
|
438
|
-
surprised:
|
|
439
|
-
wink:
|
|
440
|
-
thinking:
|
|
441
|
-
angry:
|
|
240
|
+
happy: chalk.hex(C.P3)("(") + chalk.hex(C.BK)("\u25D5") + chalk.hex(C.P3)("\u1D17") + chalk.hex(C.BK)("\u25D5") + chalk.hex(C.P3)(")"),
|
|
241
|
+
excited: chalk.hex(C.P3)("(") + chalk.hex(C.YL)("\u2605") + chalk.hex(C.P3)("\u1D17") + chalk.hex(C.YL)("\u2605") + chalk.hex(C.P3)(")"),
|
|
242
|
+
love: chalk.hex(C.P3)("(") + chalk.hex(C.PK)("\u2665") + chalk.hex(C.P3)("\u1D17") + chalk.hex(C.PK)("\u2665") + chalk.hex(C.P3)(")"),
|
|
243
|
+
sleepy: chalk.hex(C.P3)("(") + chalk.hex(C.BK)("\u2013") + chalk.hex(C.P3)("\u03C9") + chalk.hex(C.BK)("\u2013") + chalk.hex(C.P3)(") zZ"),
|
|
244
|
+
sad: chalk.hex(C.P3)("(") + chalk.hex(C.BK)("\u25D5") + chalk.hex(C.P3)("\uFE35") + chalk.hex(C.BK)("\u25D5") + chalk.hex(C.P3)(")"),
|
|
245
|
+
surprised: chalk.hex(C.P3)("(") + chalk.hex(C.BK)("\u25CE") + chalk.hex(C.P3)("\u25CB") + chalk.hex(C.BK)("\u25CE") + chalk.hex(C.P3)(")!"),
|
|
246
|
+
wink: chalk.hex(C.P3)("(") + chalk.hex(C.BK)("\u25D5") + chalk.hex(C.P3)("\u1D17") + chalk.hex(C.BK)(">") + chalk.hex(C.P3)(")"),
|
|
247
|
+
thinking: chalk.hex(C.P3)("(") + chalk.hex(C.BK)("\u25D5") + chalk.hex(C.P3)("\uFF5E") + chalk.hex(C.BK)("\u25D4") + chalk.hex(C.P3)(")"),
|
|
248
|
+
angry: chalk.hex(C.P3)("(") + chalk.hex(C.RD)(">") + chalk.hex(C.P3)("_") + chalk.hex(C.RD)("<") + chalk.hex(C.P3)(")")
|
|
442
249
|
};
|
|
443
250
|
var validMoods = Object.keys(slimeFrames);
|
|
444
251
|
function react(mood, message) {
|
|
@@ -508,16 +315,16 @@ var C2 = {
|
|
|
508
315
|
PK: "#E91E63"
|
|
509
316
|
// Pink (tongue)
|
|
510
317
|
};
|
|
511
|
-
var b2 = (hex) =>
|
|
512
|
-
var dot2 =
|
|
318
|
+
var b2 = (hex) => chalk2.bgHex(hex)(" ");
|
|
319
|
+
var dot2 = chalk2.hex(C2.WH)("\xB7");
|
|
513
320
|
function getSlimeLines(isBlinking, _mood) {
|
|
514
321
|
const { P1, P2, P3, P4, P5, WH, BK, PK } = C2;
|
|
515
|
-
const openEye =
|
|
516
|
-
const closedEye =
|
|
322
|
+
const openEye = chalk2.bgHex(BK).hex(WH)(" \xB7");
|
|
323
|
+
const closedEye = chalk2.bgHex(P3).hex(BK)("\u2500\u2500");
|
|
517
324
|
const eyeL = isBlinking ? closedEye : openEye;
|
|
518
325
|
const eyeR = isBlinking ? closedEye : openEye;
|
|
519
|
-
const shine3 =
|
|
520
|
-
const shine22 =
|
|
326
|
+
const shine3 = chalk2.bgHex(P3).hex(WH)(" \xB7");
|
|
327
|
+
const shine22 = chalk2.bgHex(P4).hex(WH)("\xB7 ");
|
|
521
328
|
const miniBlob = `${b2(P3)}`;
|
|
522
329
|
return [
|
|
523
330
|
` ${dot2} ${dot2}`,
|
|
@@ -534,7 +341,7 @@ var MIN_WIDTH_FOR_MASCOT2 = 90;
|
|
|
534
341
|
var MIN_WIDTH_FOR_FULL_LOGO = 55;
|
|
535
342
|
var MIN_WIDTH_FOR_COMPACT = 30;
|
|
536
343
|
async function displayBanner(simple = false) {
|
|
537
|
-
return new Promise((
|
|
344
|
+
return new Promise((resolve5) => {
|
|
538
345
|
const termWidth = process.stdout.columns || 80;
|
|
539
346
|
figlet("ZAMMY", {
|
|
540
347
|
font: "ANSI Shadow",
|
|
@@ -548,7 +355,7 @@ async function displayBanner(simple = false) {
|
|
|
548
355
|
console.log(theme.secondary(` "${greeting}"`));
|
|
549
356
|
console.log(theme.dim(" Type /help for commands"));
|
|
550
357
|
console.log("");
|
|
551
|
-
|
|
358
|
+
resolve5();
|
|
552
359
|
return;
|
|
553
360
|
}
|
|
554
361
|
let figletLines = [];
|
|
@@ -581,7 +388,7 @@ async function displayBanner(simple = false) {
|
|
|
581
388
|
console.log(theme.dim(` ${symbols.arrow} Type ${theme.primary("/")} to browse commands or ${theme.primary("/help")} for full list`));
|
|
582
389
|
console.log(theme.dim(` ${symbols.arrow} Shell commands start with ${theme.primary("!")} (e.g., ${theme.primary("!ls")}, ${theme.primary("!git")})`));
|
|
583
390
|
console.log("");
|
|
584
|
-
|
|
391
|
+
resolve5();
|
|
585
392
|
return;
|
|
586
393
|
}
|
|
587
394
|
const figletWidth = 50;
|
|
@@ -611,7 +418,7 @@ async function displayBanner(simple = false) {
|
|
|
611
418
|
console.log(theme.dim(` ${symbols.arrow} Type ${theme.primary("/")} to browse commands or ${theme.primary("/help")} for full list`));
|
|
612
419
|
console.log(theme.dim(` ${symbols.arrow} Shell commands start with ${theme.primary("!")} (e.g., ${theme.primary("!ls")}, ${theme.primary("!git")})`));
|
|
613
420
|
console.log("");
|
|
614
|
-
|
|
421
|
+
resolve5();
|
|
615
422
|
});
|
|
616
423
|
});
|
|
617
424
|
}
|
|
@@ -621,35 +428,24 @@ function getPrompt() {
|
|
|
621
428
|
return `${theme.b.primary("zammy")}${theme.dim(symbols.arrow)} `;
|
|
622
429
|
}
|
|
623
430
|
|
|
624
|
-
// src/commands/registry.ts
|
|
625
|
-
var commands = /* @__PURE__ */ new Map();
|
|
626
|
-
function registerCommand(command) {
|
|
627
|
-
commands.set(command.name, command);
|
|
628
|
-
}
|
|
629
|
-
function getCommand(name) {
|
|
630
|
-
return commands.get(name);
|
|
631
|
-
}
|
|
632
|
-
function getAllCommands() {
|
|
633
|
-
return Array.from(commands.values());
|
|
634
|
-
}
|
|
635
|
-
|
|
636
431
|
// src/commands/utilities/help.ts
|
|
637
432
|
var categories = {
|
|
638
433
|
"Utilities": ["help", "exit", "calc", "password", "stats", "time", "countdown", "timer", "todo", "history"],
|
|
639
434
|
"Fun": ["joke", "quote", "fortune", "dice", "flip", "pomodoro", "zammy"],
|
|
640
435
|
"Creative": ["asciiart", "figlet", "lorem", "color"],
|
|
641
436
|
"Dev": ["hash", "uuid", "encode"],
|
|
642
|
-
"Info": ["weather"]
|
|
437
|
+
"Info": ["weather"],
|
|
438
|
+
"System": ["plugin"]
|
|
643
439
|
};
|
|
644
440
|
registerCommand({
|
|
645
441
|
name: "help",
|
|
646
442
|
description: "Show all available commands",
|
|
647
443
|
usage: "/help [command]",
|
|
648
444
|
async execute(args2) {
|
|
649
|
-
const
|
|
445
|
+
const commands = getAllCommands();
|
|
650
446
|
if (args2.length > 0) {
|
|
651
447
|
const cmdName = args2[0].replace(/^\//, "");
|
|
652
|
-
const cmd =
|
|
448
|
+
const cmd = commands.find((c) => c.name === cmdName);
|
|
653
449
|
if (cmd) {
|
|
654
450
|
console.log("");
|
|
655
451
|
console.log(box.draw([
|
|
@@ -677,9 +473,9 @@ registerCommand({
|
|
|
677
473
|
console.log(` ${symbols.rocket} ${theme.gradient("ZAMMY COMMANDS")} ${symbols.rocket}`);
|
|
678
474
|
console.log(` ${theme.rainbow("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501")}`);
|
|
679
475
|
console.log("");
|
|
680
|
-
const maxNameLength = Math.max(...
|
|
476
|
+
const maxNameLength = Math.max(...commands.map((c) => c.name.length));
|
|
681
477
|
for (const [category, cmdNames] of Object.entries(categories)) {
|
|
682
|
-
const categoryCommands =
|
|
478
|
+
const categoryCommands = commands.filter((c) => cmdNames.includes(c.name));
|
|
683
479
|
if (categoryCommands.length === 0) continue;
|
|
684
480
|
const icon = categoryIcons[category] || symbols.folder;
|
|
685
481
|
console.log(` ${icon} ${theme.b.secondary(category)}`);
|
|
@@ -692,8 +488,24 @@ registerCommand({
|
|
|
692
488
|
}
|
|
693
489
|
console.log("");
|
|
694
490
|
}
|
|
491
|
+
const pluginCmds = getPluginCommands();
|
|
492
|
+
if (pluginCmds.length > 0) {
|
|
493
|
+
console.log(` ${symbols.gear} ${theme.b.secondary("Plugins")}`);
|
|
494
|
+
console.log(theme.dim(" " + "\u2500".repeat(46)));
|
|
495
|
+
for (const cmd of pluginCmds) {
|
|
496
|
+
const paddedName = cmd.name.padEnd(maxNameLength + 2);
|
|
497
|
+
const pluginBadge = cmd.pluginName ? theme.dim(`[${cmd.pluginName}]`) : "";
|
|
498
|
+
console.log(
|
|
499
|
+
` ${theme.command("/" + paddedName)} ${theme.dim("\u2502")} ${theme.dim(cmd.description)} ${pluginBadge}`
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
console.log("");
|
|
503
|
+
}
|
|
695
504
|
const categorizedNames = Object.values(categories).flat();
|
|
696
|
-
const
|
|
505
|
+
const pluginCmdNames = pluginCmds.map((c) => c.name);
|
|
506
|
+
const uncategorized = commands.filter(
|
|
507
|
+
(c) => !categorizedNames.includes(c.name) && !pluginCmdNames.includes(c.name) && c.source === "core"
|
|
508
|
+
);
|
|
697
509
|
if (uncategorized.length > 0) {
|
|
698
510
|
console.log(` ${symbols.folder} ${theme.b.secondary("Other")}`);
|
|
699
511
|
console.log(theme.dim(" " + "\u2500".repeat(46)));
|
|
@@ -764,21 +576,126 @@ registerCommand({
|
|
|
764
576
|
});
|
|
765
577
|
|
|
766
578
|
// src/handlers/utilities/calc.ts
|
|
767
|
-
function
|
|
768
|
-
const
|
|
769
|
-
|
|
579
|
+
function tokenize(expression) {
|
|
580
|
+
const tokens = [];
|
|
581
|
+
let i = 0;
|
|
582
|
+
while (i < expression.length) {
|
|
583
|
+
const char = expression[i];
|
|
584
|
+
if (/\s/.test(char)) {
|
|
585
|
+
i++;
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
if (/\d/.test(char) || char === "." && /\d/.test(expression[i + 1])) {
|
|
589
|
+
let numStr = "";
|
|
590
|
+
while (i < expression.length && (/\d/.test(expression[i]) || expression[i] === ".")) {
|
|
591
|
+
numStr += expression[i];
|
|
592
|
+
i++;
|
|
593
|
+
}
|
|
594
|
+
const value = parseFloat(numStr);
|
|
595
|
+
if (isNaN(value)) return null;
|
|
596
|
+
tokens.push({ type: "number", value });
|
|
597
|
+
continue;
|
|
598
|
+
}
|
|
599
|
+
if (["+", "-", "*", "/", "%", "^"].includes(char)) {
|
|
600
|
+
tokens.push({ type: "op", value: char });
|
|
601
|
+
i++;
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
if (char === "(" || char === ")") {
|
|
605
|
+
tokens.push({ type: "paren", value: char });
|
|
606
|
+
i++;
|
|
607
|
+
continue;
|
|
608
|
+
}
|
|
770
609
|
return null;
|
|
771
610
|
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
611
|
+
return tokens;
|
|
612
|
+
}
|
|
613
|
+
var Parser = class {
|
|
614
|
+
tokens;
|
|
615
|
+
pos = 0;
|
|
616
|
+
constructor(tokens) {
|
|
617
|
+
this.tokens = tokens;
|
|
618
|
+
}
|
|
619
|
+
parse() {
|
|
620
|
+
const result = this.expr();
|
|
621
|
+
if (this.pos !== this.tokens.length) return null;
|
|
778
622
|
return result;
|
|
779
|
-
}
|
|
623
|
+
}
|
|
624
|
+
current() {
|
|
625
|
+
return this.tokens[this.pos];
|
|
626
|
+
}
|
|
627
|
+
consume() {
|
|
628
|
+
return this.tokens[this.pos++];
|
|
629
|
+
}
|
|
630
|
+
expr() {
|
|
631
|
+
let left = this.term();
|
|
632
|
+
if (left === null) return null;
|
|
633
|
+
while (this.current()?.type === "op" && ["+", "-"].includes(this.current().value)) {
|
|
634
|
+
const op = this.consume().value;
|
|
635
|
+
const right = this.term();
|
|
636
|
+
if (right === null) return null;
|
|
637
|
+
left = op === "+" ? left + right : left - right;
|
|
638
|
+
}
|
|
639
|
+
return left;
|
|
640
|
+
}
|
|
641
|
+
term() {
|
|
642
|
+
let left = this.power();
|
|
643
|
+
if (left === null) return null;
|
|
644
|
+
while (this.current()?.type === "op" && ["*", "/", "%"].includes(this.current().value)) {
|
|
645
|
+
const op = this.consume().value;
|
|
646
|
+
const right = this.power();
|
|
647
|
+
if (right === null) return null;
|
|
648
|
+
if ((op === "/" || op === "%") && right === 0) return null;
|
|
649
|
+
left = op === "*" ? left * right : op === "/" ? left / right : left % right;
|
|
650
|
+
}
|
|
651
|
+
return left;
|
|
652
|
+
}
|
|
653
|
+
power() {
|
|
654
|
+
const base = this.unary();
|
|
655
|
+
if (base === null) return null;
|
|
656
|
+
if (this.current()?.type === "op" && this.current().value === "^") {
|
|
657
|
+
this.consume();
|
|
658
|
+
const exp = this.power();
|
|
659
|
+
if (exp === null) return null;
|
|
660
|
+
return Math.pow(base, exp);
|
|
661
|
+
}
|
|
662
|
+
return base;
|
|
663
|
+
}
|
|
664
|
+
unary() {
|
|
665
|
+
if (this.current()?.type === "op" && this.current().value === "-") {
|
|
666
|
+
this.consume();
|
|
667
|
+
const val = this.factor();
|
|
668
|
+
if (val === null) return null;
|
|
669
|
+
return -val;
|
|
670
|
+
}
|
|
671
|
+
return this.factor();
|
|
672
|
+
}
|
|
673
|
+
factor() {
|
|
674
|
+
const token = this.current();
|
|
675
|
+
if (token?.type === "number") {
|
|
676
|
+
this.consume();
|
|
677
|
+
return token.value;
|
|
678
|
+
}
|
|
679
|
+
if (token?.type === "paren" && token.value === "(") {
|
|
680
|
+
this.consume();
|
|
681
|
+
const result = this.expr();
|
|
682
|
+
if (result === null) return null;
|
|
683
|
+
if (this.current()?.type !== "paren" || this.current().value !== ")") {
|
|
684
|
+
return null;
|
|
685
|
+
}
|
|
686
|
+
this.consume();
|
|
687
|
+
return result;
|
|
688
|
+
}
|
|
780
689
|
return null;
|
|
781
690
|
}
|
|
691
|
+
};
|
|
692
|
+
function evaluate(expression) {
|
|
693
|
+
const tokens = tokenize(expression);
|
|
694
|
+
if (!tokens || tokens.length === 0) return null;
|
|
695
|
+
const parser = new Parser(tokens);
|
|
696
|
+
const result = parser.parse();
|
|
697
|
+
if (result === null || !isFinite(result)) return null;
|
|
698
|
+
return result;
|
|
782
699
|
}
|
|
783
700
|
function formatNumber(num) {
|
|
784
701
|
if (Math.abs(num) < 1e-4 || Math.abs(num) > 1e10) {
|
|
@@ -1142,15 +1059,16 @@ registerCommand({
|
|
|
1142
1059
|
console.log("");
|
|
1143
1060
|
let remaining = totalSeconds;
|
|
1144
1061
|
let spinnerIndex = 0;
|
|
1145
|
-
return new Promise((
|
|
1062
|
+
return new Promise((resolve5) => {
|
|
1146
1063
|
const interval = setInterval(() => {
|
|
1147
1064
|
process.stdout.write("\r\x1B[K");
|
|
1148
1065
|
if (remaining <= 0) {
|
|
1149
1066
|
clearInterval(interval);
|
|
1067
|
+
process.removeListener("SIGINT", cleanup);
|
|
1150
1068
|
console.log(` ${symbols.sparkle} ${theme.success("TIME'S UP!")} ${symbols.sparkle}`);
|
|
1151
1069
|
console.log("");
|
|
1152
1070
|
process.stdout.write("\x07");
|
|
1153
|
-
|
|
1071
|
+
resolve5();
|
|
1154
1072
|
return;
|
|
1155
1073
|
}
|
|
1156
1074
|
const spinner = spinnerFrames[spinnerIndex % spinnerFrames.length];
|
|
@@ -1162,6 +1080,14 @@ registerCommand({
|
|
|
1162
1080
|
remaining--;
|
|
1163
1081
|
spinnerIndex++;
|
|
1164
1082
|
}, 1e3);
|
|
1083
|
+
const cleanup = () => {
|
|
1084
|
+
clearInterval(interval);
|
|
1085
|
+
process.stdout.write("\r\x1B[K");
|
|
1086
|
+
console.log(` ${symbols.cross} ${theme.secondary("Countdown cancelled")}`);
|
|
1087
|
+
console.log("");
|
|
1088
|
+
resolve5();
|
|
1089
|
+
};
|
|
1090
|
+
process.once("SIGINT", cleanup);
|
|
1165
1091
|
process.stdout.write(` ${theme.secondary(spinnerFrames[0])} ${theme.primary(formatTime(remaining))} remaining...`);
|
|
1166
1092
|
});
|
|
1167
1093
|
}
|
|
@@ -1423,7 +1349,7 @@ registerCommand({
|
|
|
1423
1349
|
let history = [];
|
|
1424
1350
|
try {
|
|
1425
1351
|
if (existsSync2(HISTORY_FILE)) {
|
|
1426
|
-
const lines = readFileSync2(HISTORY_FILE, "utf8").split(
|
|
1352
|
+
const lines = readFileSync2(HISTORY_FILE, "utf8").split(/\r?\n/).filter((l) => l);
|
|
1427
1353
|
history = lines.map((line) => {
|
|
1428
1354
|
const [time, ...rest] = line.split("|");
|
|
1429
1355
|
return { time, cmd: rest.join("|") };
|
|
@@ -1468,58 +1394,368 @@ registerCommand({
|
|
|
1468
1394
|
}
|
|
1469
1395
|
});
|
|
1470
1396
|
|
|
1397
|
+
// src/handlers/utilities/env.ts
|
|
1398
|
+
function getAllEnvVars() {
|
|
1399
|
+
return Object.entries(process.env).filter(([, value]) => value !== void 0).map(([name, value]) => ({ name, value })).sort((a, b3) => a.name.localeCompare(b3.name));
|
|
1400
|
+
}
|
|
1401
|
+
function getEnvVar(name) {
|
|
1402
|
+
const exactMatch = process.env[name];
|
|
1403
|
+
if (exactMatch !== void 0) return exactMatch;
|
|
1404
|
+
const upperName = name.toUpperCase();
|
|
1405
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
1406
|
+
if (key.toUpperCase() === upperName) {
|
|
1407
|
+
return value;
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
return void 0;
|
|
1411
|
+
}
|
|
1412
|
+
function searchEnvVars(query) {
|
|
1413
|
+
const lowerQuery = query.toLowerCase();
|
|
1414
|
+
return getAllEnvVars().filter(
|
|
1415
|
+
(env) => env.name.toLowerCase().includes(lowerQuery) || env.value.toLowerCase().includes(lowerQuery)
|
|
1416
|
+
);
|
|
1417
|
+
}
|
|
1418
|
+
function getPathEntries() {
|
|
1419
|
+
const pathVar = process.env.PATH || process.env.Path || "";
|
|
1420
|
+
const separator = process.platform === "win32" ? ";" : ":";
|
|
1421
|
+
return pathVar.split(separator).filter(Boolean);
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
// src/commands/utilities/env.ts
|
|
1425
|
+
registerCommand({
|
|
1426
|
+
name: "env",
|
|
1427
|
+
description: "View environment variables",
|
|
1428
|
+
usage: "/env [name|search|path]",
|
|
1429
|
+
async execute(args2) {
|
|
1430
|
+
const action = args2[0];
|
|
1431
|
+
console.log("");
|
|
1432
|
+
if (!action) {
|
|
1433
|
+
const vars = getAllEnvVars();
|
|
1434
|
+
console.log(` ${symbols.sparkle} ${theme.gradient("ENVIRONMENT VARIABLES")} ${theme.dim(`(${vars.length})`)}`);
|
|
1435
|
+
console.log("");
|
|
1436
|
+
for (const env of vars.slice(0, 30)) {
|
|
1437
|
+
const displayValue = env.value.length > 50 ? env.value.slice(0, 47) + "..." : env.value;
|
|
1438
|
+
console.log(` ${theme.primary(env.name.padEnd(20))} ${theme.dim("=")} ${displayValue}`);
|
|
1439
|
+
}
|
|
1440
|
+
if (vars.length > 30) {
|
|
1441
|
+
console.log("");
|
|
1442
|
+
console.log(` ${theme.dim(`... and ${vars.length - 30} more. Use /env search <query> to filter.`)}`);
|
|
1443
|
+
}
|
|
1444
|
+
console.log("");
|
|
1445
|
+
return;
|
|
1446
|
+
}
|
|
1447
|
+
if (action.toLowerCase() === "path") {
|
|
1448
|
+
const paths = getPathEntries();
|
|
1449
|
+
console.log(` ${symbols.sparkle} ${theme.gradient("PATH ENTRIES")} ${theme.dim(`(${paths.length})`)}`);
|
|
1450
|
+
console.log("");
|
|
1451
|
+
paths.forEach((p, i) => {
|
|
1452
|
+
console.log(` ${theme.dim(`${(i + 1).toString().padStart(2)}.`)} ${theme.primary(p)}`);
|
|
1453
|
+
});
|
|
1454
|
+
console.log("");
|
|
1455
|
+
return;
|
|
1456
|
+
}
|
|
1457
|
+
if (action.toLowerCase() === "search" && args2[1]) {
|
|
1458
|
+
const query = args2.slice(1).join(" ");
|
|
1459
|
+
const results = searchEnvVars(query);
|
|
1460
|
+
console.log(` ${symbols.sparkle} ${theme.gradient(`SEARCH: "${query}"`)} ${theme.dim(`(${results.length} matches)`)}`);
|
|
1461
|
+
console.log("");
|
|
1462
|
+
if (results.length === 0) {
|
|
1463
|
+
console.log(` ${theme.dim("No matches found")}`);
|
|
1464
|
+
} else {
|
|
1465
|
+
for (const env of results) {
|
|
1466
|
+
const displayValue = env.value.length > 50 ? env.value.slice(0, 47) + "..." : env.value;
|
|
1467
|
+
console.log(` ${theme.primary(env.name.padEnd(20))} ${theme.dim("=")} ${displayValue}`);
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
console.log("");
|
|
1471
|
+
return;
|
|
1472
|
+
}
|
|
1473
|
+
const value = getEnvVar(action);
|
|
1474
|
+
if (value !== void 0) {
|
|
1475
|
+
console.log(` ${theme.primary(action)} ${theme.dim("=")}`);
|
|
1476
|
+
console.log("");
|
|
1477
|
+
if (value.includes(process.platform === "win32" ? ";" : ":") && value.length > 100) {
|
|
1478
|
+
const separator = process.platform === "win32" ? ";" : ":";
|
|
1479
|
+
const parts = value.split(separator);
|
|
1480
|
+
parts.forEach((p, i) => {
|
|
1481
|
+
console.log(` ${theme.dim(`${(i + 1).toString().padStart(2)}.`)} ${p}`);
|
|
1482
|
+
});
|
|
1483
|
+
} else {
|
|
1484
|
+
console.log(` ${theme.success(value)}`);
|
|
1485
|
+
}
|
|
1486
|
+
} else {
|
|
1487
|
+
console.log(` ${symbols.cross} ${theme.error(`Environment variable not found: ${action}`)}`);
|
|
1488
|
+
}
|
|
1489
|
+
console.log("");
|
|
1490
|
+
}
|
|
1491
|
+
});
|
|
1492
|
+
|
|
1493
|
+
// src/handlers/utilities/size.ts
|
|
1494
|
+
import { statSync, readdirSync, existsSync as existsSync3 } from "fs";
|
|
1495
|
+
import { join as join3, basename } from "path";
|
|
1496
|
+
function formatBytes2(bytes) {
|
|
1497
|
+
if (bytes === 0) return "0 B";
|
|
1498
|
+
const units = ["B", "KB", "MB", "GB", "TB"];
|
|
1499
|
+
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
1500
|
+
const size = bytes / Math.pow(1024, i);
|
|
1501
|
+
return `${size.toFixed(i > 0 ? 1 : 0)} ${units[i]}`;
|
|
1502
|
+
}
|
|
1503
|
+
function getSize(path) {
|
|
1504
|
+
if (!existsSync3(path)) return null;
|
|
1505
|
+
try {
|
|
1506
|
+
const stats = statSync(path);
|
|
1507
|
+
if (stats.isFile()) {
|
|
1508
|
+
return {
|
|
1509
|
+
path,
|
|
1510
|
+
name: basename(path),
|
|
1511
|
+
size: stats.size,
|
|
1512
|
+
isDirectory: false
|
|
1513
|
+
};
|
|
1514
|
+
}
|
|
1515
|
+
if (stats.isDirectory()) {
|
|
1516
|
+
return getDirSize(path);
|
|
1517
|
+
}
|
|
1518
|
+
return null;
|
|
1519
|
+
} catch {
|
|
1520
|
+
return null;
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
function getDirSize(dirPath) {
|
|
1524
|
+
const children = [];
|
|
1525
|
+
let totalSize = 0;
|
|
1526
|
+
try {
|
|
1527
|
+
const entries = readdirSync(dirPath, { withFileTypes: true });
|
|
1528
|
+
for (const entry of entries) {
|
|
1529
|
+
const entryPath = join3(dirPath, entry.name);
|
|
1530
|
+
try {
|
|
1531
|
+
if (entry.isFile()) {
|
|
1532
|
+
const stats = statSync(entryPath);
|
|
1533
|
+
totalSize += stats.size;
|
|
1534
|
+
children.push({
|
|
1535
|
+
path: entryPath,
|
|
1536
|
+
name: entry.name,
|
|
1537
|
+
size: stats.size,
|
|
1538
|
+
isDirectory: false
|
|
1539
|
+
});
|
|
1540
|
+
} else if (entry.isDirectory()) {
|
|
1541
|
+
if (["node_modules", ".git", "dist", "build", ".next", "coverage"].includes(entry.name)) {
|
|
1542
|
+
const subSize = getQuickDirSize(entryPath);
|
|
1543
|
+
totalSize += subSize;
|
|
1544
|
+
children.push({
|
|
1545
|
+
path: entryPath,
|
|
1546
|
+
name: entry.name,
|
|
1547
|
+
size: subSize,
|
|
1548
|
+
isDirectory: true
|
|
1549
|
+
});
|
|
1550
|
+
} else {
|
|
1551
|
+
const subInfo = getDirSize(entryPath);
|
|
1552
|
+
totalSize += subInfo.size;
|
|
1553
|
+
children.push(subInfo);
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
} catch {
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
} catch {
|
|
1560
|
+
}
|
|
1561
|
+
children.sort((a, b3) => b3.size - a.size);
|
|
1562
|
+
return {
|
|
1563
|
+
path: dirPath,
|
|
1564
|
+
name: basename(dirPath),
|
|
1565
|
+
size: totalSize,
|
|
1566
|
+
isDirectory: true,
|
|
1567
|
+
children
|
|
1568
|
+
};
|
|
1569
|
+
}
|
|
1570
|
+
function getQuickDirSize(dirPath) {
|
|
1571
|
+
let totalSize = 0;
|
|
1572
|
+
try {
|
|
1573
|
+
const entries = readdirSync(dirPath, { withFileTypes: true });
|
|
1574
|
+
for (const entry of entries) {
|
|
1575
|
+
const entryPath = join3(dirPath, entry.name);
|
|
1576
|
+
try {
|
|
1577
|
+
if (entry.isFile()) {
|
|
1578
|
+
totalSize += statSync(entryPath).size;
|
|
1579
|
+
} else if (entry.isDirectory()) {
|
|
1580
|
+
totalSize += getQuickDirSize(entryPath);
|
|
1581
|
+
}
|
|
1582
|
+
} catch {
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
} catch {
|
|
1586
|
+
}
|
|
1587
|
+
return totalSize;
|
|
1588
|
+
}
|
|
1589
|
+
function findLargestFiles(dirPath, count = 10) {
|
|
1590
|
+
const allFiles = [];
|
|
1591
|
+
function collectFiles(dir) {
|
|
1592
|
+
try {
|
|
1593
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
1594
|
+
for (const entry of entries) {
|
|
1595
|
+
const entryPath = join3(dir, entry.name);
|
|
1596
|
+
try {
|
|
1597
|
+
if (entry.isFile()) {
|
|
1598
|
+
const stats = statSync(entryPath);
|
|
1599
|
+
allFiles.push({
|
|
1600
|
+
path: entryPath,
|
|
1601
|
+
name: entry.name,
|
|
1602
|
+
size: stats.size,
|
|
1603
|
+
isDirectory: false
|
|
1604
|
+
});
|
|
1605
|
+
} else if (entry.isDirectory()) {
|
|
1606
|
+
if (!["node_modules", ".git"].includes(entry.name)) {
|
|
1607
|
+
collectFiles(entryPath);
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
} catch {
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
} catch {
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
collectFiles(dirPath);
|
|
1617
|
+
allFiles.sort((a, b3) => b3.size - a.size);
|
|
1618
|
+
return allFiles.slice(0, count);
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
// src/commands/utilities/size.ts
|
|
1622
|
+
import { resolve } from "path";
|
|
1623
|
+
registerCommand({
|
|
1624
|
+
name: "size",
|
|
1625
|
+
description: "Analyze file/folder sizes",
|
|
1626
|
+
usage: "/size [path] [--top N]",
|
|
1627
|
+
async execute(args2) {
|
|
1628
|
+
const targetPath = args2[0] || ".";
|
|
1629
|
+
const absPath = resolve(targetPath);
|
|
1630
|
+
const topIndex = args2.indexOf("--top");
|
|
1631
|
+
const showTop = topIndex !== -1 ? parseInt(args2[topIndex + 1]) || 10 : 0;
|
|
1632
|
+
console.log("");
|
|
1633
|
+
if (showTop > 0) {
|
|
1634
|
+
console.log(` ${symbols.sparkle} ${theme.gradient("LARGEST FILES")}`);
|
|
1635
|
+
console.log(` ${theme.dim(`in ${absPath}`)}`);
|
|
1636
|
+
console.log("");
|
|
1637
|
+
const largestFiles = findLargestFiles(absPath, showTop);
|
|
1638
|
+
if (largestFiles.length === 0) {
|
|
1639
|
+
console.log(` ${theme.dim("No files found")}`);
|
|
1640
|
+
} else {
|
|
1641
|
+
const maxSize = largestFiles[0].size;
|
|
1642
|
+
for (let i = 0; i < largestFiles.length; i++) {
|
|
1643
|
+
const file = largestFiles[i];
|
|
1644
|
+
const percent = file.size / maxSize * 100;
|
|
1645
|
+
const bar = progressBar(percent, 20);
|
|
1646
|
+
const relativePath = file.path.replace(absPath, ".").replace(/\\/g, "/");
|
|
1647
|
+
console.log(
|
|
1648
|
+
` ${theme.dim(`${(i + 1).toString().padStart(2)}.`)} ${bar} ${theme.primary(formatBytes2(file.size).padStart(10))} ${relativePath}`
|
|
1649
|
+
);
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
console.log("");
|
|
1653
|
+
return;
|
|
1654
|
+
}
|
|
1655
|
+
const info = getSize(absPath);
|
|
1656
|
+
if (!info) {
|
|
1657
|
+
console.log(` ${symbols.cross} ${theme.error(`Path not found: ${absPath}`)}`);
|
|
1658
|
+
console.log("");
|
|
1659
|
+
return;
|
|
1660
|
+
}
|
|
1661
|
+
console.log(` ${symbols.sparkle} ${theme.gradient("SIZE ANALYSIS")}`);
|
|
1662
|
+
console.log(` ${theme.dim(absPath)}`);
|
|
1663
|
+
console.log("");
|
|
1664
|
+
if (!info.isDirectory) {
|
|
1665
|
+
console.log(` ${theme.primary(info.name)}: ${theme.success(formatBytes2(info.size))}`);
|
|
1666
|
+
} else {
|
|
1667
|
+
console.log(` ${theme.secondary("Total:")} ${theme.success(formatBytes2(info.size))}`);
|
|
1668
|
+
console.log("");
|
|
1669
|
+
if (info.children && info.children.length > 0) {
|
|
1670
|
+
const maxSize = info.children[0].size;
|
|
1671
|
+
const displayCount = Math.min(15, info.children.length);
|
|
1672
|
+
for (let i = 0; i < displayCount; i++) {
|
|
1673
|
+
const child = info.children[i];
|
|
1674
|
+
const percent = child.size / maxSize * 100;
|
|
1675
|
+
const bar = progressBar(percent, 15);
|
|
1676
|
+
const icon = child.isDirectory ? symbols.folder : symbols.bullet;
|
|
1677
|
+
console.log(
|
|
1678
|
+
` ${bar} ${theme.primary(formatBytes2(child.size).padStart(10))} ${icon} ${child.name}`
|
|
1679
|
+
);
|
|
1680
|
+
}
|
|
1681
|
+
if (info.children.length > displayCount) {
|
|
1682
|
+
console.log("");
|
|
1683
|
+
console.log(` ${theme.dim(`... and ${info.children.length - displayCount} more items`)}`);
|
|
1684
|
+
}
|
|
1685
|
+
} else {
|
|
1686
|
+
console.log(` ${theme.dim("Directory is empty")}`);
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
console.log("");
|
|
1690
|
+
console.log(` ${theme.dim("Tip: /size . --top 10 shows largest files")}`);
|
|
1691
|
+
console.log("");
|
|
1692
|
+
}
|
|
1693
|
+
});
|
|
1694
|
+
|
|
1471
1695
|
// src/commands/fun/joke.ts
|
|
1472
1696
|
var fallbackJokes = [
|
|
1473
1697
|
{ setup: "Why do programmers prefer dark mode?", punchline: "Because light attracts bugs!" },
|
|
1474
1698
|
{ setup: "Why do Java developers wear glasses?", punchline: "Because they can't C#!" },
|
|
1475
1699
|
{ setup: "A SQL query walks into a bar, walks up to two tables and asks...", punchline: "Can I join you?" },
|
|
1476
1700
|
{ setup: "Why did the developer go broke?", punchline: "Because he used up all his cache!" },
|
|
1477
|
-
{ setup: "How many programmers does it take to change a light bulb?", punchline: "None, that's a hardware problem!" }
|
|
1701
|
+
{ setup: "How many programmers does it take to change a light bulb?", punchline: "None, that's a hardware problem!" },
|
|
1702
|
+
{ setup: "Why do programmers hate nature?", punchline: "It has too many bugs!" },
|
|
1703
|
+
{ setup: "What's a programmer's favorite hangout place?", punchline: "Foo Bar!" },
|
|
1704
|
+
{ setup: "Why was the JavaScript developer sad?", punchline: "Because he didn't Node how to Express himself!" },
|
|
1705
|
+
{ setup: "What do you call a computer that sings?", punchline: "A-Dell!" },
|
|
1706
|
+
{ setup: "Why did the developer quit his job?", punchline: "Because he didn't get arrays (a raise)!" }
|
|
1478
1707
|
];
|
|
1708
|
+
async function fetchJoke() {
|
|
1709
|
+
try {
|
|
1710
|
+
const response = await fetch("https://v2.jokeapi.dev/joke/Programming?type=twopart&safe-mode", {
|
|
1711
|
+
signal: AbortSignal.timeout(3e3)
|
|
1712
|
+
});
|
|
1713
|
+
if (response.ok) {
|
|
1714
|
+
const data = await response.json();
|
|
1715
|
+
if (!data.error && data.setup && data.delivery) {
|
|
1716
|
+
return { setup: data.setup, punchline: data.delivery };
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
} catch {
|
|
1720
|
+
}
|
|
1721
|
+
try {
|
|
1722
|
+
const response = await fetch("https://official-joke-api.appspot.com/jokes/programming/random", {
|
|
1723
|
+
signal: AbortSignal.timeout(3e3)
|
|
1724
|
+
});
|
|
1725
|
+
if (response.ok) {
|
|
1726
|
+
const data = await response.json();
|
|
1727
|
+
if (data && data[0]) {
|
|
1728
|
+
return { setup: data[0].setup, punchline: data[0].punchline };
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
} catch {
|
|
1732
|
+
}
|
|
1733
|
+
return fallbackJokes[Math.floor(Math.random() * fallbackJokes.length)];
|
|
1734
|
+
}
|
|
1479
1735
|
registerCommand({
|
|
1480
1736
|
name: "joke",
|
|
1481
|
-
description: "Get a random joke",
|
|
1737
|
+
description: "Get a random programming joke",
|
|
1482
1738
|
usage: "/joke",
|
|
1483
1739
|
async execute(_args) {
|
|
1484
1740
|
console.log("");
|
|
1485
1741
|
console.log(` ${symbols.dice} ${theme.sunset("Getting a joke...")}`);
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
console.log(bubble.say(joke.setup, 55));
|
|
1499
|
-
console.log(` ${symbols.sparkle}`);
|
|
1500
|
-
await new Promise((resolve3) => setTimeout(resolve3, 1500));
|
|
1501
|
-
console.log("");
|
|
1502
|
-
console.log(` ${theme.gold(" \u2726")} ${theme.b.success(joke.punchline)} ${theme.gold("\u2726")}`);
|
|
1503
|
-
console.log("");
|
|
1504
|
-
console.log(` ${theme.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}`);
|
|
1505
|
-
console.log(` ${symbols.dice} ${theme.dim("Run /joke again for another!")}`);
|
|
1506
|
-
console.log("");
|
|
1507
|
-
} catch (error) {
|
|
1508
|
-
process.stdout.write("\x1B[1A\x1B[2K");
|
|
1509
|
-
const joke = fallbackJokes[Math.floor(Math.random() * fallbackJokes.length)];
|
|
1510
|
-
console.log("");
|
|
1511
|
-
console.log(bubble.say(joke.setup, 55));
|
|
1512
|
-
console.log(` ${symbols.sparkle}`);
|
|
1513
|
-
await new Promise((resolve3) => setTimeout(resolve3, 1500));
|
|
1514
|
-
console.log("");
|
|
1515
|
-
console.log(` ${theme.gold(" \u2726")} ${theme.b.success(joke.punchline)} ${theme.gold("\u2726")}`);
|
|
1516
|
-
console.log("");
|
|
1517
|
-
}
|
|
1742
|
+
const joke = await fetchJoke();
|
|
1743
|
+
process.stdout.write("\x1B[1A\x1B[2K");
|
|
1744
|
+
console.log("");
|
|
1745
|
+
console.log(bubble.say(joke.setup, 55));
|
|
1746
|
+
console.log(` ${symbols.sparkle}`);
|
|
1747
|
+
await new Promise((resolve5) => setTimeout(resolve5, 1500));
|
|
1748
|
+
console.log("");
|
|
1749
|
+
console.log(` ${theme.gold(" \u2726")} ${theme.b.success(joke.punchline)} ${theme.gold("\u2726")}`);
|
|
1750
|
+
console.log("");
|
|
1751
|
+
console.log(` ${theme.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}`);
|
|
1752
|
+
console.log(` ${symbols.dice} ${theme.dim("Run /joke again for another!")}`);
|
|
1753
|
+
console.log("");
|
|
1518
1754
|
}
|
|
1519
1755
|
});
|
|
1520
1756
|
|
|
1521
1757
|
// src/commands/fun/quote.ts
|
|
1522
|
-
var
|
|
1758
|
+
var fallbackQuotes = [
|
|
1523
1759
|
{ text: "The only way to do great work is to love what you do.", author: "Steve Jobs" },
|
|
1524
1760
|
{ text: "Code is like humor. When you have to explain it, it's bad.", author: "Cory House" },
|
|
1525
1761
|
{ text: "First, solve the problem. Then, write the code.", author: "John Johnson" },
|
|
@@ -1536,6 +1772,33 @@ var quotes = [
|
|
|
1536
1772
|
{ text: "There are only two hard things in Computer Science: cache invalidation and naming things.", author: "Phil Karlton" },
|
|
1537
1773
|
{ text: "The best time to plant a tree was 20 years ago. The second best time is now.", author: "Chinese Proverb" }
|
|
1538
1774
|
];
|
|
1775
|
+
async function fetchQuote() {
|
|
1776
|
+
try {
|
|
1777
|
+
const response = await fetch("https://zenquotes.io/api/random", {
|
|
1778
|
+
signal: AbortSignal.timeout(3e3)
|
|
1779
|
+
});
|
|
1780
|
+
if (response.ok) {
|
|
1781
|
+
const data = await response.json();
|
|
1782
|
+
if (data && data[0]) {
|
|
1783
|
+
return { text: data[0].q, author: data[0].a };
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
} catch {
|
|
1787
|
+
}
|
|
1788
|
+
try {
|
|
1789
|
+
const response = await fetch("https://api.quotable.io/random", {
|
|
1790
|
+
signal: AbortSignal.timeout(3e3)
|
|
1791
|
+
});
|
|
1792
|
+
if (response.ok) {
|
|
1793
|
+
const data = await response.json();
|
|
1794
|
+
if (data && data.content) {
|
|
1795
|
+
return { text: data.content, author: data.author };
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
} catch {
|
|
1799
|
+
}
|
|
1800
|
+
return fallbackQuotes[Math.floor(Math.random() * fallbackQuotes.length)];
|
|
1801
|
+
}
|
|
1539
1802
|
function wrapText(text, maxWidth) {
|
|
1540
1803
|
const words = text.split(" ");
|
|
1541
1804
|
const lines = [];
|
|
@@ -1556,7 +1819,10 @@ registerCommand({
|
|
|
1556
1819
|
description: "Get an inspirational quote",
|
|
1557
1820
|
usage: "/quote",
|
|
1558
1821
|
async execute(_args) {
|
|
1559
|
-
|
|
1822
|
+
console.log("");
|
|
1823
|
+
console.log(` ${symbols.sparkle} ${theme.dim("Fetching wisdom...")}`);
|
|
1824
|
+
const quote = await fetchQuote();
|
|
1825
|
+
process.stdout.write("\x1B[1A\x1B[2K\x1B[1A\x1B[2K");
|
|
1560
1826
|
const wrapped = wrapText(quote.text, 55);
|
|
1561
1827
|
console.log("");
|
|
1562
1828
|
console.log(` ${theme.dim("\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E")}`);
|
|
@@ -1928,7 +2194,10 @@ registerCommand({
|
|
|
1928
2194
|
console.log(theme.dim(" Use /pomodoro status to check progress"));
|
|
1929
2195
|
console.log(theme.dim(" Use /pomodoro skip to skip to break"));
|
|
1930
2196
|
console.log("");
|
|
1931
|
-
if (state.interval)
|
|
2197
|
+
if (state.interval) {
|
|
2198
|
+
clearTimeout(state.interval);
|
|
2199
|
+
state.interval = null;
|
|
2200
|
+
}
|
|
1932
2201
|
state.interval = setTimeout(() => {
|
|
1933
2202
|
if (state.running) {
|
|
1934
2203
|
console.log("\n");
|
|
@@ -1937,6 +2206,7 @@ registerCommand({
|
|
|
1937
2206
|
console.log("\n");
|
|
1938
2207
|
state.sessions++;
|
|
1939
2208
|
state.running = false;
|
|
2209
|
+
state.interval = null;
|
|
1940
2210
|
}
|
|
1941
2211
|
}, DURATIONS.work);
|
|
1942
2212
|
return;
|
|
@@ -1946,7 +2216,10 @@ registerCommand({
|
|
|
1946
2216
|
console.log(theme.dim(" Pomodoro is not running"));
|
|
1947
2217
|
return;
|
|
1948
2218
|
}
|
|
1949
|
-
if (state.interval)
|
|
2219
|
+
if (state.interval) {
|
|
2220
|
+
clearTimeout(state.interval);
|
|
2221
|
+
state.interval = null;
|
|
2222
|
+
}
|
|
1950
2223
|
state.running = false;
|
|
1951
2224
|
console.log("");
|
|
1952
2225
|
console.log(` ${symbols.cross} ${theme.secondary("Pomodoro stopped")}`);
|
|
@@ -1959,7 +2232,10 @@ registerCommand({
|
|
|
1959
2232
|
console.log(theme.dim(" Pomodoro is not running"));
|
|
1960
2233
|
return;
|
|
1961
2234
|
}
|
|
1962
|
-
if (state.interval)
|
|
2235
|
+
if (state.interval) {
|
|
2236
|
+
clearTimeout(state.interval);
|
|
2237
|
+
state.interval = null;
|
|
2238
|
+
}
|
|
1963
2239
|
if (state.mode === "work") {
|
|
1964
2240
|
state.sessions++;
|
|
1965
2241
|
state.mode = state.sessions % 4 === 0 ? "longbreak" : "break";
|
|
@@ -1982,6 +2258,7 @@ registerCommand({
|
|
|
1982
2258
|
${symbols.bell} ${state.mode === "work" ? "Focus session" : "Break"} complete!
|
|
1983
2259
|
`);
|
|
1984
2260
|
state.running = false;
|
|
2261
|
+
state.interval = null;
|
|
1985
2262
|
}
|
|
1986
2263
|
}, state.endTime - Date.now());
|
|
1987
2264
|
return;
|
|
@@ -2106,8 +2383,8 @@ registerCommand({
|
|
|
2106
2383
|
|
|
2107
2384
|
// src/commands/creative/asciiart.ts
|
|
2108
2385
|
import Jimp from "jimp";
|
|
2109
|
-
import { existsSync as
|
|
2110
|
-
import { resolve } from "path";
|
|
2386
|
+
import { existsSync as existsSync4 } from "fs";
|
|
2387
|
+
import { resolve as resolve2 } from "path";
|
|
2111
2388
|
var CHAR_RAMPS = {
|
|
2112
2389
|
// Standard - 10 levels, balanced
|
|
2113
2390
|
standard: " .:-=+*#%@",
|
|
@@ -2212,8 +2489,8 @@ registerCommand({
|
|
|
2212
2489
|
i++;
|
|
2213
2490
|
}
|
|
2214
2491
|
}
|
|
2215
|
-
const fullPath =
|
|
2216
|
-
if (!
|
|
2492
|
+
const fullPath = resolve2(process.cwd(), imagePath);
|
|
2493
|
+
if (!existsSync4(fullPath)) {
|
|
2217
2494
|
console.log(theme.error(`File not found: ${imagePath}`));
|
|
2218
2495
|
return;
|
|
2219
2496
|
}
|
|
@@ -2494,7 +2771,7 @@ registerCommand({
|
|
|
2494
2771
|
});
|
|
2495
2772
|
|
|
2496
2773
|
// src/commands/creative/color.ts
|
|
2497
|
-
import
|
|
2774
|
+
import chalk3 from "chalk";
|
|
2498
2775
|
|
|
2499
2776
|
// src/handlers/creative/color.ts
|
|
2500
2777
|
function hexToRgb(hex) {
|
|
@@ -2643,7 +2920,7 @@ registerCommand({
|
|
|
2643
2920
|
console.log("");
|
|
2644
2921
|
console.log(` ${symbols.palette} ${theme.gradient("COLOR CONVERTER")} ${symbols.palette}`);
|
|
2645
2922
|
console.log("");
|
|
2646
|
-
const colorBlock =
|
|
2923
|
+
const colorBlock = chalk3.bgHex(hex).hex(textColor);
|
|
2647
2924
|
console.log(` ${colorBlock(" ")}`);
|
|
2648
2925
|
console.log(` ${colorBlock(" ")}`);
|
|
2649
2926
|
console.log(` ${colorBlock(` ${hex.toUpperCase()} `.slice(0, 40))}`);
|
|
@@ -2658,14 +2935,14 @@ registerCommand({
|
|
|
2658
2935
|
let shadesLine = " ";
|
|
2659
2936
|
const shades = generateShades(rgb);
|
|
2660
2937
|
for (const shade of shades) {
|
|
2661
|
-
shadesLine +=
|
|
2938
|
+
shadesLine += chalk3.bgRgb(shade.r, shade.g, shade.b)(" ");
|
|
2662
2939
|
}
|
|
2663
2940
|
console.log(shadesLine);
|
|
2664
2941
|
console.log(` ${theme.dim("Tints:")}`);
|
|
2665
2942
|
let tintsLine = " ";
|
|
2666
2943
|
const tints = generateTints(rgb);
|
|
2667
2944
|
for (const tint of tints) {
|
|
2668
|
-
tintsLine +=
|
|
2945
|
+
tintsLine += chalk3.bgRgb(tint.r, tint.g, tint.b)(" ");
|
|
2669
2946
|
}
|
|
2670
2947
|
console.log(tintsLine);
|
|
2671
2948
|
console.log("");
|
|
@@ -2772,8 +3049,18 @@ var SUPPORTED_METHODS = ["base64", "url", "hex"];
|
|
|
2772
3049
|
function isValidMethod(method) {
|
|
2773
3050
|
return SUPPORTED_METHODS.includes(method.toLowerCase());
|
|
2774
3051
|
}
|
|
3052
|
+
function isValidBase64(str) {
|
|
3053
|
+
if (!str || str.length === 0) return false;
|
|
3054
|
+
const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
3055
|
+
return base64Regex.test(str) && str.length % 4 === 0;
|
|
3056
|
+
}
|
|
3057
|
+
function isValidHex(str) {
|
|
3058
|
+
if (!str || str.length === 0) return false;
|
|
3059
|
+
return str.length % 2 === 0 && /^[0-9A-Fa-f]+$/.test(str);
|
|
3060
|
+
}
|
|
2775
3061
|
function encodeText(text, method, direction) {
|
|
2776
3062
|
let output;
|
|
3063
|
+
let error;
|
|
2777
3064
|
if (direction === "encode") {
|
|
2778
3065
|
switch (method) {
|
|
2779
3066
|
case "base64":
|
|
@@ -2789,21 +3076,47 @@ function encodeText(text, method, direction) {
|
|
|
2789
3076
|
} else {
|
|
2790
3077
|
switch (method) {
|
|
2791
3078
|
case "base64":
|
|
2792
|
-
|
|
3079
|
+
try {
|
|
3080
|
+
if (!isValidBase64(text)) {
|
|
3081
|
+
output = "";
|
|
3082
|
+
error = "Invalid base64 input";
|
|
3083
|
+
} else {
|
|
3084
|
+
output = Buffer.from(text, "base64").toString("utf-8");
|
|
3085
|
+
}
|
|
3086
|
+
} catch (e) {
|
|
3087
|
+
output = "";
|
|
3088
|
+
error = "Failed to decode base64: invalid input";
|
|
3089
|
+
}
|
|
2793
3090
|
break;
|
|
2794
3091
|
case "url":
|
|
2795
|
-
|
|
3092
|
+
try {
|
|
3093
|
+
output = decodeURIComponent(text);
|
|
3094
|
+
} catch (e) {
|
|
3095
|
+
output = "";
|
|
3096
|
+
error = "Failed to decode URL: malformed URI sequence";
|
|
3097
|
+
}
|
|
2796
3098
|
break;
|
|
2797
3099
|
case "hex":
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
3100
|
+
try {
|
|
3101
|
+
if (!isValidHex(text)) {
|
|
3102
|
+
output = "";
|
|
3103
|
+
error = "Invalid hex input: must be even length and contain only 0-9, A-F";
|
|
3104
|
+
} else {
|
|
3105
|
+
output = Buffer.from(text, "hex").toString("utf-8");
|
|
3106
|
+
}
|
|
3107
|
+
} catch (e) {
|
|
3108
|
+
output = "";
|
|
3109
|
+
error = "Failed to decode hex: invalid input";
|
|
3110
|
+
}
|
|
3111
|
+
break;
|
|
3112
|
+
}
|
|
3113
|
+
}
|
|
2802
3114
|
return {
|
|
2803
3115
|
method: method.toUpperCase(),
|
|
2804
3116
|
direction,
|
|
2805
3117
|
input: text,
|
|
2806
|
-
output
|
|
3118
|
+
output,
|
|
3119
|
+
...error && { error }
|
|
2807
3120
|
};
|
|
2808
3121
|
}
|
|
2809
3122
|
|
|
@@ -2865,6 +3178,565 @@ registerCommand({
|
|
|
2865
3178
|
}
|
|
2866
3179
|
});
|
|
2867
3180
|
|
|
3181
|
+
// src/handlers/dev/json.ts
|
|
3182
|
+
function validateJson(input) {
|
|
3183
|
+
try {
|
|
3184
|
+
const data = JSON.parse(input);
|
|
3185
|
+
return { valid: true, data };
|
|
3186
|
+
} catch (error) {
|
|
3187
|
+
const message = error instanceof Error ? error.message : "Invalid JSON";
|
|
3188
|
+
return { valid: false, error: message };
|
|
3189
|
+
}
|
|
3190
|
+
}
|
|
3191
|
+
function formatJson(input, indent = 2) {
|
|
3192
|
+
try {
|
|
3193
|
+
const data = JSON.parse(input);
|
|
3194
|
+
const formatted = JSON.stringify(data, null, indent);
|
|
3195
|
+
return { valid: true, data, formatted };
|
|
3196
|
+
} catch (error) {
|
|
3197
|
+
const message = error instanceof Error ? error.message : "Invalid JSON";
|
|
3198
|
+
return { valid: false, error: message };
|
|
3199
|
+
}
|
|
3200
|
+
}
|
|
3201
|
+
function minifyJson(input) {
|
|
3202
|
+
try {
|
|
3203
|
+
const data = JSON.parse(input);
|
|
3204
|
+
const formatted = JSON.stringify(data);
|
|
3205
|
+
return { valid: true, data, formatted };
|
|
3206
|
+
} catch (error) {
|
|
3207
|
+
const message = error instanceof Error ? error.message : "Invalid JSON";
|
|
3208
|
+
return { valid: false, error: message };
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
function queryJson(input, path) {
|
|
3212
|
+
try {
|
|
3213
|
+
const data = JSON.parse(input);
|
|
3214
|
+
const parts = path.replace(/^\$\.?/, "").split(".").filter(Boolean);
|
|
3215
|
+
let current = data;
|
|
3216
|
+
for (const part of parts) {
|
|
3217
|
+
const arrayMatch = part.match(/^(\w*)\[(\d+)\]$/);
|
|
3218
|
+
if (arrayMatch) {
|
|
3219
|
+
const [, key, index] = arrayMatch;
|
|
3220
|
+
if (key) {
|
|
3221
|
+
current = current[key];
|
|
3222
|
+
}
|
|
3223
|
+
if (Array.isArray(current)) {
|
|
3224
|
+
current = current[parseInt(index)];
|
|
3225
|
+
} else {
|
|
3226
|
+
return { valid: false, error: `Not an array at ${part}` };
|
|
3227
|
+
}
|
|
3228
|
+
} else {
|
|
3229
|
+
if (current && typeof current === "object") {
|
|
3230
|
+
current = current[part];
|
|
3231
|
+
} else {
|
|
3232
|
+
return { valid: false, error: `Cannot access ${part}` };
|
|
3233
|
+
}
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
3236
|
+
return { valid: true, data: current, formatted: JSON.stringify(current, null, 2) };
|
|
3237
|
+
} catch (error) {
|
|
3238
|
+
const message = error instanceof Error ? error.message : "Invalid JSON";
|
|
3239
|
+
return { valid: false, error: message };
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3242
|
+
function getJsonStats(input) {
|
|
3243
|
+
try {
|
|
3244
|
+
let countKeys2 = function(obj, depth = 0) {
|
|
3245
|
+
if (typeof obj !== "object" || obj === null) {
|
|
3246
|
+
return { keys: 0, maxDepth: depth };
|
|
3247
|
+
}
|
|
3248
|
+
let keys = 0;
|
|
3249
|
+
let maxDepth = depth;
|
|
3250
|
+
if (Array.isArray(obj)) {
|
|
3251
|
+
for (const item of obj) {
|
|
3252
|
+
const result = countKeys2(item, depth + 1);
|
|
3253
|
+
keys += result.keys;
|
|
3254
|
+
maxDepth = Math.max(maxDepth, result.maxDepth);
|
|
3255
|
+
}
|
|
3256
|
+
} else {
|
|
3257
|
+
keys = Object.keys(obj).length;
|
|
3258
|
+
for (const value of Object.values(obj)) {
|
|
3259
|
+
const result = countKeys2(value, depth + 1);
|
|
3260
|
+
keys += result.keys;
|
|
3261
|
+
maxDepth = Math.max(maxDepth, result.maxDepth);
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3264
|
+
return { keys, maxDepth };
|
|
3265
|
+
};
|
|
3266
|
+
var countKeys = countKeys2;
|
|
3267
|
+
const data = JSON.parse(input);
|
|
3268
|
+
const stats = countKeys2(data);
|
|
3269
|
+
const size = new Blob([input]).size;
|
|
3270
|
+
const sizeStr = size < 1024 ? `${size}B` : size < 1024 * 1024 ? `${(size / 1024).toFixed(1)}KB` : `${(size / 1024 / 1024).toFixed(1)}MB`;
|
|
3271
|
+
return { keys: stats.keys, depth: stats.maxDepth, size: sizeStr };
|
|
3272
|
+
} catch {
|
|
3273
|
+
return null;
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
|
|
3277
|
+
// src/commands/dev/json.ts
|
|
3278
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
3279
|
+
registerCommand({
|
|
3280
|
+
name: "json",
|
|
3281
|
+
description: "JSON tools (validate, format, query)",
|
|
3282
|
+
usage: "/json <action> <input>\n\n Actions: validate, format, minify, query, stats",
|
|
3283
|
+
async execute(args2) {
|
|
3284
|
+
const action = args2[0]?.toLowerCase();
|
|
3285
|
+
const input = args2.slice(1).join(" ");
|
|
3286
|
+
if (!action) {
|
|
3287
|
+
console.log("");
|
|
3288
|
+
console.log(` ${symbols.sparkle} ${theme.gradient("JSON TOOLS")}`);
|
|
3289
|
+
console.log("");
|
|
3290
|
+
console.log(` ${theme.dim("Usage:")} /json <action> <input>`);
|
|
3291
|
+
console.log("");
|
|
3292
|
+
console.log(` ${theme.dim("Actions:")}`);
|
|
3293
|
+
console.log(` ${theme.primary("validate")} <json|@file> ${theme.dim("Check if JSON is valid")}`);
|
|
3294
|
+
console.log(` ${theme.primary("format")} <json|@file> ${theme.dim("Pretty-print JSON")}`);
|
|
3295
|
+
console.log(` ${theme.primary("minify")} <json|@file> ${theme.dim("Minify JSON")}`);
|
|
3296
|
+
console.log(` ${theme.primary("query")} <path> <json> ${theme.dim("Query with path (e.g., users[0].name)")}`);
|
|
3297
|
+
console.log(` ${theme.primary("stats")} <json|@file> ${theme.dim("Show JSON statistics")}`);
|
|
3298
|
+
console.log("");
|
|
3299
|
+
console.log(` ${theme.dim("Use @filename to read from file")}`);
|
|
3300
|
+
console.log("");
|
|
3301
|
+
return;
|
|
3302
|
+
}
|
|
3303
|
+
let jsonContent = input;
|
|
3304
|
+
if (input.startsWith("@")) {
|
|
3305
|
+
const filePath = input.slice(1);
|
|
3306
|
+
if (!existsSync5(filePath)) {
|
|
3307
|
+
console.log("");
|
|
3308
|
+
console.log(` ${symbols.cross} ${theme.error(`File not found: ${filePath}`)}`);
|
|
3309
|
+
console.log("");
|
|
3310
|
+
return;
|
|
3311
|
+
}
|
|
3312
|
+
jsonContent = readFileSync3(filePath, "utf-8");
|
|
3313
|
+
}
|
|
3314
|
+
console.log("");
|
|
3315
|
+
switch (action) {
|
|
3316
|
+
case "validate": {
|
|
3317
|
+
if (!jsonContent) {
|
|
3318
|
+
console.log(` ${symbols.warning} ${theme.warning("Usage:")} /json validate <json|@file>`);
|
|
3319
|
+
break;
|
|
3320
|
+
}
|
|
3321
|
+
const result = validateJson(jsonContent);
|
|
3322
|
+
if (result.valid) {
|
|
3323
|
+
console.log(` ${symbols.check} ${theme.success("Valid JSON")}`);
|
|
3324
|
+
} else {
|
|
3325
|
+
console.log(` ${symbols.cross} ${theme.error("Invalid JSON")}`);
|
|
3326
|
+
console.log(` ${theme.dim(result.error || "")}`);
|
|
3327
|
+
}
|
|
3328
|
+
break;
|
|
3329
|
+
}
|
|
3330
|
+
case "format":
|
|
3331
|
+
case "pretty": {
|
|
3332
|
+
if (!jsonContent) {
|
|
3333
|
+
console.log(` ${symbols.warning} ${theme.warning("Usage:")} /json format <json|@file>`);
|
|
3334
|
+
break;
|
|
3335
|
+
}
|
|
3336
|
+
const result = formatJson(jsonContent);
|
|
3337
|
+
if (result.valid && result.formatted) {
|
|
3338
|
+
console.log(` ${symbols.check} ${theme.success("Formatted JSON:")}`);
|
|
3339
|
+
console.log("");
|
|
3340
|
+
for (const line of result.formatted.split("\n")) {
|
|
3341
|
+
console.log(` ${theme.primary(line)}`);
|
|
3342
|
+
}
|
|
3343
|
+
} else {
|
|
3344
|
+
console.log(` ${symbols.cross} ${theme.error("Invalid JSON")}`);
|
|
3345
|
+
console.log(` ${theme.dim(result.error || "")}`);
|
|
3346
|
+
}
|
|
3347
|
+
break;
|
|
3348
|
+
}
|
|
3349
|
+
case "minify":
|
|
3350
|
+
case "min": {
|
|
3351
|
+
if (!jsonContent) {
|
|
3352
|
+
console.log(` ${symbols.warning} ${theme.warning("Usage:")} /json minify <json|@file>`);
|
|
3353
|
+
break;
|
|
3354
|
+
}
|
|
3355
|
+
const result = minifyJson(jsonContent);
|
|
3356
|
+
if (result.valid && result.formatted) {
|
|
3357
|
+
console.log(` ${symbols.check} ${theme.success("Minified:")}`);
|
|
3358
|
+
console.log("");
|
|
3359
|
+
console.log(` ${theme.primary(result.formatted)}`);
|
|
3360
|
+
} else {
|
|
3361
|
+
console.log(` ${symbols.cross} ${theme.error("Invalid JSON")}`);
|
|
3362
|
+
console.log(` ${theme.dim(result.error || "")}`);
|
|
3363
|
+
}
|
|
3364
|
+
break;
|
|
3365
|
+
}
|
|
3366
|
+
case "query":
|
|
3367
|
+
case "get": {
|
|
3368
|
+
const path = args2[1];
|
|
3369
|
+
const queryInput = args2.slice(2).join(" ");
|
|
3370
|
+
if (!path || !queryInput) {
|
|
3371
|
+
console.log(` ${symbols.warning} ${theme.warning("Usage:")} /json query <path> <json|@file>`);
|
|
3372
|
+
console.log("");
|
|
3373
|
+
console.log(` ${theme.dim("Examples:")}`);
|
|
3374
|
+
console.log(` /json query name '{"name": "John"}'`);
|
|
3375
|
+
console.log(` /json query users[0].email @data.json`);
|
|
3376
|
+
break;
|
|
3377
|
+
}
|
|
3378
|
+
let queryJsonContent = queryInput;
|
|
3379
|
+
if (queryInput.startsWith("@")) {
|
|
3380
|
+
const filePath = queryInput.slice(1);
|
|
3381
|
+
if (!existsSync5(filePath)) {
|
|
3382
|
+
console.log(` ${symbols.cross} ${theme.error(`File not found: ${filePath}`)}`);
|
|
3383
|
+
break;
|
|
3384
|
+
}
|
|
3385
|
+
queryJsonContent = readFileSync3(filePath, "utf-8");
|
|
3386
|
+
}
|
|
3387
|
+
const result = queryJson(queryJsonContent, path);
|
|
3388
|
+
if (result.valid) {
|
|
3389
|
+
console.log(` ${symbols.check} ${theme.success(`Result for "${path}":`)} `);
|
|
3390
|
+
console.log("");
|
|
3391
|
+
if (result.formatted) {
|
|
3392
|
+
for (const line of result.formatted.split("\n")) {
|
|
3393
|
+
console.log(` ${theme.primary(line)}`);
|
|
3394
|
+
}
|
|
3395
|
+
} else {
|
|
3396
|
+
console.log(` ${theme.dim("undefined")}`);
|
|
3397
|
+
}
|
|
3398
|
+
} else {
|
|
3399
|
+
console.log(` ${symbols.cross} ${theme.error(result.error || "Query failed")}`);
|
|
3400
|
+
}
|
|
3401
|
+
break;
|
|
3402
|
+
}
|
|
3403
|
+
case "stats":
|
|
3404
|
+
case "info": {
|
|
3405
|
+
if (!jsonContent) {
|
|
3406
|
+
console.log(` ${symbols.warning} ${theme.warning("Usage:")} /json stats <json|@file>`);
|
|
3407
|
+
break;
|
|
3408
|
+
}
|
|
3409
|
+
const stats = getJsonStats(jsonContent);
|
|
3410
|
+
if (stats) {
|
|
3411
|
+
console.log(` ${symbols.sparkle} ${theme.gradient("JSON STATS")}`);
|
|
3412
|
+
console.log("");
|
|
3413
|
+
console.log(` ${theme.dim("Total keys:")} ${theme.primary(stats.keys.toString())}`);
|
|
3414
|
+
console.log(` ${theme.dim("Max depth:")} ${theme.primary(stats.depth.toString())}`);
|
|
3415
|
+
console.log(` ${theme.dim("Size:")} ${theme.primary(stats.size)}`);
|
|
3416
|
+
} else {
|
|
3417
|
+
console.log(` ${symbols.cross} ${theme.error("Invalid JSON")}`);
|
|
3418
|
+
}
|
|
3419
|
+
break;
|
|
3420
|
+
}
|
|
3421
|
+
default:
|
|
3422
|
+
console.log(` ${symbols.cross} ${theme.error(`Unknown action: ${action}`)}`);
|
|
3423
|
+
console.log(` ${theme.dim("Run /json to see available actions")}`);
|
|
3424
|
+
}
|
|
3425
|
+
console.log("");
|
|
3426
|
+
}
|
|
3427
|
+
});
|
|
3428
|
+
|
|
3429
|
+
// src/handlers/dev/request.ts
|
|
3430
|
+
import https from "https";
|
|
3431
|
+
import http from "http";
|
|
3432
|
+
import { URL } from "url";
|
|
3433
|
+
async function makeRequest(urlStr, options = { method: "GET" }) {
|
|
3434
|
+
const startTime2 = Date.now();
|
|
3435
|
+
return new Promise((resolve5) => {
|
|
3436
|
+
const timeout = setTimeout(() => {
|
|
3437
|
+
resolve5({ success: false, error: "Request timed out" });
|
|
3438
|
+
}, options.timeout || 3e4);
|
|
3439
|
+
try {
|
|
3440
|
+
const url = new URL(urlStr.startsWith("http") ? urlStr : `https://${urlStr}`);
|
|
3441
|
+
const client = url.protocol === "https:" ? https : http;
|
|
3442
|
+
const reqOptions = {
|
|
3443
|
+
hostname: url.hostname,
|
|
3444
|
+
port: url.port || (url.protocol === "https:" ? 443 : 80),
|
|
3445
|
+
path: url.pathname + url.search,
|
|
3446
|
+
method: options.method.toUpperCase(),
|
|
3447
|
+
headers: {
|
|
3448
|
+
"User-Agent": "Zammy-CLI/1.0",
|
|
3449
|
+
...options.headers
|
|
3450
|
+
}
|
|
3451
|
+
};
|
|
3452
|
+
const req = client.request(reqOptions, (res) => {
|
|
3453
|
+
let body = "";
|
|
3454
|
+
res.on("data", (chunk) => {
|
|
3455
|
+
body += chunk.toString();
|
|
3456
|
+
});
|
|
3457
|
+
res.on("end", () => {
|
|
3458
|
+
clearTimeout(timeout);
|
|
3459
|
+
resolve5({
|
|
3460
|
+
success: true,
|
|
3461
|
+
statusCode: res.statusCode,
|
|
3462
|
+
statusMessage: res.statusMessage,
|
|
3463
|
+
headers: res.headers,
|
|
3464
|
+
body,
|
|
3465
|
+
time: Date.now() - startTime2
|
|
3466
|
+
});
|
|
3467
|
+
});
|
|
3468
|
+
});
|
|
3469
|
+
req.on("error", (error) => {
|
|
3470
|
+
clearTimeout(timeout);
|
|
3471
|
+
resolve5({ success: false, error: error.message });
|
|
3472
|
+
});
|
|
3473
|
+
if (options.body) {
|
|
3474
|
+
req.write(options.body);
|
|
3475
|
+
}
|
|
3476
|
+
req.end();
|
|
3477
|
+
} catch (error) {
|
|
3478
|
+
clearTimeout(timeout);
|
|
3479
|
+
resolve5({ success: false, error: error instanceof Error ? error.message : "Request failed" });
|
|
3480
|
+
}
|
|
3481
|
+
});
|
|
3482
|
+
}
|
|
3483
|
+
function tryParseJson(body) {
|
|
3484
|
+
try {
|
|
3485
|
+
const parsed = JSON.parse(body);
|
|
3486
|
+
return { isJson: true, formatted: JSON.stringify(parsed, null, 2) };
|
|
3487
|
+
} catch {
|
|
3488
|
+
return { isJson: false };
|
|
3489
|
+
}
|
|
3490
|
+
}
|
|
3491
|
+
|
|
3492
|
+
// src/commands/dev/request.ts
|
|
3493
|
+
registerCommand({
|
|
3494
|
+
name: "request",
|
|
3495
|
+
description: "Make HTTP requests",
|
|
3496
|
+
usage: "/request <method> <url> [options]",
|
|
3497
|
+
async execute(args2) {
|
|
3498
|
+
if (args2.length < 1) {
|
|
3499
|
+
console.log("");
|
|
3500
|
+
console.log(` ${symbols.sparkle} ${theme.gradient("HTTP REQUEST")}`);
|
|
3501
|
+
console.log("");
|
|
3502
|
+
console.log(` ${theme.dim("Usage:")} /request <method> <url> [options]`);
|
|
3503
|
+
console.log("");
|
|
3504
|
+
console.log(` ${theme.dim("Methods:")} GET, POST, PUT, DELETE, PATCH, HEAD`);
|
|
3505
|
+
console.log("");
|
|
3506
|
+
console.log(` ${theme.dim("Examples:")}`);
|
|
3507
|
+
console.log(` /request GET https://api.github.com`);
|
|
3508
|
+
console.log(` /request POST https://httpbin.org/post --body '{"name":"test"}'`);
|
|
3509
|
+
console.log(` /request GET api.example.com/users`);
|
|
3510
|
+
console.log("");
|
|
3511
|
+
return;
|
|
3512
|
+
}
|
|
3513
|
+
let method = "GET";
|
|
3514
|
+
let url = args2[0];
|
|
3515
|
+
const methods = ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"];
|
|
3516
|
+
if (methods.includes(args2[0].toUpperCase())) {
|
|
3517
|
+
method = args2[0].toUpperCase();
|
|
3518
|
+
url = args2[1];
|
|
3519
|
+
}
|
|
3520
|
+
if (!url) {
|
|
3521
|
+
console.log("");
|
|
3522
|
+
console.log(` ${symbols.cross} ${theme.error("URL is required")}`);
|
|
3523
|
+
console.log("");
|
|
3524
|
+
return;
|
|
3525
|
+
}
|
|
3526
|
+
const headers = {};
|
|
3527
|
+
let body;
|
|
3528
|
+
for (let i = 2; i < args2.length; i++) {
|
|
3529
|
+
if (args2[i] === "--header" || args2[i] === "-H") {
|
|
3530
|
+
const header = args2[++i];
|
|
3531
|
+
if (header) {
|
|
3532
|
+
const [key, ...valueParts] = header.split(":");
|
|
3533
|
+
headers[key.trim()] = valueParts.join(":").trim();
|
|
3534
|
+
}
|
|
3535
|
+
} else if (args2[i] === "--body" || args2[i] === "-d") {
|
|
3536
|
+
body = args2[++i];
|
|
3537
|
+
}
|
|
3538
|
+
}
|
|
3539
|
+
console.log("");
|
|
3540
|
+
console.log(` ${theme.dim(`${method} ${url}...`)}`);
|
|
3541
|
+
const result = await makeRequest(url, { method, headers, body });
|
|
3542
|
+
process.stdout.write("\x1B[1A\x1B[2K");
|
|
3543
|
+
if (!result.success) {
|
|
3544
|
+
console.log(` ${symbols.cross} ${theme.error(result.error || "Request failed")}`);
|
|
3545
|
+
console.log("");
|
|
3546
|
+
return;
|
|
3547
|
+
}
|
|
3548
|
+
const statusColor = result.statusCode && result.statusCode >= 200 && result.statusCode < 300 ? theme.success : result.statusCode && result.statusCode >= 400 ? theme.error : theme.warning;
|
|
3549
|
+
console.log(` ${statusColor(`${result.statusCode} ${result.statusMessage}`)} ${theme.dim(`(${result.time}ms)`)}`);
|
|
3550
|
+
console.log("");
|
|
3551
|
+
if (result.headers) {
|
|
3552
|
+
const importantHeaders = ["content-type", "content-length", "server", "date"];
|
|
3553
|
+
console.log(` ${theme.dim("Headers:")}`);
|
|
3554
|
+
for (const key of importantHeaders) {
|
|
3555
|
+
if (result.headers[key]) {
|
|
3556
|
+
console.log(` ${theme.secondary(key)}: ${result.headers[key]}`);
|
|
3557
|
+
}
|
|
3558
|
+
}
|
|
3559
|
+
console.log("");
|
|
3560
|
+
}
|
|
3561
|
+
if (result.body && method !== "HEAD") {
|
|
3562
|
+
console.log(` ${theme.dim("Body:")}`);
|
|
3563
|
+
const jsonResult = tryParseJson(result.body);
|
|
3564
|
+
if (jsonResult.isJson && jsonResult.formatted) {
|
|
3565
|
+
const lines = jsonResult.formatted.split("\n");
|
|
3566
|
+
const displayLines = lines.slice(0, 30);
|
|
3567
|
+
for (const line of displayLines) {
|
|
3568
|
+
console.log(` ${theme.primary(line)}`);
|
|
3569
|
+
}
|
|
3570
|
+
if (lines.length > 30) {
|
|
3571
|
+
console.log(` ${theme.dim(`... and ${lines.length - 30} more lines`)}`);
|
|
3572
|
+
}
|
|
3573
|
+
} else {
|
|
3574
|
+
const lines = result.body.split("\n").slice(0, 20);
|
|
3575
|
+
for (const line of lines) {
|
|
3576
|
+
console.log(` ${line.slice(0, 100)}`);
|
|
3577
|
+
}
|
|
3578
|
+
if (result.body.split("\n").length > 20) {
|
|
3579
|
+
console.log(` ${theme.dim("... (truncated)")}`);
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3582
|
+
}
|
|
3583
|
+
console.log("");
|
|
3584
|
+
}
|
|
3585
|
+
});
|
|
3586
|
+
|
|
3587
|
+
// src/handlers/dev/diff.ts
|
|
3588
|
+
import { readFileSync as readFileSync4, existsSync as existsSync6 } from "fs";
|
|
3589
|
+
function diffFiles(file1, file2) {
|
|
3590
|
+
if (!existsSync6(file1)) {
|
|
3591
|
+
return { success: false, lines: [], stats: { additions: 0, deletions: 0, unchanged: 0 }, error: `File not found: ${file1}` };
|
|
3592
|
+
}
|
|
3593
|
+
if (!existsSync6(file2)) {
|
|
3594
|
+
return { success: false, lines: [], stats: { additions: 0, deletions: 0, unchanged: 0 }, error: `File not found: ${file2}` };
|
|
3595
|
+
}
|
|
3596
|
+
try {
|
|
3597
|
+
const content1 = readFileSync4(file1, "utf-8");
|
|
3598
|
+
const content2 = readFileSync4(file2, "utf-8");
|
|
3599
|
+
return diffStrings(content1, content2);
|
|
3600
|
+
} catch (error) {
|
|
3601
|
+
return {
|
|
3602
|
+
success: false,
|
|
3603
|
+
lines: [],
|
|
3604
|
+
stats: { additions: 0, deletions: 0, unchanged: 0 },
|
|
3605
|
+
error: error instanceof Error ? error.message : "Failed to read files"
|
|
3606
|
+
};
|
|
3607
|
+
}
|
|
3608
|
+
}
|
|
3609
|
+
function diffStrings(str1, str2) {
|
|
3610
|
+
const lines1 = str1.split("\n");
|
|
3611
|
+
const lines2 = str2.split("\n");
|
|
3612
|
+
const lcs = computeLCS(lines1, lines2);
|
|
3613
|
+
const diff = buildDiff(lines1, lines2, lcs);
|
|
3614
|
+
let additions = 0;
|
|
3615
|
+
let deletions = 0;
|
|
3616
|
+
let unchanged = 0;
|
|
3617
|
+
for (const line of diff) {
|
|
3618
|
+
if (line.type === "add") additions++;
|
|
3619
|
+
else if (line.type === "remove") deletions++;
|
|
3620
|
+
else if (line.type === "same") unchanged++;
|
|
3621
|
+
}
|
|
3622
|
+
return {
|
|
3623
|
+
success: true,
|
|
3624
|
+
lines: diff,
|
|
3625
|
+
stats: { additions, deletions, unchanged }
|
|
3626
|
+
};
|
|
3627
|
+
}
|
|
3628
|
+
function computeLCS(lines1, lines2) {
|
|
3629
|
+
const m = lines1.length;
|
|
3630
|
+
const n = lines2.length;
|
|
3631
|
+
const dp = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0));
|
|
3632
|
+
for (let i = 1; i <= m; i++) {
|
|
3633
|
+
for (let j = 1; j <= n; j++) {
|
|
3634
|
+
if (lines1[i - 1] === lines2[j - 1]) {
|
|
3635
|
+
dp[i][j] = dp[i - 1][j - 1] + 1;
|
|
3636
|
+
} else {
|
|
3637
|
+
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
|
|
3638
|
+
}
|
|
3639
|
+
}
|
|
3640
|
+
}
|
|
3641
|
+
return dp;
|
|
3642
|
+
}
|
|
3643
|
+
function buildDiff(lines1, lines2, lcs) {
|
|
3644
|
+
const result = [];
|
|
3645
|
+
let i = lines1.length;
|
|
3646
|
+
let j = lines2.length;
|
|
3647
|
+
const temp = [];
|
|
3648
|
+
while (i > 0 || j > 0) {
|
|
3649
|
+
if (i > 0 && j > 0 && lines1[i - 1] === lines2[j - 1]) {
|
|
3650
|
+
temp.push({ type: "same", content: lines1[i - 1], lineNum1: i, lineNum2: j });
|
|
3651
|
+
i--;
|
|
3652
|
+
j--;
|
|
3653
|
+
} else if (j > 0 && (i === 0 || lcs[i][j - 1] >= lcs[i - 1][j])) {
|
|
3654
|
+
temp.push({ type: "add", content: lines2[j - 1], lineNum2: j });
|
|
3655
|
+
j--;
|
|
3656
|
+
} else if (i > 0) {
|
|
3657
|
+
temp.push({ type: "remove", content: lines1[i - 1], lineNum1: i });
|
|
3658
|
+
i--;
|
|
3659
|
+
}
|
|
3660
|
+
}
|
|
3661
|
+
return temp.reverse();
|
|
3662
|
+
}
|
|
3663
|
+
function formatDiffStats(stats) {
|
|
3664
|
+
const parts = [];
|
|
3665
|
+
if (stats.additions > 0) parts.push(`+${stats.additions}`);
|
|
3666
|
+
if (stats.deletions > 0) parts.push(`-${stats.deletions}`);
|
|
3667
|
+
if (stats.unchanged > 0) parts.push(`=${stats.unchanged}`);
|
|
3668
|
+
return parts.join(", ");
|
|
3669
|
+
}
|
|
3670
|
+
|
|
3671
|
+
// src/commands/dev/diff.ts
|
|
3672
|
+
import { basename as basename2 } from "path";
|
|
3673
|
+
registerCommand({
|
|
3674
|
+
name: "diff",
|
|
3675
|
+
description: "Compare two files",
|
|
3676
|
+
usage: "/diff <file1> <file2>",
|
|
3677
|
+
async execute(args2) {
|
|
3678
|
+
if (args2.length < 2) {
|
|
3679
|
+
console.log("");
|
|
3680
|
+
console.log(` ${symbols.sparkle} ${theme.gradient("FILE DIFF")}`);
|
|
3681
|
+
console.log("");
|
|
3682
|
+
console.log(` ${theme.dim("Usage:")} /diff <file1> <file2>`);
|
|
3683
|
+
console.log("");
|
|
3684
|
+
console.log(` ${theme.dim("Example:")}`);
|
|
3685
|
+
console.log(` /diff old.json new.json`);
|
|
3686
|
+
console.log(` /diff config.ts config.backup.ts`);
|
|
3687
|
+
console.log("");
|
|
3688
|
+
return;
|
|
3689
|
+
}
|
|
3690
|
+
const file1 = args2[0];
|
|
3691
|
+
const file2 = args2[1];
|
|
3692
|
+
console.log("");
|
|
3693
|
+
const result = diffFiles(file1, file2);
|
|
3694
|
+
if (!result.success) {
|
|
3695
|
+
console.log(` ${symbols.cross} ${theme.error(result.error || "Diff failed")}`);
|
|
3696
|
+
console.log("");
|
|
3697
|
+
return;
|
|
3698
|
+
}
|
|
3699
|
+
console.log(` ${symbols.sparkle} ${theme.gradient("DIFF")}: ${theme.primary(basename2(file1))} ${theme.dim("\u2192")} ${theme.primary(basename2(file2))}`);
|
|
3700
|
+
console.log(` ${theme.dim(formatDiffStats(result.stats))}`);
|
|
3701
|
+
console.log("");
|
|
3702
|
+
if (result.stats.additions === 0 && result.stats.deletions === 0) {
|
|
3703
|
+
console.log(` ${symbols.check} ${theme.success("Files are identical")}`);
|
|
3704
|
+
console.log("");
|
|
3705
|
+
return;
|
|
3706
|
+
}
|
|
3707
|
+
let contextLines = 3;
|
|
3708
|
+
let lastShownIndex = -contextLines - 1;
|
|
3709
|
+
const linesToShow = [];
|
|
3710
|
+
result.lines.forEach((line, i) => {
|
|
3711
|
+
if (line.type !== "same") {
|
|
3712
|
+
for (let j = Math.max(0, i - contextLines); j <= Math.min(result.lines.length - 1, i + contextLines); j++) {
|
|
3713
|
+
if (!linesToShow.includes(j)) {
|
|
3714
|
+
linesToShow.push(j);
|
|
3715
|
+
}
|
|
3716
|
+
}
|
|
3717
|
+
}
|
|
3718
|
+
});
|
|
3719
|
+
linesToShow.sort((a, b3) => a - b3);
|
|
3720
|
+
for (let i = 0; i < linesToShow.length; i++) {
|
|
3721
|
+
const lineIndex = linesToShow[i];
|
|
3722
|
+
const line = result.lines[lineIndex];
|
|
3723
|
+
if (i > 0 && linesToShow[i] - linesToShow[i - 1] > 1) {
|
|
3724
|
+
console.log(` ${theme.dim("...")}`);
|
|
3725
|
+
}
|
|
3726
|
+
const lineNum = line.lineNum1 || line.lineNum2 || "";
|
|
3727
|
+
const numStr = lineNum.toString().padStart(4);
|
|
3728
|
+
if (line.type === "add") {
|
|
3729
|
+
console.log(` ${theme.success("+")} ${theme.dim(numStr)} ${theme.success(line.content)}`);
|
|
3730
|
+
} else if (line.type === "remove") {
|
|
3731
|
+
console.log(` ${theme.error("-")} ${theme.dim(numStr)} ${theme.error(line.content)}`);
|
|
3732
|
+
} else {
|
|
3733
|
+
console.log(` ${theme.dim(" ")} ${theme.dim(numStr)} ${line.content}`);
|
|
3734
|
+
}
|
|
3735
|
+
}
|
|
3736
|
+
console.log("");
|
|
3737
|
+
}
|
|
3738
|
+
});
|
|
3739
|
+
|
|
2868
3740
|
// src/commands/info/weather.ts
|
|
2869
3741
|
registerCommand({
|
|
2870
3742
|
name: "weather",
|
|
@@ -2903,12 +3775,536 @@ registerCommand({
|
|
|
2903
3775
|
}
|
|
2904
3776
|
});
|
|
2905
3777
|
|
|
3778
|
+
// src/commands/plugin/list.ts
|
|
3779
|
+
async function listPlugins() {
|
|
3780
|
+
await discoverPlugins();
|
|
3781
|
+
const plugins = getDiscoveredPlugins();
|
|
3782
|
+
console.log("");
|
|
3783
|
+
if (plugins.length === 0) {
|
|
3784
|
+
console.log(` ${symbols.info} ${theme.dim("No plugins installed")}`);
|
|
3785
|
+
console.log("");
|
|
3786
|
+
console.log(` ${theme.dim("Install a plugin with:")} ${theme.primary("/plugin install <source>")}`);
|
|
3787
|
+
console.log(` ${theme.dim("Create a new plugin with:")} ${theme.primary("/plugin create")}`);
|
|
3788
|
+
console.log("");
|
|
3789
|
+
return;
|
|
3790
|
+
}
|
|
3791
|
+
console.log(` ${symbols.folder} ${theme.gradient("INSTALLED PLUGINS")} ${theme.dim(`(${plugins.length})`)}`);
|
|
3792
|
+
console.log("");
|
|
3793
|
+
for (const plugin of plugins) {
|
|
3794
|
+
const loaded = isPluginLoaded(plugin.name);
|
|
3795
|
+
const status = loaded ? theme.success("active") : theme.dim("idle");
|
|
3796
|
+
const statusIcon = loaded ? symbols.check : symbols.bullet;
|
|
3797
|
+
console.log(` ${statusIcon} ${theme.primary(plugin.displayName || plugin.name)} ${theme.dim(`v${plugin.version}`)}`);
|
|
3798
|
+
if (plugin.description) {
|
|
3799
|
+
console.log(` ${theme.dim(plugin.description)}`);
|
|
3800
|
+
}
|
|
3801
|
+
console.log(` ${theme.dim("Commands:")} ${plugin.commands.map((c) => theme.accent("/" + c)).join(", ")}`);
|
|
3802
|
+
if (plugin.permissions) {
|
|
3803
|
+
const perms = [];
|
|
3804
|
+
if (plugin.permissions.shell) perms.push("shell");
|
|
3805
|
+
if (plugin.permissions.filesystem) perms.push("fs");
|
|
3806
|
+
if (plugin.permissions.network) perms.push("net");
|
|
3807
|
+
if (perms.length > 0) {
|
|
3808
|
+
console.log(` ${theme.dim("Permissions:")} ${theme.warning(perms.join(", "))}`);
|
|
3809
|
+
}
|
|
3810
|
+
}
|
|
3811
|
+
console.log("");
|
|
3812
|
+
}
|
|
3813
|
+
}
|
|
3814
|
+
|
|
3815
|
+
// src/ui/input.ts
|
|
3816
|
+
async function confirm(message, defaultNo = true, options = {}) {
|
|
3817
|
+
const stdin = options.stdin || process.stdin;
|
|
3818
|
+
const stdout = options.stdout || process.stdout;
|
|
3819
|
+
const suffix = defaultNo ? "[y/N]" : "[Y/n]";
|
|
3820
|
+
stdout.write(`${message} ${theme.dim(suffix)} `);
|
|
3821
|
+
return new Promise((resolve5) => {
|
|
3822
|
+
const isTTY2 = "isTTY" in stdin && stdin.isTTY;
|
|
3823
|
+
const wasRaw = "isRaw" in stdin ? stdin.isRaw : false;
|
|
3824
|
+
if (isTTY2 && stdin.setRawMode) {
|
|
3825
|
+
stdin.setRawMode(true);
|
|
3826
|
+
}
|
|
3827
|
+
stdin.resume();
|
|
3828
|
+
const onData = (data) => {
|
|
3829
|
+
const char = data.toString()[0]?.toLowerCase() || "";
|
|
3830
|
+
if (isTTY2 && stdin.setRawMode) {
|
|
3831
|
+
stdin.setRawMode(wasRaw || false);
|
|
3832
|
+
}
|
|
3833
|
+
stdin.removeListener("data", onData);
|
|
3834
|
+
stdin.pause();
|
|
3835
|
+
if (char === "y") {
|
|
3836
|
+
stdout.write("y\n");
|
|
3837
|
+
resolve5(true);
|
|
3838
|
+
} else if (char === "n") {
|
|
3839
|
+
stdout.write("n\n");
|
|
3840
|
+
resolve5(false);
|
|
3841
|
+
} else if (char === "\r" || char === "\n") {
|
|
3842
|
+
stdout.write(defaultNo ? "n\n" : "y\n");
|
|
3843
|
+
resolve5(!defaultNo);
|
|
3844
|
+
} else if (char === "") {
|
|
3845
|
+
stdout.write("\n");
|
|
3846
|
+
resolve5(false);
|
|
3847
|
+
} else {
|
|
3848
|
+
stdout.write("\n");
|
|
3849
|
+
resolve5(false);
|
|
3850
|
+
}
|
|
3851
|
+
};
|
|
3852
|
+
stdin.once("data", onData);
|
|
3853
|
+
});
|
|
3854
|
+
}
|
|
3855
|
+
async function prompt(message, defaultValue, options = {}) {
|
|
3856
|
+
const stdin = options.stdin || process.stdin;
|
|
3857
|
+
const stdout = options.stdout || process.stdout;
|
|
3858
|
+
const suffix = defaultValue ? ` ${theme.dim(`(${defaultValue})`)}` : "";
|
|
3859
|
+
stdout.write(` ${message}${suffix}: `);
|
|
3860
|
+
return new Promise((resolve5) => {
|
|
3861
|
+
let input = "";
|
|
3862
|
+
const isTTY2 = "isTTY" in stdin && stdin.isTTY;
|
|
3863
|
+
const wasRaw = "isRaw" in stdin ? stdin.isRaw : false;
|
|
3864
|
+
if (isTTY2 && stdin.setRawMode) {
|
|
3865
|
+
stdin.setRawMode(true);
|
|
3866
|
+
}
|
|
3867
|
+
stdin.resume();
|
|
3868
|
+
const onData = (data) => {
|
|
3869
|
+
const chars = data.toString();
|
|
3870
|
+
for (const char of chars) {
|
|
3871
|
+
if (char === "\r" || char === "\n") {
|
|
3872
|
+
if (isTTY2 && stdin.setRawMode) {
|
|
3873
|
+
stdin.setRawMode(wasRaw || false);
|
|
3874
|
+
}
|
|
3875
|
+
stdin.removeListener("data", onData);
|
|
3876
|
+
stdin.pause();
|
|
3877
|
+
stdout.write("\n");
|
|
3878
|
+
resolve5(input.trim() || defaultValue || "");
|
|
3879
|
+
return;
|
|
3880
|
+
} else if (char === "") {
|
|
3881
|
+
if (isTTY2 && stdin.setRawMode) {
|
|
3882
|
+
stdin.setRawMode(wasRaw || false);
|
|
3883
|
+
}
|
|
3884
|
+
stdin.removeListener("data", onData);
|
|
3885
|
+
stdin.pause();
|
|
3886
|
+
stdout.write("\n");
|
|
3887
|
+
resolve5(defaultValue || "");
|
|
3888
|
+
return;
|
|
3889
|
+
} else if (char === "\x7F" || char === "\b") {
|
|
3890
|
+
if (input.length > 0) {
|
|
3891
|
+
input = input.slice(0, -1);
|
|
3892
|
+
stdout.write("\b \b");
|
|
3893
|
+
}
|
|
3894
|
+
} else if (char >= " " && char <= "~") {
|
|
3895
|
+
input += char;
|
|
3896
|
+
stdout.write(char);
|
|
3897
|
+
}
|
|
3898
|
+
}
|
|
3899
|
+
};
|
|
3900
|
+
stdin.on("data", onData);
|
|
3901
|
+
});
|
|
3902
|
+
}
|
|
3903
|
+
|
|
3904
|
+
// src/commands/plugin/install.ts
|
|
3905
|
+
async function installPlugin(args2) {
|
|
3906
|
+
const source = args2[0];
|
|
3907
|
+
if (!source) {
|
|
3908
|
+
console.log(theme.error(` ${symbols.cross} No source specified`));
|
|
3909
|
+
console.log("");
|
|
3910
|
+
console.log(` ${theme.primary("Usage:")} /plugin install <source>`);
|
|
3911
|
+
console.log("");
|
|
3912
|
+
console.log(` ${theme.dim("Examples:")}`);
|
|
3913
|
+
console.log(` ${theme.dim("/plugin install ./my-plugin")}`);
|
|
3914
|
+
console.log(` ${theme.dim("/plugin install zammy-plugin-git")}`);
|
|
3915
|
+
console.log(` ${theme.dim("/plugin install github:user/repo")}`);
|
|
3916
|
+
console.log("");
|
|
3917
|
+
return;
|
|
3918
|
+
}
|
|
3919
|
+
console.log("");
|
|
3920
|
+
console.log(` ${symbols.rocket} ${theme.primary("Installing plugin...")}`);
|
|
3921
|
+
const sourceType = detectSourceType(source);
|
|
3922
|
+
if (sourceType === "unknown") {
|
|
3923
|
+
console.log(theme.error(` ${symbols.cross} Could not determine source type for: ${source}`));
|
|
3924
|
+
return;
|
|
3925
|
+
}
|
|
3926
|
+
console.log(theme.dim(` Source type: ${sourceType}`));
|
|
3927
|
+
let result;
|
|
3928
|
+
switch (sourceType) {
|
|
3929
|
+
case "local":
|
|
3930
|
+
result = await installFromLocal(source);
|
|
3931
|
+
break;
|
|
3932
|
+
case "npm":
|
|
3933
|
+
result = await installFromNpm(source);
|
|
3934
|
+
break;
|
|
3935
|
+
case "github":
|
|
3936
|
+
result = await installFromGithub(source);
|
|
3937
|
+
break;
|
|
3938
|
+
case "git":
|
|
3939
|
+
result = await installFromGit(source);
|
|
3940
|
+
break;
|
|
3941
|
+
default:
|
|
3942
|
+
result = { success: false, error: "Unknown source type" };
|
|
3943
|
+
}
|
|
3944
|
+
if (!result.success) {
|
|
3945
|
+
console.log(theme.error(` ${symbols.cross} Installation failed: ${result.error}`));
|
|
3946
|
+
return;
|
|
3947
|
+
}
|
|
3948
|
+
const manifest = result.manifest;
|
|
3949
|
+
const conflicts = checkConflicts(manifest);
|
|
3950
|
+
if (conflicts.hasConflicts) {
|
|
3951
|
+
console.log("");
|
|
3952
|
+
console.log(theme.warning(` ${symbols.warning} Command conflicts detected:`));
|
|
3953
|
+
for (const conflict of conflicts.conflicts) {
|
|
3954
|
+
console.log(` ${theme.dim("-")} ${conflict}`);
|
|
3955
|
+
}
|
|
3956
|
+
console.log("");
|
|
3957
|
+
const proceed = await confirm(` ${theme.warning("Continue anyway?")}`);
|
|
3958
|
+
if (!proceed) {
|
|
3959
|
+
console.log(theme.dim(" Installation cancelled"));
|
|
3960
|
+
return;
|
|
3961
|
+
}
|
|
3962
|
+
}
|
|
3963
|
+
const permissions = formatPermissions(manifest);
|
|
3964
|
+
if (permissions.length > 0) {
|
|
3965
|
+
console.log("");
|
|
3966
|
+
console.log(theme.warning(` ${symbols.warning} Plugin requests permissions:`));
|
|
3967
|
+
for (const perm of permissions) {
|
|
3968
|
+
console.log(` ${perm}`);
|
|
3969
|
+
}
|
|
3970
|
+
console.log("");
|
|
3971
|
+
}
|
|
3972
|
+
await discoverPlugins();
|
|
3973
|
+
for (const cmdName of manifest.commands) {
|
|
3974
|
+
if (getCommand(cmdName)) continue;
|
|
3975
|
+
const lazyExecute = async (args3) => {
|
|
3976
|
+
const loaded = await loadPlugin(manifest.name);
|
|
3977
|
+
if (!loaded) {
|
|
3978
|
+
console.log(theme.error(` ${symbols.cross} Failed to load plugin '${manifest.name}'`));
|
|
3979
|
+
return;
|
|
3980
|
+
}
|
|
3981
|
+
const realCommand = getCommand(cmdName);
|
|
3982
|
+
if (realCommand && realCommand.execute !== lazyExecute) {
|
|
3983
|
+
await realCommand.execute(args3);
|
|
3984
|
+
} else {
|
|
3985
|
+
console.log(theme.error(` ${symbols.cross} Plugin '${manifest.name}' did not register command '${cmdName}'`));
|
|
3986
|
+
}
|
|
3987
|
+
};
|
|
3988
|
+
registerPluginCommand(
|
|
3989
|
+
{
|
|
3990
|
+
name: cmdName,
|
|
3991
|
+
description: `[${manifest.displayName || manifest.name}] ${manifest.description || "Plugin command"}`,
|
|
3992
|
+
usage: `/${cmdName}`,
|
|
3993
|
+
execute: lazyExecute
|
|
3994
|
+
},
|
|
3995
|
+
manifest.name
|
|
3996
|
+
);
|
|
3997
|
+
}
|
|
3998
|
+
console.log("");
|
|
3999
|
+
console.log(` ${symbols.check} ${theme.success("Plugin installed successfully!")}`);
|
|
4000
|
+
console.log("");
|
|
4001
|
+
console.log(` ${theme.primary(manifest.displayName || manifest.name)} ${theme.dim(`v${manifest.version}`)}`);
|
|
4002
|
+
if (manifest.description) {
|
|
4003
|
+
console.log(` ${theme.dim(manifest.description)}`);
|
|
4004
|
+
}
|
|
4005
|
+
console.log("");
|
|
4006
|
+
console.log(` ${theme.dim("Commands added:")} ${manifest.commands.map((c) => theme.accent("/" + c)).join(", ")}`);
|
|
4007
|
+
console.log("");
|
|
4008
|
+
}
|
|
4009
|
+
|
|
4010
|
+
// src/commands/plugin/remove.ts
|
|
4011
|
+
async function removePluginCommand(args2) {
|
|
4012
|
+
const forceIndex = args2.findIndex((a) => a === "-y" || a === "--yes");
|
|
4013
|
+
const skipConfirm = forceIndex !== -1;
|
|
4014
|
+
if (skipConfirm) {
|
|
4015
|
+
args2.splice(forceIndex, 1);
|
|
4016
|
+
}
|
|
4017
|
+
const name = args2[0];
|
|
4018
|
+
if (!name) {
|
|
4019
|
+
console.log(theme.error(` ${symbols.cross} No plugin name specified`));
|
|
4020
|
+
console.log("");
|
|
4021
|
+
console.log(` ${theme.primary("Usage:")} /plugin remove <name>`);
|
|
4022
|
+
console.log("");
|
|
4023
|
+
await discoverPlugins();
|
|
4024
|
+
const plugins2 = getDiscoveredPlugins();
|
|
4025
|
+
if (plugins2.length > 0) {
|
|
4026
|
+
console.log(` ${theme.dim("Installed plugins:")}`);
|
|
4027
|
+
for (const p of plugins2) {
|
|
4028
|
+
console.log(` ${theme.accent(p.name)}`);
|
|
4029
|
+
}
|
|
4030
|
+
console.log("");
|
|
4031
|
+
}
|
|
4032
|
+
return;
|
|
4033
|
+
}
|
|
4034
|
+
await discoverPlugins();
|
|
4035
|
+
const plugins = getDiscoveredPlugins();
|
|
4036
|
+
const plugin = plugins.find((p) => p.name === name || p.displayName?.toLowerCase() === name.toLowerCase());
|
|
4037
|
+
if (!plugin) {
|
|
4038
|
+
console.log(theme.error(` ${symbols.cross} Plugin '${name}' not found`));
|
|
4039
|
+
console.log("");
|
|
4040
|
+
const similar = plugins.filter(
|
|
4041
|
+
(p) => p.name.includes(name) || name.includes(p.name) || p.displayName?.toLowerCase().includes(name.toLowerCase())
|
|
4042
|
+
);
|
|
4043
|
+
if (similar.length > 0) {
|
|
4044
|
+
console.log(` ${theme.dim("Did you mean:")}`);
|
|
4045
|
+
for (const p of similar) {
|
|
4046
|
+
console.log(` ${theme.accent(p.name)}`);
|
|
4047
|
+
}
|
|
4048
|
+
console.log("");
|
|
4049
|
+
}
|
|
4050
|
+
return;
|
|
4051
|
+
}
|
|
4052
|
+
console.log("");
|
|
4053
|
+
console.log(` ${theme.warning("About to remove:")}`);
|
|
4054
|
+
console.log(` ${theme.primary(plugin.displayName || plugin.name)} ${theme.dim(`v${plugin.version}`)}`);
|
|
4055
|
+
console.log(` ${theme.dim("Commands:")} ${plugin.commands.map((c) => "/" + c).join(", ")}`);
|
|
4056
|
+
console.log("");
|
|
4057
|
+
if (!skipConfirm) {
|
|
4058
|
+
const proceed = await confirm(` ${theme.warning("Remove this plugin?")}`);
|
|
4059
|
+
if (!proceed) {
|
|
4060
|
+
console.log(theme.dim(" Removal cancelled"));
|
|
4061
|
+
return;
|
|
4062
|
+
}
|
|
4063
|
+
}
|
|
4064
|
+
await unloadPlugin(plugin.name);
|
|
4065
|
+
const result = removePlugin(plugin.name);
|
|
4066
|
+
if (!result.success) {
|
|
4067
|
+
console.log(theme.error(` ${symbols.cross} Failed to remove: ${result.error}`));
|
|
4068
|
+
return;
|
|
4069
|
+
}
|
|
4070
|
+
await discoverPlugins();
|
|
4071
|
+
console.log("");
|
|
4072
|
+
console.log(` ${symbols.check} ${theme.success("Plugin removed successfully")}`);
|
|
4073
|
+
console.log("");
|
|
4074
|
+
}
|
|
4075
|
+
|
|
4076
|
+
// src/commands/plugin/create.ts
|
|
4077
|
+
import { existsSync as existsSync7, mkdirSync, writeFileSync as writeFileSync3 } from "fs";
|
|
4078
|
+
import { join as join4, resolve as resolve3 } from "path";
|
|
4079
|
+
function generateManifest(name, displayName, description, commandName) {
|
|
4080
|
+
return JSON.stringify({
|
|
4081
|
+
name,
|
|
4082
|
+
version: "1.0.0",
|
|
4083
|
+
displayName,
|
|
4084
|
+
description,
|
|
4085
|
+
main: "./dist/index.js",
|
|
4086
|
+
commands: [commandName],
|
|
4087
|
+
zammy: {
|
|
4088
|
+
minVersion: "1.3.0"
|
|
4089
|
+
},
|
|
4090
|
+
permissions: {}
|
|
4091
|
+
}, null, 2);
|
|
4092
|
+
}
|
|
4093
|
+
function generatePackageJson(name, description) {
|
|
4094
|
+
return JSON.stringify({
|
|
4095
|
+
name,
|
|
4096
|
+
version: "1.0.0",
|
|
4097
|
+
description,
|
|
4098
|
+
type: "module",
|
|
4099
|
+
main: "dist/index.js",
|
|
4100
|
+
types: "dist/index.d.ts",
|
|
4101
|
+
scripts: {
|
|
4102
|
+
build: "tsc",
|
|
4103
|
+
dev: "tsc --watch"
|
|
4104
|
+
},
|
|
4105
|
+
keywords: ["zammy-plugin", "zammy", "cli", "plugin"],
|
|
4106
|
+
peerDependencies: {
|
|
4107
|
+
zammy: "^1.3.0"
|
|
4108
|
+
},
|
|
4109
|
+
devDependencies: {
|
|
4110
|
+
zammy: "^1.3.0",
|
|
4111
|
+
typescript: "^5.3.0"
|
|
4112
|
+
}
|
|
4113
|
+
}, null, 2);
|
|
4114
|
+
}
|
|
4115
|
+
function generateTsConfig() {
|
|
4116
|
+
return JSON.stringify({
|
|
4117
|
+
compilerOptions: {
|
|
4118
|
+
target: "ES2022",
|
|
4119
|
+
module: "NodeNext",
|
|
4120
|
+
moduleResolution: "NodeNext",
|
|
4121
|
+
outDir: "./dist",
|
|
4122
|
+
rootDir: "./src",
|
|
4123
|
+
strict: true,
|
|
4124
|
+
esModuleInterop: true,
|
|
4125
|
+
skipLibCheck: true,
|
|
4126
|
+
declaration: true
|
|
4127
|
+
},
|
|
4128
|
+
include: ["src/**/*"]
|
|
4129
|
+
}, null, 2);
|
|
4130
|
+
}
|
|
4131
|
+
function generateEntryPoint(commandName, displayName) {
|
|
4132
|
+
return `// ${displayName} - A zammy plugin
|
|
4133
|
+
|
|
4134
|
+
import type { PluginAPI, ZammyPlugin } from 'zammy/plugins';
|
|
4135
|
+
|
|
4136
|
+
const plugin: ZammyPlugin = {
|
|
4137
|
+
activate(api: PluginAPI) {
|
|
4138
|
+
const { theme, symbols } = api.ui;
|
|
4139
|
+
|
|
4140
|
+
api.registerCommand({
|
|
4141
|
+
name: '${commandName}',
|
|
4142
|
+
description: 'My custom command',
|
|
4143
|
+
usage: '/${commandName} [args]',
|
|
4144
|
+
async execute(args: string[]) {
|
|
4145
|
+
console.log('');
|
|
4146
|
+
console.log(\` \${symbols.star} \${theme.gradient('${displayName.toUpperCase()}')}\`);
|
|
4147
|
+
console.log('');
|
|
4148
|
+
console.log(\` \${theme.success('Hello from ${displayName}!')}\`);
|
|
4149
|
+
|
|
4150
|
+
if (args.length > 0) {
|
|
4151
|
+
console.log(\` \${theme.dim('Arguments:')} \${args.join(' ')}\`);
|
|
4152
|
+
}
|
|
4153
|
+
|
|
4154
|
+
console.log('');
|
|
4155
|
+
},
|
|
4156
|
+
});
|
|
4157
|
+
|
|
4158
|
+
api.log.info('Plugin activated!');
|
|
4159
|
+
},
|
|
4160
|
+
|
|
4161
|
+
deactivate() {
|
|
4162
|
+
// Cleanup if needed
|
|
4163
|
+
},
|
|
4164
|
+
};
|
|
4165
|
+
|
|
4166
|
+
export default plugin;
|
|
4167
|
+
`;
|
|
4168
|
+
}
|
|
4169
|
+
function generateReadme(name, displayName, description, commandName) {
|
|
4170
|
+
return `# ${displayName}
|
|
4171
|
+
|
|
4172
|
+
${description}
|
|
4173
|
+
|
|
4174
|
+
## Installation
|
|
4175
|
+
|
|
4176
|
+
\`\`\`bash
|
|
4177
|
+
/plugin install ./${name}
|
|
4178
|
+
\`\`\`
|
|
4179
|
+
|
|
4180
|
+
## Usage
|
|
4181
|
+
|
|
4182
|
+
\`\`\`bash
|
|
4183
|
+
/${commandName} [args]
|
|
4184
|
+
\`\`\`
|
|
4185
|
+
|
|
4186
|
+
## Development
|
|
4187
|
+
|
|
4188
|
+
\`\`\`bash
|
|
4189
|
+
# Build the plugin
|
|
4190
|
+
npm run build
|
|
4191
|
+
|
|
4192
|
+
# Watch for changes
|
|
4193
|
+
npm run dev
|
|
4194
|
+
\`\`\`
|
|
4195
|
+
|
|
4196
|
+
## License
|
|
4197
|
+
|
|
4198
|
+
MIT
|
|
4199
|
+
`;
|
|
4200
|
+
}
|
|
4201
|
+
async function createPlugin(args2) {
|
|
4202
|
+
console.log("");
|
|
4203
|
+
console.log(` ${symbols.sparkle} ${theme.gradient("CREATE NEW PLUGIN")}`);
|
|
4204
|
+
console.log("");
|
|
4205
|
+
let name = args2[0] || "";
|
|
4206
|
+
if (!name) {
|
|
4207
|
+
name = await prompt("Plugin name (e.g., my-plugin)", "zammy-plugin-example");
|
|
4208
|
+
}
|
|
4209
|
+
name = name.toLowerCase().replace(/\s+/g, "-");
|
|
4210
|
+
if (!name.startsWith("zammy-plugin-")) {
|
|
4211
|
+
}
|
|
4212
|
+
const displayName = await prompt("Display name", name.replace(/^zammy-plugin-/, "").replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()));
|
|
4213
|
+
const description = await prompt("Description", "A zammy plugin");
|
|
4214
|
+
const commandName = await prompt("Main command name", name.replace(/^zammy-plugin-/, "").replace(/-/g, ""));
|
|
4215
|
+
const targetDir = resolve3(process.cwd(), name);
|
|
4216
|
+
if (existsSync7(targetDir)) {
|
|
4217
|
+
console.log(theme.error(` ${symbols.cross} Directory already exists: ${name}`));
|
|
4218
|
+
return;
|
|
4219
|
+
}
|
|
4220
|
+
console.log("");
|
|
4221
|
+
console.log(theme.dim(` Creating plugin in ${targetDir}...`));
|
|
4222
|
+
try {
|
|
4223
|
+
mkdirSync(targetDir);
|
|
4224
|
+
mkdirSync(join4(targetDir, "src"));
|
|
4225
|
+
mkdirSync(join4(targetDir, "dist"));
|
|
4226
|
+
writeFileSync3(join4(targetDir, "zammy-plugin.json"), generateManifest(name, displayName, description, commandName));
|
|
4227
|
+
writeFileSync3(join4(targetDir, "package.json"), generatePackageJson(name, description));
|
|
4228
|
+
writeFileSync3(join4(targetDir, "tsconfig.json"), generateTsConfig());
|
|
4229
|
+
writeFileSync3(join4(targetDir, "src", "index.ts"), generateEntryPoint(commandName, displayName));
|
|
4230
|
+
writeFileSync3(join4(targetDir, "README.md"), generateReadme(name, displayName, description, commandName));
|
|
4231
|
+
console.log("");
|
|
4232
|
+
console.log(` ${symbols.check} ${theme.success("Plugin created successfully!")}`);
|
|
4233
|
+
console.log("");
|
|
4234
|
+
console.log(` ${theme.primary("Next steps:")}`);
|
|
4235
|
+
console.log(` ${theme.dim("1.")} cd ${name}`);
|
|
4236
|
+
console.log(` ${theme.dim("2.")} npm install`);
|
|
4237
|
+
console.log(` ${theme.dim("3.")} npm run build`);
|
|
4238
|
+
console.log(` ${theme.dim("4.")} /plugin install ./${name}`);
|
|
4239
|
+
console.log("");
|
|
4240
|
+
console.log(` ${theme.dim("Edit")} ${theme.accent("src/index.ts")} ${theme.dim("to customize your plugin")}`);
|
|
4241
|
+
console.log("");
|
|
4242
|
+
} catch (error) {
|
|
4243
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4244
|
+
console.log(theme.error(` ${symbols.cross} Failed to create plugin: ${message}`));
|
|
4245
|
+
}
|
|
4246
|
+
}
|
|
4247
|
+
|
|
4248
|
+
// src/commands/plugin/index.ts
|
|
4249
|
+
registerCommand({
|
|
4250
|
+
name: "plugin",
|
|
4251
|
+
description: "Manage zammy plugins",
|
|
4252
|
+
usage: "/plugin <list|install|remove|create> [args]",
|
|
4253
|
+
async execute(args2) {
|
|
4254
|
+
const subcommand = args2[0]?.toLowerCase();
|
|
4255
|
+
if (!subcommand || subcommand === "help") {
|
|
4256
|
+
console.log("");
|
|
4257
|
+
console.log(` ${symbols.gear} ${theme.gradient("PLUGIN MANAGER")}`);
|
|
4258
|
+
console.log("");
|
|
4259
|
+
console.log(` ${theme.primary("Usage:")} /plugin <command> [args]`);
|
|
4260
|
+
console.log("");
|
|
4261
|
+
console.log(` ${theme.primary("Commands:")}`);
|
|
4262
|
+
console.log(` ${theme.accent("list")} ${theme.dim("Show installed plugins")}`);
|
|
4263
|
+
console.log(` ${theme.accent("install")} <source> ${theme.dim("Install a plugin")}`);
|
|
4264
|
+
console.log(` ${theme.accent("remove")} <name> ${theme.dim("Remove a plugin")}`);
|
|
4265
|
+
console.log(` ${theme.accent("create")} [name] ${theme.dim("Create a new plugin")}`);
|
|
4266
|
+
console.log("");
|
|
4267
|
+
console.log(` ${theme.primary("Install sources:")}`);
|
|
4268
|
+
console.log(` ${theme.dim("./path/to/plugin")} ${theme.dim("Local directory")}`);
|
|
4269
|
+
console.log(` ${theme.dim("package-name")} ${theme.dim("npm package")}`);
|
|
4270
|
+
console.log(` ${theme.dim("github:user/repo")} ${theme.dim("GitHub repository")}`);
|
|
4271
|
+
console.log(` ${theme.dim("https://...git")} ${theme.dim("Git URL")}`);
|
|
4272
|
+
console.log("");
|
|
4273
|
+
return;
|
|
4274
|
+
}
|
|
4275
|
+
switch (subcommand) {
|
|
4276
|
+
case "list":
|
|
4277
|
+
case "ls":
|
|
4278
|
+
await listPlugins();
|
|
4279
|
+
break;
|
|
4280
|
+
case "install":
|
|
4281
|
+
case "i":
|
|
4282
|
+
case "add":
|
|
4283
|
+
await installPlugin(args2.slice(1));
|
|
4284
|
+
break;
|
|
4285
|
+
case "remove":
|
|
4286
|
+
case "rm":
|
|
4287
|
+
case "uninstall":
|
|
4288
|
+
await removePluginCommand(args2.slice(1));
|
|
4289
|
+
break;
|
|
4290
|
+
case "create":
|
|
4291
|
+
case "new":
|
|
4292
|
+
case "init":
|
|
4293
|
+
await createPlugin(args2.slice(1));
|
|
4294
|
+
break;
|
|
4295
|
+
default:
|
|
4296
|
+
console.log(theme.error(` ${symbols.cross} Unknown subcommand: ${subcommand}`));
|
|
4297
|
+
console.log(theme.dim(` Use '/plugin help' to see available commands`));
|
|
4298
|
+
}
|
|
4299
|
+
}
|
|
4300
|
+
});
|
|
4301
|
+
|
|
2906
4302
|
// src/cli.ts
|
|
2907
4303
|
import { exec, execSync, spawn } from "child_process";
|
|
2908
|
-
import { existsSync as
|
|
2909
|
-
import { resolve as
|
|
4304
|
+
import { existsSync as existsSync8, statSync as statSync2, readFileSync as readFileSync5, readdirSync as readdirSync2, writeFileSync as writeFileSync4, watchFile, unwatchFile } from "fs";
|
|
4305
|
+
import { resolve as resolve4, extname, basename as basename3, join as join5 } from "path";
|
|
2910
4306
|
import { homedir as homedir3, platform as platform2, networkInterfaces } from "os";
|
|
2911
|
-
import
|
|
4307
|
+
import chalk4 from "chalk";
|
|
2912
4308
|
var isWindows = platform2() === "win32";
|
|
2913
4309
|
function translateCommand(cmd) {
|
|
2914
4310
|
if (!isWindows) return cmd;
|
|
@@ -2965,19 +4361,19 @@ function handleCd(args2) {
|
|
|
2965
4361
|
if (!targetPath || targetPath === "~") {
|
|
2966
4362
|
targetPath = homedir3();
|
|
2967
4363
|
} else if (targetPath.startsWith("~/")) {
|
|
2968
|
-
targetPath =
|
|
4364
|
+
targetPath = resolve4(homedir3(), targetPath.slice(2));
|
|
2969
4365
|
} else if (targetPath === "-") {
|
|
2970
4366
|
console.log(theme.dim(process.cwd()));
|
|
2971
4367
|
return;
|
|
2972
4368
|
} else {
|
|
2973
|
-
targetPath =
|
|
4369
|
+
targetPath = resolve4(process.cwd(), targetPath);
|
|
2974
4370
|
}
|
|
2975
|
-
if (!
|
|
4371
|
+
if (!existsSync8(targetPath)) {
|
|
2976
4372
|
console.log(`${miniSlime.sad} ${theme.error(`Directory not found: ${targetPath}`)}`);
|
|
2977
4373
|
return;
|
|
2978
4374
|
}
|
|
2979
4375
|
try {
|
|
2980
|
-
const stats =
|
|
4376
|
+
const stats = statSync2(targetPath);
|
|
2981
4377
|
if (!stats.isDirectory()) {
|
|
2982
4378
|
console.log(`${miniSlime.sad} ${theme.error(`Not a directory: ${targetPath}`)}`);
|
|
2983
4379
|
return;
|
|
@@ -2992,13 +4388,13 @@ function handlePwd() {
|
|
|
2992
4388
|
console.log(theme.primary(process.cwd()));
|
|
2993
4389
|
}
|
|
2994
4390
|
function handleCat(args2) {
|
|
2995
|
-
const filePath =
|
|
2996
|
-
if (!
|
|
4391
|
+
const filePath = resolve4(process.cwd(), args2.trim());
|
|
4392
|
+
if (!existsSync8(filePath)) {
|
|
2997
4393
|
console.log(`${miniSlime.sad} ${theme.error(`File not found: ${args2}`)}`);
|
|
2998
4394
|
return;
|
|
2999
4395
|
}
|
|
3000
4396
|
try {
|
|
3001
|
-
const content =
|
|
4397
|
+
const content = readFileSync5(filePath, "utf-8");
|
|
3002
4398
|
const ext = extname(filePath).toLowerCase();
|
|
3003
4399
|
if ([".js", ".ts", ".jsx", ".tsx", ".json", ".css", ".html", ".py", ".go", ".rs"].includes(ext)) {
|
|
3004
4400
|
console.log(highlightSyntax(content, ext));
|
|
@@ -3015,13 +4411,13 @@ function highlightSyntax(content, ext) {
|
|
|
3015
4411
|
py: ["def", "class", "import", "from", "return", "if", "elif", "else", "for", "while", "try", "except", "with", "as", "True", "False", "None", "and", "or", "not", "in", "is", "lambda", "async", "await"]
|
|
3016
4412
|
};
|
|
3017
4413
|
const kw = ext === ".py" ? keywords.py : keywords.js;
|
|
3018
|
-
return content.split(
|
|
3019
|
-
line = line.replace(/(["'`])(?:(?!\1)[^\\]|\\.)*?\1/g, (match) =>
|
|
3020
|
-
line = line.replace(/(\/\/.*$|#.*$)/g, (match) =>
|
|
3021
|
-
line = line.replace(/\b(\d+\.?\d*)\b/g, (match) =>
|
|
4414
|
+
return content.split(/\r?\n/).map((line) => {
|
|
4415
|
+
line = line.replace(/(["'`])(?:(?!\1)[^\\]|\\.)*?\1/g, (match) => chalk4.hex("#98C379")(match));
|
|
4416
|
+
line = line.replace(/(\/\/.*$|#.*$)/g, (match) => chalk4.hex("#5C6370")(match));
|
|
4417
|
+
line = line.replace(/\b(\d+\.?\d*)\b/g, (match) => chalk4.hex("#D19A66")(match));
|
|
3022
4418
|
kw.forEach((keyword) => {
|
|
3023
4419
|
const regex = new RegExp(`\\b(${keyword})\\b`, "g");
|
|
3024
|
-
line = line.replace(regex,
|
|
4420
|
+
line = line.replace(regex, chalk4.hex("#C678DD")(keyword));
|
|
3025
4421
|
});
|
|
3026
4422
|
return line;
|
|
3027
4423
|
}).join("\n");
|
|
@@ -3086,24 +4482,24 @@ var fileIcons = {
|
|
|
3086
4482
|
"default": { icon: "\u{1F4C4}", color: "#6C7A89" }
|
|
3087
4483
|
};
|
|
3088
4484
|
function formatSize(bytes) {
|
|
3089
|
-
if (bytes === 0) return
|
|
4485
|
+
if (bytes === 0) return chalk4.dim(" 0 B");
|
|
3090
4486
|
const units = ["B", "KB", "MB", "GB", "TB"];
|
|
3091
4487
|
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
3092
4488
|
const size = (bytes / Math.pow(1024, i)).toFixed(i > 0 ? 1 : 0);
|
|
3093
|
-
return
|
|
4489
|
+
return chalk4.hex("#98C379")(size.padStart(5) + " " + units[i].padEnd(2));
|
|
3094
4490
|
}
|
|
3095
4491
|
function handleLs(args2) {
|
|
3096
4492
|
const parts = args2.trim().split(/\s+/).filter(Boolean);
|
|
3097
4493
|
const showAll = parts.some((a) => a === "-a" || a === "-la" || a === "-al");
|
|
3098
4494
|
const showLong = parts.some((a) => a === "-l" || a === "-la" || a === "-al");
|
|
3099
4495
|
const pathArgs = parts.filter((a) => !a.startsWith("-"));
|
|
3100
|
-
const targetPath = pathArgs.length > 0 ?
|
|
3101
|
-
if (!
|
|
4496
|
+
const targetPath = pathArgs.length > 0 ? resolve4(process.cwd(), pathArgs[0]) : process.cwd();
|
|
4497
|
+
if (!existsSync8(targetPath)) {
|
|
3102
4498
|
console.log(theme.error(`Directory not found: ${targetPath}`));
|
|
3103
4499
|
return;
|
|
3104
4500
|
}
|
|
3105
4501
|
try {
|
|
3106
|
-
const entries =
|
|
4502
|
+
const entries = readdirSync2(targetPath, { withFileTypes: true });
|
|
3107
4503
|
const filtered = showAll ? entries : entries.filter((e) => !e.name.startsWith("."));
|
|
3108
4504
|
console.log("");
|
|
3109
4505
|
console.log(theme.dim(` ${targetPath}`));
|
|
@@ -3119,22 +4515,22 @@ function handleLs(args2) {
|
|
|
3119
4515
|
return a.name.localeCompare(b3.name);
|
|
3120
4516
|
});
|
|
3121
4517
|
for (const entry of sorted) {
|
|
3122
|
-
const fullPath =
|
|
4518
|
+
const fullPath = resolve4(targetPath, entry.name);
|
|
3123
4519
|
const isDir = entry.isDirectory();
|
|
3124
4520
|
const ext = isDir ? "dir" : extname(entry.name).toLowerCase();
|
|
3125
4521
|
const iconInfo = fileIcons[ext] || fileIcons["default"];
|
|
3126
4522
|
let line = ` ${iconInfo.icon} `;
|
|
3127
4523
|
if (showLong) {
|
|
3128
4524
|
try {
|
|
3129
|
-
const stats =
|
|
3130
|
-
const size = isDir ?
|
|
4525
|
+
const stats = statSync2(fullPath);
|
|
4526
|
+
const size = isDir ? chalk4.dim(" <DIR>") : formatSize(stats.size);
|
|
3131
4527
|
const date = stats.mtime.toLocaleDateString("en-US", { month: "short", day: "2-digit", year: "numeric" });
|
|
3132
|
-
line +=
|
|
4528
|
+
line += chalk4.dim(date.padEnd(13)) + size + " ";
|
|
3133
4529
|
} catch {
|
|
3134
|
-
line +=
|
|
4530
|
+
line += chalk4.dim(" ") + " ";
|
|
3135
4531
|
}
|
|
3136
4532
|
}
|
|
3137
|
-
const name = isDir ?
|
|
4533
|
+
const name = isDir ? chalk4.hex(iconInfo.color).bold(entry.name + "/") : chalk4.hex(iconInfo.color)(entry.name);
|
|
3138
4534
|
line += name;
|
|
3139
4535
|
console.log(line);
|
|
3140
4536
|
}
|
|
@@ -3148,19 +4544,19 @@ function handleLs(args2) {
|
|
|
3148
4544
|
function handleTree(args2, maxDepth = 3) {
|
|
3149
4545
|
const parts = args2.trim().split(/\s+/).filter(Boolean);
|
|
3150
4546
|
const pathArgs = parts.filter((a) => !a.startsWith("-"));
|
|
3151
|
-
const targetPath = pathArgs.length > 0 ?
|
|
3152
|
-
if (!
|
|
4547
|
+
const targetPath = pathArgs.length > 0 ? resolve4(process.cwd(), pathArgs[0]) : process.cwd();
|
|
4548
|
+
if (!existsSync8(targetPath)) {
|
|
3153
4549
|
console.log(theme.error(`Directory not found: ${targetPath}`));
|
|
3154
4550
|
return;
|
|
3155
4551
|
}
|
|
3156
4552
|
console.log("");
|
|
3157
|
-
console.log(theme.primary(` \u{1F4C1} ${
|
|
4553
|
+
console.log(theme.primary(` \u{1F4C1} ${basename3(targetPath)}/`));
|
|
3158
4554
|
let dirCount = 0;
|
|
3159
4555
|
let fileCount = 0;
|
|
3160
4556
|
function printTree(dir, prefix, depth) {
|
|
3161
4557
|
if (depth > maxDepth) return;
|
|
3162
4558
|
try {
|
|
3163
|
-
const entries =
|
|
4559
|
+
const entries = readdirSync2(dir, { withFileTypes: true }).filter((e) => !e.name.startsWith(".") && !["node_modules", ".git", "dist", "build"].includes(e.name)).sort((a, b3) => {
|
|
3164
4560
|
if (a.isDirectory() && !b3.isDirectory()) return -1;
|
|
3165
4561
|
if (!a.isDirectory() && b3.isDirectory()) return 1;
|
|
3166
4562
|
return a.name.localeCompare(b3.name);
|
|
@@ -3172,11 +4568,11 @@ function handleTree(args2, maxDepth = 3) {
|
|
|
3172
4568
|
const iconInfo = fileIcons[ext] || fileIcons["default"];
|
|
3173
4569
|
if (entry.isDirectory()) {
|
|
3174
4570
|
dirCount++;
|
|
3175
|
-
console.log(theme.dim(prefix + connector) + iconInfo.icon + " " +
|
|
3176
|
-
printTree(
|
|
4571
|
+
console.log(theme.dim(prefix + connector) + iconInfo.icon + " " + chalk4.hex(iconInfo.color).bold(entry.name + "/"));
|
|
4572
|
+
printTree(resolve4(dir, entry.name), prefix + (isLast ? " " : "\u2502 "), depth + 1);
|
|
3177
4573
|
} else {
|
|
3178
4574
|
fileCount++;
|
|
3179
|
-
console.log(theme.dim(prefix + connector) + iconInfo.icon + " " +
|
|
4575
|
+
console.log(theme.dim(prefix + connector) + iconInfo.icon + " " + chalk4.hex(iconInfo.color)(entry.name));
|
|
3180
4576
|
}
|
|
3181
4577
|
});
|
|
3182
4578
|
} catch {
|
|
@@ -3187,18 +4583,18 @@ function handleTree(args2, maxDepth = 3) {
|
|
|
3187
4583
|
console.log(theme.dim(` ${dirCount} directories, ${fileCount} files`));
|
|
3188
4584
|
console.log("");
|
|
3189
4585
|
}
|
|
3190
|
-
var bookmarksFile =
|
|
4586
|
+
var bookmarksFile = join5(homedir3(), ".zammy-bookmarks.json");
|
|
3191
4587
|
function loadBookmarks() {
|
|
3192
4588
|
try {
|
|
3193
|
-
if (
|
|
3194
|
-
return JSON.parse(
|
|
4589
|
+
if (existsSync8(bookmarksFile)) {
|
|
4590
|
+
return JSON.parse(readFileSync5(bookmarksFile, "utf-8"));
|
|
3195
4591
|
}
|
|
3196
4592
|
} catch {
|
|
3197
4593
|
}
|
|
3198
4594
|
return {};
|
|
3199
4595
|
}
|
|
3200
4596
|
function saveBookmarks(bookmarks) {
|
|
3201
|
-
|
|
4597
|
+
writeFileSync4(bookmarksFile, JSON.stringify(bookmarks, null, 2));
|
|
3202
4598
|
}
|
|
3203
4599
|
function handleBookmark(args2) {
|
|
3204
4600
|
const parts = args2.trim().split(/\s+/);
|
|
@@ -3254,7 +4650,7 @@ function handleBookmark(args2) {
|
|
|
3254
4650
|
console.log(theme.primary(" \u{1F4CD} Directory Bookmarks"));
|
|
3255
4651
|
console.log("");
|
|
3256
4652
|
for (const key of keys.sort()) {
|
|
3257
|
-
const exists =
|
|
4653
|
+
const exists = existsSync8(bookmarks[key]);
|
|
3258
4654
|
const status = exists ? theme.success(symbols.check) : theme.error(symbols.cross);
|
|
3259
4655
|
console.log(` ${status} ${theme.primary(key.padEnd(15))} ${theme.dim("\u2192")} ${bookmarks[key]}`);
|
|
3260
4656
|
}
|
|
@@ -3271,10 +4667,10 @@ function handleFind(args2) {
|
|
|
3271
4667
|
function searchDir(dir, depth = 0) {
|
|
3272
4668
|
if (depth > 5 || results.length >= maxResults) return;
|
|
3273
4669
|
try {
|
|
3274
|
-
const entries =
|
|
4670
|
+
const entries = readdirSync2(dir, { withFileTypes: true });
|
|
3275
4671
|
for (const entry of entries) {
|
|
3276
4672
|
if (entry.name.startsWith(".") || ["node_modules", ".git", "dist", "build"].includes(entry.name)) continue;
|
|
3277
|
-
const fullPath =
|
|
4673
|
+
const fullPath = resolve4(dir, entry.name);
|
|
3278
4674
|
const matchPattern = pattern.replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
3279
4675
|
const regex = new RegExp(matchPattern, "i");
|
|
3280
4676
|
if (regex.test(entry.name)) {
|
|
@@ -3298,9 +4694,9 @@ function handleFind(args2) {
|
|
|
3298
4694
|
const relativePath = result.path.replace(searchPath, ".").replace(/\\/g, "/");
|
|
3299
4695
|
const ext = result.isDir ? "dir" : extname(result.path).toLowerCase();
|
|
3300
4696
|
const iconInfo = fileIcons[ext] || fileIcons["default"];
|
|
3301
|
-
const fileName =
|
|
4697
|
+
const fileName = basename3(result.path);
|
|
3302
4698
|
const dirPath = relativePath.slice(0, -fileName.length);
|
|
3303
|
-
console.log(` ${iconInfo.icon} ${theme.dim(dirPath)}${
|
|
4699
|
+
console.log(` ${iconInfo.icon} ${theme.dim(dirPath)}${chalk4.hex(iconInfo.color)(fileName)}${result.isDir ? "/" : ""}`);
|
|
3304
4700
|
}
|
|
3305
4701
|
if (results.length >= maxResults) {
|
|
3306
4702
|
console.log("");
|
|
@@ -3310,8 +4706,8 @@ function handleFind(args2) {
|
|
|
3310
4706
|
console.log("");
|
|
3311
4707
|
}
|
|
3312
4708
|
function handleDu(args2) {
|
|
3313
|
-
const targetPath = args2.trim() ?
|
|
3314
|
-
if (!
|
|
4709
|
+
const targetPath = args2.trim() ? resolve4(process.cwd(), args2.trim()) : process.cwd();
|
|
4710
|
+
if (!existsSync8(targetPath)) {
|
|
3315
4711
|
console.log(theme.error(` Path not found: ${targetPath}`));
|
|
3316
4712
|
return;
|
|
3317
4713
|
}
|
|
@@ -3319,10 +4715,10 @@ function handleDu(args2) {
|
|
|
3319
4715
|
console.log("");
|
|
3320
4716
|
console.log(theme.dim(" Calculating sizes..."));
|
|
3321
4717
|
try {
|
|
3322
|
-
const entries =
|
|
4718
|
+
const entries = readdirSync2(targetPath, { withFileTypes: true });
|
|
3323
4719
|
for (const entry of entries) {
|
|
3324
4720
|
if (entry.name.startsWith(".")) continue;
|
|
3325
|
-
const fullPath =
|
|
4721
|
+
const fullPath = resolve4(targetPath, entry.name);
|
|
3326
4722
|
let size = 0;
|
|
3327
4723
|
let skipped = false;
|
|
3328
4724
|
try {
|
|
@@ -3331,10 +4727,10 @@ function handleDu(args2) {
|
|
|
3331
4727
|
skipped = true;
|
|
3332
4728
|
size = 0;
|
|
3333
4729
|
} else {
|
|
3334
|
-
size =
|
|
4730
|
+
size = getDirSize2(fullPath);
|
|
3335
4731
|
}
|
|
3336
4732
|
} else {
|
|
3337
|
-
size =
|
|
4733
|
+
size = statSync2(fullPath).size;
|
|
3338
4734
|
}
|
|
3339
4735
|
items.push({ name: entry.name, size, isDir: entry.isDirectory(), skipped });
|
|
3340
4736
|
} catch {
|
|
@@ -3348,7 +4744,7 @@ function handleDu(args2) {
|
|
|
3348
4744
|
items.sort((a, b3) => b3.size - a.size);
|
|
3349
4745
|
const totalSize = items.reduce((sum, item) => sum + item.size, 0);
|
|
3350
4746
|
console.log("");
|
|
3351
|
-
console.log(theme.primary(` \u{1F4CA} Disk Usage: ${
|
|
4747
|
+
console.log(theme.primary(` \u{1F4CA} Disk Usage: ${basename3(targetPath)}`));
|
|
3352
4748
|
console.log(theme.dim(` Total: ${formatSizeSimple(totalSize)}`));
|
|
3353
4749
|
console.log("");
|
|
3354
4750
|
const maxItems = 15;
|
|
@@ -3362,10 +4758,10 @@ function handleDu(args2) {
|
|
|
3362
4758
|
const percent = totalSize > 0 ? item.size / totalSize * 100 : 0;
|
|
3363
4759
|
const barWidth = 20;
|
|
3364
4760
|
const filled = Math.round(percent / 100 * barWidth);
|
|
3365
|
-
const bar =
|
|
4761
|
+
const bar = chalk4.hex("#4ECDC4")("\u2588".repeat(filled)) + chalk4.dim("\u2591".repeat(barWidth - filled));
|
|
3366
4762
|
const icon = item.isDir ? "\u{1F4C1}" : "\u{1F4C4}";
|
|
3367
4763
|
const name = item.name.length > 25 ? item.name.slice(0, 22) + "..." : item.name.padEnd(25);
|
|
3368
|
-
console.log(` ${icon} ${name} ${bar} ${formatSizeSimple(item.size).padStart(8)} ${
|
|
4764
|
+
console.log(` ${icon} ${name} ${bar} ${formatSizeSimple(item.size).padStart(8)} ${chalk4.dim(`${percent.toFixed(1)}%`)}`);
|
|
3369
4765
|
}
|
|
3370
4766
|
if (items.length > maxItems) {
|
|
3371
4767
|
console.log(theme.dim(` ... and ${items.length - maxItems} more items`));
|
|
@@ -3377,19 +4773,19 @@ function handleDu(args2) {
|
|
|
3377
4773
|
console.log("");
|
|
3378
4774
|
}
|
|
3379
4775
|
var skipDirs = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", ".next", ".nuxt", "coverage", ".cache", "__pycache__", "venv", ".venv"]);
|
|
3380
|
-
function
|
|
4776
|
+
function getDirSize2(dir, depth = 0, maxDepth = 4) {
|
|
3381
4777
|
if (depth > maxDepth) return 0;
|
|
3382
4778
|
let size = 0;
|
|
3383
4779
|
try {
|
|
3384
|
-
const entries =
|
|
4780
|
+
const entries = readdirSync2(dir, { withFileTypes: true });
|
|
3385
4781
|
for (const entry of entries) {
|
|
3386
4782
|
if (skipDirs.has(entry.name)) continue;
|
|
3387
|
-
const fullPath =
|
|
4783
|
+
const fullPath = resolve4(dir, entry.name);
|
|
3388
4784
|
if (entry.isDirectory()) {
|
|
3389
|
-
size +=
|
|
4785
|
+
size += getDirSize2(fullPath, depth + 1, maxDepth);
|
|
3390
4786
|
} else {
|
|
3391
4787
|
try {
|
|
3392
|
-
size +=
|
|
4788
|
+
size += statSync2(fullPath).size;
|
|
3393
4789
|
} catch {
|
|
3394
4790
|
}
|
|
3395
4791
|
}
|
|
@@ -3419,7 +4815,7 @@ function handleGit(args2) {
|
|
|
3419
4815
|
case "status":
|
|
3420
4816
|
case "s": {
|
|
3421
4817
|
const branch = execSync("git branch --show-current", { encoding: "utf-8", timeout: 5e3 }).trim();
|
|
3422
|
-
console.log(` ${symbols.rocket} ${theme.primary("Branch:")} ${
|
|
4818
|
+
console.log(` ${symbols.rocket} ${theme.primary("Branch:")} ${chalk4.hex("#98C379")(branch)}`);
|
|
3423
4819
|
console.log("");
|
|
3424
4820
|
const status = execSync("git status --porcelain", { encoding: "utf-8", timeout: 5e3 });
|
|
3425
4821
|
if (!status.trim()) {
|
|
@@ -3444,12 +4840,12 @@ function handleGit(args2) {
|
|
|
3444
4840
|
}
|
|
3445
4841
|
if (staged.length > 0) {
|
|
3446
4842
|
console.log(theme.success(" Staged changes:"));
|
|
3447
|
-
staged.forEach((f) => console.log(` ${symbols.check} ${
|
|
4843
|
+
staged.forEach((f) => console.log(` ${symbols.check} ${chalk4.hex("#98C379")(f)}`));
|
|
3448
4844
|
console.log("");
|
|
3449
4845
|
}
|
|
3450
4846
|
if (modified.length > 0) {
|
|
3451
4847
|
console.log(theme.warning(" Modified:"));
|
|
3452
|
-
modified.forEach((f) => console.log(` ${symbols.bullet} ${
|
|
4848
|
+
modified.forEach((f) => console.log(` ${symbols.bullet} ${chalk4.hex("#E5C07B")(f)}`));
|
|
3453
4849
|
console.log("");
|
|
3454
4850
|
}
|
|
3455
4851
|
if (untracked.length > 0) {
|
|
@@ -3463,7 +4859,7 @@ function handleGit(args2) {
|
|
|
3463
4859
|
console.log(theme.dim(" Recent commits:"));
|
|
3464
4860
|
log.split("\n").forEach((line) => {
|
|
3465
4861
|
const [hash, ...msg] = line.split(" ");
|
|
3466
|
-
console.log(` ${
|
|
4862
|
+
console.log(` ${chalk4.hex("#61AFEF")(hash)} ${theme.dim(msg.join(" "))}`);
|
|
3467
4863
|
});
|
|
3468
4864
|
}
|
|
3469
4865
|
break;
|
|
@@ -3475,7 +4871,7 @@ function handleGit(args2) {
|
|
|
3475
4871
|
console.log("");
|
|
3476
4872
|
log.split("\n").forEach((line) => {
|
|
3477
4873
|
const [hash, ...msg] = line.split(" ");
|
|
3478
|
-
console.log(` ${
|
|
4874
|
+
console.log(` ${chalk4.hex("#61AFEF")(hash)} ${msg.join(" ")}`);
|
|
3479
4875
|
});
|
|
3480
4876
|
break;
|
|
3481
4877
|
}
|
|
@@ -3486,7 +4882,7 @@ function handleGit(args2) {
|
|
|
3486
4882
|
console.log("");
|
|
3487
4883
|
branches.split("\n").forEach((line) => {
|
|
3488
4884
|
if (line.startsWith("*")) {
|
|
3489
|
-
console.log(` ${
|
|
4885
|
+
console.log(` ${chalk4.hex("#98C379")(line)}`);
|
|
3490
4886
|
} else {
|
|
3491
4887
|
console.log(` ${theme.dim(line)}`);
|
|
3492
4888
|
}
|
|
@@ -3559,8 +4955,8 @@ function handleClipboard(args2) {
|
|
|
3559
4955
|
}
|
|
3560
4956
|
}
|
|
3561
4957
|
} else if (action === "file" && parts[1]) {
|
|
3562
|
-
const filePath =
|
|
3563
|
-
if (
|
|
4958
|
+
const filePath = resolve4(process.cwd(), parts[1]);
|
|
4959
|
+
if (existsSync8(filePath)) {
|
|
3564
4960
|
try {
|
|
3565
4961
|
const copyCmd = getClipboardCopyCmd();
|
|
3566
4962
|
if (isWindows) {
|
|
@@ -3592,14 +4988,14 @@ function handleClipboard(args2) {
|
|
|
3592
4988
|
console.log("");
|
|
3593
4989
|
}
|
|
3594
4990
|
function handlePretty(args2) {
|
|
3595
|
-
const filePath =
|
|
3596
|
-
if (!
|
|
4991
|
+
const filePath = resolve4(process.cwd(), args2.trim());
|
|
4992
|
+
if (!existsSync8(filePath)) {
|
|
3597
4993
|
console.log(theme.error(` File not found: ${args2}`));
|
|
3598
4994
|
return;
|
|
3599
4995
|
}
|
|
3600
4996
|
console.log("");
|
|
3601
4997
|
try {
|
|
3602
|
-
const content =
|
|
4998
|
+
const content = readFileSync5(filePath, "utf-8");
|
|
3603
4999
|
const ext = extname(filePath).toLowerCase();
|
|
3604
5000
|
if (ext === ".json") {
|
|
3605
5001
|
const parsed = JSON.parse(content);
|
|
@@ -3615,7 +5011,7 @@ function handlePretty(args2) {
|
|
|
3615
5011
|
console.log("");
|
|
3616
5012
|
}
|
|
3617
5013
|
function highlightJson(json) {
|
|
3618
|
-
return json.replace(/"([^"]+)":/g, (_, key) =>
|
|
5014
|
+
return json.replace(/"([^"]+)":/g, (_, key) => chalk4.hex("#E06C75")(`"${key}"`) + ":").replace(/: "([^"]*)"/g, (_, val) => ": " + chalk4.hex("#98C379")(`"${val}"`)).replace(/: (\d+)/g, (_, num) => ": " + chalk4.hex("#D19A66")(num)).replace(/: (true|false)/g, (_, bool) => ": " + chalk4.hex("#56B6C2")(bool)).replace(/: (null)/g, (_, n) => ": " + chalk4.hex("#C678DD")(n));
|
|
3619
5015
|
}
|
|
3620
5016
|
var activeWatcher = null;
|
|
3621
5017
|
function handleWatch(args2) {
|
|
@@ -3646,14 +5042,14 @@ function handleWatch(args2) {
|
|
|
3646
5042
|
console.log("");
|
|
3647
5043
|
return;
|
|
3648
5044
|
}
|
|
3649
|
-
const filePath =
|
|
3650
|
-
if (!
|
|
5045
|
+
const filePath = resolve4(process.cwd(), action);
|
|
5046
|
+
if (!existsSync8(filePath)) {
|
|
3651
5047
|
console.log(theme.error(` File not found: ${action}`));
|
|
3652
5048
|
console.log("");
|
|
3653
5049
|
return;
|
|
3654
5050
|
}
|
|
3655
5051
|
try {
|
|
3656
|
-
const stats =
|
|
5052
|
+
const stats = statSync2(filePath);
|
|
3657
5053
|
if (stats.isDirectory()) {
|
|
3658
5054
|
console.log(theme.error(` Cannot watch a directory: ${action}`));
|
|
3659
5055
|
console.log(theme.dim(" Please specify a file path"));
|
|
@@ -3669,13 +5065,13 @@ function handleWatch(args2) {
|
|
|
3669
5065
|
unwatchFile(activeWatcher);
|
|
3670
5066
|
}
|
|
3671
5067
|
activeWatcher = filePath;
|
|
3672
|
-
let lastSize =
|
|
5068
|
+
let lastSize = statSync2(filePath).size;
|
|
3673
5069
|
console.log(` ${symbols.info} ${theme.primary("Watching:")} ${filePath}`);
|
|
3674
5070
|
console.log(theme.dim(' (Type "!watch stop" to stop watching)'));
|
|
3675
5071
|
console.log("");
|
|
3676
5072
|
try {
|
|
3677
|
-
const content =
|
|
3678
|
-
const lines = content.split(
|
|
5073
|
+
const content = readFileSync5(filePath, "utf-8");
|
|
5074
|
+
const lines = content.split(/\r?\n/).slice(-10);
|
|
3679
5075
|
lines.forEach((line) => console.log(theme.dim(line)));
|
|
3680
5076
|
} catch {
|
|
3681
5077
|
console.log(theme.dim(" (Unable to read initial content)"));
|
|
@@ -3683,12 +5079,12 @@ function handleWatch(args2) {
|
|
|
3683
5079
|
watchFile(filePath, { interval: 500 }, (curr, prev) => {
|
|
3684
5080
|
if (curr.size > lastSize) {
|
|
3685
5081
|
try {
|
|
3686
|
-
const newContent =
|
|
3687
|
-
const allLines = newContent.split(
|
|
5082
|
+
const newContent = readFileSync5(filePath, "utf-8");
|
|
5083
|
+
const allLines = newContent.split(/\r?\n/);
|
|
3688
5084
|
const oldLines = Math.floor(prev.size / 50);
|
|
3689
5085
|
const newLines = allLines.slice(-Math.max(1, allLines.length - oldLines));
|
|
3690
5086
|
newLines.forEach((line) => {
|
|
3691
|
-
if (line.trim()) console.log(
|
|
5087
|
+
if (line.trim()) console.log(chalk4.hex("#98C379")(line));
|
|
3692
5088
|
});
|
|
3693
5089
|
} catch {
|
|
3694
5090
|
}
|
|
@@ -3701,7 +5097,7 @@ function handleServe(args2) {
|
|
|
3701
5097
|
console.log("");
|
|
3702
5098
|
console.log(` ${symbols.rocket} ${theme.primary("Starting HTTP server...")}`);
|
|
3703
5099
|
console.log(` ${theme.dim("Serving:")} ${process.cwd()}`);
|
|
3704
|
-
console.log(` ${theme.dim("URL:")} ${
|
|
5100
|
+
console.log(` ${theme.dim("URL:")} ${chalk4.hex("#61AFEF")(`http://localhost:${port}`)}`);
|
|
3705
5101
|
console.log("");
|
|
3706
5102
|
console.log(theme.dim(" Press Ctrl+C to stop"));
|
|
3707
5103
|
console.log("");
|
|
@@ -3732,7 +5128,7 @@ function handlePs() {
|
|
|
3732
5128
|
const name = parts[0].slice(0, 28).padEnd(30);
|
|
3733
5129
|
const pid = parts[1].padStart(8);
|
|
3734
5130
|
const mem = parts[4];
|
|
3735
|
-
console.log(` ${name}${pid} ${
|
|
5131
|
+
console.log(` ${name}${pid} ${chalk4.hex("#98C379")(mem)}`);
|
|
3736
5132
|
}
|
|
3737
5133
|
});
|
|
3738
5134
|
} else {
|
|
@@ -3759,7 +5155,7 @@ function handleEnv(args2) {
|
|
|
3759
5155
|
filtered.slice(0, maxShow).forEach((key) => {
|
|
3760
5156
|
const value = env[key] || "";
|
|
3761
5157
|
const displayValue = value.length > 50 ? value.slice(0, 47) + "..." : value;
|
|
3762
|
-
console.log(` ${
|
|
5158
|
+
console.log(` ${chalk4.hex("#E06C75")(key.padEnd(25))} ${theme.dim("=")} ${displayValue}`);
|
|
3763
5159
|
});
|
|
3764
5160
|
if (filtered.length > maxShow) {
|
|
3765
5161
|
console.log(theme.dim(` ... and ${filtered.length - maxShow} more`));
|
|
@@ -3788,7 +5184,7 @@ function handleIp() {
|
|
|
3788
5184
|
if (localIps.length === 0) {
|
|
3789
5185
|
console.log(` ${theme.dim("(No network interfaces found)")}`);
|
|
3790
5186
|
} else {
|
|
3791
|
-
localIps.forEach((ip) => console.log(` ${
|
|
5187
|
+
localIps.forEach((ip) => console.log(` ${chalk4.hex("#98C379")(ip)}`));
|
|
3792
5188
|
}
|
|
3793
5189
|
console.log("");
|
|
3794
5190
|
console.log(theme.dim(" Public IP:"));
|
|
@@ -3803,7 +5199,7 @@ function handleIp() {
|
|
|
3803
5199
|
throw new Error("curl not available");
|
|
3804
5200
|
}
|
|
3805
5201
|
}
|
|
3806
|
-
console.log(` ${
|
|
5202
|
+
console.log(` ${chalk4.hex("#61AFEF")(result)}`);
|
|
3807
5203
|
} catch {
|
|
3808
5204
|
console.log(` ${theme.dim("(Could not fetch - requires curl or internet)")}`);
|
|
3809
5205
|
}
|
|
@@ -3820,21 +5216,21 @@ function handleEpoch(args2) {
|
|
|
3820
5216
|
if (!input || input === "now") {
|
|
3821
5217
|
const now = /* @__PURE__ */ new Date();
|
|
3822
5218
|
console.log(` ${theme.dim("Current Time:")}`);
|
|
3823
|
-
console.log(` ${
|
|
3824
|
-
console.log(` ${
|
|
3825
|
-
console.log(` ${
|
|
5219
|
+
console.log(` ${chalk4.hex("#98C379")(now.toISOString())}`);
|
|
5220
|
+
console.log(` ${chalk4.hex("#61AFEF")(Math.floor(now.getTime() / 1e3).toString())} ${theme.dim("(Unix seconds)")}`);
|
|
5221
|
+
console.log(` ${chalk4.hex("#E5C07B")(now.getTime().toString())} ${theme.dim("(Unix milliseconds)")}`);
|
|
3826
5222
|
} else if (/^\d{10,13}$/.test(input)) {
|
|
3827
5223
|
const ms = input.length === 10 ? parseInt(input) * 1e3 : parseInt(input);
|
|
3828
5224
|
const date = new Date(ms);
|
|
3829
|
-
console.log(` ${theme.dim("Epoch:")} ${
|
|
3830
|
-
console.log(` ${theme.dim("Date:")} ${
|
|
3831
|
-
console.log(` ${
|
|
5225
|
+
console.log(` ${theme.dim("Epoch:")} ${chalk4.hex("#E5C07B")(input)}`);
|
|
5226
|
+
console.log(` ${theme.dim("Date:")} ${chalk4.hex("#98C379")(date.toISOString())}`);
|
|
5227
|
+
console.log(` ${chalk4.hex("#98C379")(date.toLocaleString())}`);
|
|
3832
5228
|
} else {
|
|
3833
5229
|
const date = new Date(input);
|
|
3834
5230
|
if (!isNaN(date.getTime())) {
|
|
3835
|
-
console.log(` ${theme.dim("Date:")} ${
|
|
3836
|
-
console.log(` ${theme.dim("Unix:")} ${
|
|
3837
|
-
console.log(` ${
|
|
5231
|
+
console.log(` ${theme.dim("Date:")} ${chalk4.hex("#98C379")(input)}`);
|
|
5232
|
+
console.log(` ${theme.dim("Unix:")} ${chalk4.hex("#61AFEF")(Math.floor(date.getTime() / 1e3).toString())} ${theme.dim("(seconds)")}`);
|
|
5233
|
+
console.log(` ${chalk4.hex("#E5C07B")(date.getTime().toString())} ${theme.dim("(milliseconds)")}`);
|
|
3838
5234
|
} else {
|
|
3839
5235
|
console.log(theme.error(` Cannot parse: ${input}`));
|
|
3840
5236
|
console.log(theme.dim(' Examples: epoch now, epoch 1703788800, epoch "2024-01-01"'));
|
|
@@ -3858,7 +5254,7 @@ async function handleHttp(args2) {
|
|
|
3858
5254
|
return;
|
|
3859
5255
|
}
|
|
3860
5256
|
const fullUrl = url.startsWith("http") ? url : `https://${url}`;
|
|
3861
|
-
console.log(` ${symbols.rocket} ${theme.dim(method)} ${
|
|
5257
|
+
console.log(` ${symbols.rocket} ${theme.dim(method)} ${chalk4.hex("#61AFEF")(fullUrl)}`);
|
|
3862
5258
|
console.log("");
|
|
3863
5259
|
try {
|
|
3864
5260
|
let result;
|
|
@@ -3908,22 +5304,22 @@ function handleDiff(args2) {
|
|
|
3908
5304
|
console.log("");
|
|
3909
5305
|
return;
|
|
3910
5306
|
}
|
|
3911
|
-
const path1 =
|
|
3912
|
-
const path2 =
|
|
3913
|
-
if (!
|
|
5307
|
+
const path1 = resolve4(process.cwd(), file1);
|
|
5308
|
+
const path2 = resolve4(process.cwd(), file2);
|
|
5309
|
+
if (!existsSync8(path1)) {
|
|
3914
5310
|
console.log(theme.error(` File not found: ${file1}`));
|
|
3915
5311
|
console.log("");
|
|
3916
5312
|
return;
|
|
3917
5313
|
}
|
|
3918
|
-
if (!
|
|
5314
|
+
if (!existsSync8(path2)) {
|
|
3919
5315
|
console.log(theme.error(` File not found: ${file2}`));
|
|
3920
5316
|
console.log("");
|
|
3921
5317
|
return;
|
|
3922
5318
|
}
|
|
3923
5319
|
try {
|
|
3924
|
-
const content1 =
|
|
3925
|
-
const content2 =
|
|
3926
|
-
console.log(theme.primary(` Comparing: ${
|
|
5320
|
+
const content1 = readFileSync5(path1, "utf-8").split(/\r?\n/);
|
|
5321
|
+
const content2 = readFileSync5(path2, "utf-8").split(/\r?\n/);
|
|
5322
|
+
console.log(theme.primary(` Comparing: ${basename3(file1)} \u2194 ${basename3(file2)}`));
|
|
3927
5323
|
console.log("");
|
|
3928
5324
|
const maxLines = Math.max(content1.length, content2.length);
|
|
3929
5325
|
let differences = 0;
|
|
@@ -3932,8 +5328,8 @@ function handleDiff(args2) {
|
|
|
3932
5328
|
const line2 = content2[i] || "";
|
|
3933
5329
|
if (line1 !== line2) {
|
|
3934
5330
|
differences++;
|
|
3935
|
-
console.log(
|
|
3936
|
-
console.log(
|
|
5331
|
+
console.log(chalk4.hex("#E06C75")(` - ${(i + 1).toString().padStart(4)}: ${line1.slice(0, 70)}`));
|
|
5332
|
+
console.log(chalk4.hex("#98C379")(` + ${(i + 1).toString().padStart(4)}: ${line2.slice(0, 70)}`));
|
|
3937
5333
|
console.log("");
|
|
3938
5334
|
}
|
|
3939
5335
|
}
|
|
@@ -3950,18 +5346,18 @@ function handleDiff(args2) {
|
|
|
3950
5346
|
}
|
|
3951
5347
|
console.log("");
|
|
3952
5348
|
}
|
|
3953
|
-
var aliasesFile =
|
|
5349
|
+
var aliasesFile = join5(homedir3(), ".zammy-aliases.json");
|
|
3954
5350
|
function loadAliases() {
|
|
3955
5351
|
try {
|
|
3956
|
-
if (
|
|
3957
|
-
return JSON.parse(
|
|
5352
|
+
if (existsSync8(aliasesFile)) {
|
|
5353
|
+
return JSON.parse(readFileSync5(aliasesFile, "utf-8"));
|
|
3958
5354
|
}
|
|
3959
5355
|
} catch {
|
|
3960
5356
|
}
|
|
3961
5357
|
return {};
|
|
3962
5358
|
}
|
|
3963
5359
|
function saveAliases(aliases) {
|
|
3964
|
-
|
|
5360
|
+
writeFileSync4(aliasesFile, JSON.stringify(aliases, null, 2));
|
|
3965
5361
|
}
|
|
3966
5362
|
function handleAlias(args2) {
|
|
3967
5363
|
const parts = args2.trim().split(/\s+/);
|
|
@@ -4065,8 +5461,8 @@ function handleGrep(args2) {
|
|
|
4065
5461
|
function searchFile(filePath) {
|
|
4066
5462
|
if (results.length >= maxResults) return;
|
|
4067
5463
|
try {
|
|
4068
|
-
const content =
|
|
4069
|
-
const lines = content.split(
|
|
5464
|
+
const content = readFileSync5(filePath, "utf-8");
|
|
5465
|
+
const lines = content.split(/\r?\n/);
|
|
4070
5466
|
lines.forEach((line, index) => {
|
|
4071
5467
|
if (results.length >= maxResults) return;
|
|
4072
5468
|
if (regex.test(line)) {
|
|
@@ -4083,11 +5479,11 @@ function handleGrep(args2) {
|
|
|
4083
5479
|
function searchDir(dir, depth = 0) {
|
|
4084
5480
|
if (depth > 4 || results.length >= maxResults) return;
|
|
4085
5481
|
try {
|
|
4086
|
-
const entries =
|
|
5482
|
+
const entries = readdirSync2(dir, { withFileTypes: true });
|
|
4087
5483
|
for (const entry of entries) {
|
|
4088
5484
|
if (results.length >= maxResults) break;
|
|
4089
5485
|
if (entry.name.startsWith(".") || ["node_modules", ".git", "dist", "build"].includes(entry.name)) continue;
|
|
4090
|
-
const fullPath =
|
|
5486
|
+
const fullPath = resolve4(dir, entry.name);
|
|
4091
5487
|
if (entry.isDirectory()) {
|
|
4092
5488
|
searchDir(fullPath, depth + 1);
|
|
4093
5489
|
} else {
|
|
@@ -4110,9 +5506,9 @@ function handleGrep(args2) {
|
|
|
4110
5506
|
for (const result of results) {
|
|
4111
5507
|
const highlightedContent = result.content.replace(
|
|
4112
5508
|
regex,
|
|
4113
|
-
(match) =>
|
|
5509
|
+
(match) => chalk4.hex("#FF6B6B").bold(match)
|
|
4114
5510
|
);
|
|
4115
|
-
console.log(` ${theme.dim(result.file)}:${
|
|
5511
|
+
console.log(` ${theme.dim(result.file)}:${chalk4.hex("#61AFEF")(result.line)}`);
|
|
4116
5512
|
console.log(` ${highlightedContent}`);
|
|
4117
5513
|
console.log("");
|
|
4118
5514
|
}
|
|
@@ -4123,30 +5519,30 @@ function handleGrep(args2) {
|
|
|
4123
5519
|
console.log("");
|
|
4124
5520
|
}
|
|
4125
5521
|
function handleWc(args2) {
|
|
4126
|
-
const filePath =
|
|
5522
|
+
const filePath = resolve4(process.cwd(), args2.trim());
|
|
4127
5523
|
console.log("");
|
|
4128
5524
|
if (!args2.trim()) {
|
|
4129
5525
|
console.log(theme.error(" Usage: wc <file>"));
|
|
4130
5526
|
console.log("");
|
|
4131
5527
|
return;
|
|
4132
5528
|
}
|
|
4133
|
-
if (!
|
|
5529
|
+
if (!existsSync8(filePath)) {
|
|
4134
5530
|
console.log(theme.error(` File not found: ${args2}`));
|
|
4135
5531
|
console.log("");
|
|
4136
5532
|
return;
|
|
4137
5533
|
}
|
|
4138
5534
|
try {
|
|
4139
|
-
const content =
|
|
4140
|
-
const lines = content.split(
|
|
5535
|
+
const content = readFileSync5(filePath, "utf-8");
|
|
5536
|
+
const lines = content.split(/\r?\n/).length;
|
|
4141
5537
|
const words = content.split(/\s+/).filter((w) => w.length > 0).length;
|
|
4142
5538
|
const chars = content.length;
|
|
4143
5539
|
const bytes = Buffer.byteLength(content, "utf-8");
|
|
4144
|
-
console.log(theme.primary(` \u{1F4CA} ${
|
|
5540
|
+
console.log(theme.primary(` \u{1F4CA} ${basename3(args2)}`));
|
|
4145
5541
|
console.log("");
|
|
4146
|
-
console.log(` ${
|
|
4147
|
-
console.log(` ${
|
|
4148
|
-
console.log(` ${
|
|
4149
|
-
console.log(` ${
|
|
5542
|
+
console.log(` ${chalk4.hex("#61AFEF")(lines.toLocaleString().padStart(8))} ${theme.dim("lines")}`);
|
|
5543
|
+
console.log(` ${chalk4.hex("#98C379")(words.toLocaleString().padStart(8))} ${theme.dim("words")}`);
|
|
5544
|
+
console.log(` ${chalk4.hex("#E5C07B")(chars.toLocaleString().padStart(8))} ${theme.dim("characters")}`);
|
|
5545
|
+
console.log(` ${chalk4.hex("#C678DD")(bytes.toLocaleString().padStart(8))} ${theme.dim("bytes")}`);
|
|
4150
5546
|
} catch {
|
|
4151
5547
|
console.log(theme.error(" Failed to read file"));
|
|
4152
5548
|
}
|
|
@@ -4166,19 +5562,19 @@ function handleHead(args2) {
|
|
|
4166
5562
|
console.log("");
|
|
4167
5563
|
return;
|
|
4168
5564
|
}
|
|
4169
|
-
const fullPath =
|
|
4170
|
-
if (!
|
|
5565
|
+
const fullPath = resolve4(process.cwd(), filePath);
|
|
5566
|
+
if (!existsSync8(fullPath)) {
|
|
4171
5567
|
console.log(theme.error(` File not found: ${filePath}`));
|
|
4172
5568
|
console.log("");
|
|
4173
5569
|
return;
|
|
4174
5570
|
}
|
|
4175
5571
|
try {
|
|
4176
|
-
const content =
|
|
4177
|
-
const fileLines = content.split(
|
|
4178
|
-
console.log(theme.dim(` First ${lines} lines of ${
|
|
5572
|
+
const content = readFileSync5(fullPath, "utf-8");
|
|
5573
|
+
const fileLines = content.split(/\r?\n/).slice(0, lines);
|
|
5574
|
+
console.log(theme.dim(` First ${lines} lines of ${basename3(filePath)}:`));
|
|
4179
5575
|
console.log("");
|
|
4180
5576
|
fileLines.forEach((line, i) => {
|
|
4181
|
-
console.log(` ${
|
|
5577
|
+
console.log(` ${chalk4.dim((i + 1).toString().padStart(4))} ${line}`);
|
|
4182
5578
|
});
|
|
4183
5579
|
} catch {
|
|
4184
5580
|
console.log(theme.error(" Failed to read file"));
|
|
@@ -4380,19 +5776,19 @@ async function parseAndExecute(input) {
|
|
|
4380
5776
|
}
|
|
4381
5777
|
|
|
4382
5778
|
// src/index.ts
|
|
4383
|
-
import { readdirSync as
|
|
5779
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync6 } from "fs";
|
|
4384
5780
|
import { fileURLToPath } from "url";
|
|
4385
|
-
import { dirname, join as
|
|
4386
|
-
import
|
|
5781
|
+
import { dirname, join as join6 } from "path";
|
|
5782
|
+
import chalk5 from "chalk";
|
|
4387
5783
|
var SLIME_COLOR = "#9B59B6";
|
|
4388
5784
|
var EYE_COLOR = "#1A1A2E";
|
|
4389
5785
|
var MIN_WIDTH_FOR_IDLE = 40;
|
|
4390
5786
|
var MIN_WIDTH_FOR_MENU = 50;
|
|
4391
5787
|
var miniSlimeFrames = [
|
|
4392
5788
|
// Open eyes
|
|
4393
|
-
|
|
5789
|
+
chalk5.hex(SLIME_COLOR)("(") + chalk5.hex(EYE_COLOR)("\u25CF") + chalk5.hex(SLIME_COLOR)("\u1D17") + chalk5.hex(EYE_COLOR)("\u25CF") + chalk5.hex(SLIME_COLOR)(")"),
|
|
4394
5790
|
// Blink (closed eyes)
|
|
4395
|
-
|
|
5791
|
+
chalk5.hex(SLIME_COLOR)("(") + chalk5.hex(EYE_COLOR)("\u2500") + chalk5.hex(SLIME_COLOR)("\u1D17") + chalk5.hex(EYE_COLOR)("\u2500") + chalk5.hex(SLIME_COLOR)(")")
|
|
4396
5792
|
];
|
|
4397
5793
|
var idleAnimationInterval = null;
|
|
4398
5794
|
var isUserTyping = false;
|
|
@@ -4469,8 +5865,8 @@ if (args.includes("--version") || args.includes("-v")) {
|
|
|
4469
5865
|
try {
|
|
4470
5866
|
const __filename = fileURLToPath(import.meta.url);
|
|
4471
5867
|
const __dirname = dirname(__filename);
|
|
4472
|
-
const pkgPath =
|
|
4473
|
-
const pkg = JSON.parse(
|
|
5868
|
+
const pkgPath = join6(__dirname, "..", "package.json");
|
|
5869
|
+
const pkg = JSON.parse(readFileSync6(pkgPath, "utf-8"));
|
|
4474
5870
|
console.log(`zammy v${pkg.version}`);
|
|
4475
5871
|
} catch {
|
|
4476
5872
|
console.log("zammy v1.0.0");
|
|
@@ -4551,9 +5947,9 @@ var SHELL_COMMANDS = [
|
|
|
4551
5947
|
{ name: "mv", description: "Move files" }
|
|
4552
5948
|
];
|
|
4553
5949
|
function getFilteredCommands(filter) {
|
|
4554
|
-
const
|
|
4555
|
-
if (!filter) return
|
|
4556
|
-
return
|
|
5950
|
+
const commands = getAllCommands().map((c) => ({ name: c.name, description: c.description }));
|
|
5951
|
+
if (!filter) return commands;
|
|
5952
|
+
return commands.filter((c) => c.name.toLowerCase().startsWith(filter.toLowerCase()));
|
|
4557
5953
|
}
|
|
4558
5954
|
function getFilteredShellCommands(filter) {
|
|
4559
5955
|
if (!filter) return SHELL_COMMANDS;
|
|
@@ -4684,14 +6080,14 @@ function navigateMenu(direction, currentLine) {
|
|
|
4684
6080
|
renderMenu(currentLine);
|
|
4685
6081
|
}
|
|
4686
6082
|
function completer(line) {
|
|
4687
|
-
const
|
|
6083
|
+
const commands = getAllCommands().map((c) => "/" + c.name);
|
|
4688
6084
|
if (line.startsWith("/")) {
|
|
4689
6085
|
const input = line.toLowerCase();
|
|
4690
6086
|
if (input.startsWith("/asciiart ")) {
|
|
4691
6087
|
const afterCommand = line.slice("/asciiart ".length);
|
|
4692
6088
|
const searchTerm = afterCommand.startsWith("@") ? afterCommand.slice(1) : afterCommand;
|
|
4693
6089
|
try {
|
|
4694
|
-
const files =
|
|
6090
|
+
const files = readdirSync3(process.cwd());
|
|
4695
6091
|
const imageFiles = files.filter((f) => {
|
|
4696
6092
|
const ext = f.toLowerCase().slice(f.lastIndexOf("."));
|
|
4697
6093
|
return IMAGE_EXTENSIONS.includes(ext);
|
|
@@ -4705,7 +6101,7 @@ function completer(line) {
|
|
|
4705
6101
|
return [[], line];
|
|
4706
6102
|
}
|
|
4707
6103
|
}
|
|
4708
|
-
const matches =
|
|
6104
|
+
const matches = commands.filter((c) => c.toLowerCase().startsWith(input));
|
|
4709
6105
|
return [matches.length ? matches : [], line];
|
|
4710
6106
|
}
|
|
4711
6107
|
if (line.startsWith("!")) {
|
|
@@ -4721,6 +6117,7 @@ async function main() {
|
|
|
4721
6117
|
console.log(theme.dim("For full features, run in a proper terminal or use: zammy --simple\n"));
|
|
4722
6118
|
}
|
|
4723
6119
|
await displayBanner(isSimpleMode);
|
|
6120
|
+
await initPluginLoader();
|
|
4724
6121
|
const rl = readline.createInterface({
|
|
4725
6122
|
input: process.stdin,
|
|
4726
6123
|
output: process.stdout,
|