zammy 1.3.0 → 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 +1 -1
- package/dist/chunk-LLLEINP6.js +1229 -0
- package/dist/index.js +546 -1367
- package/dist/plugins.d.ts +168 -0
- package/dist/plugins.js +47 -0
- package/package.json +12 -1
- package/packages/plugins/docker/dist/index.d.ts +2 -44
- package/packages/plugins/docker/dist/index.d.ts.map +1 -1
- package/packages/plugins/docker/dist/index.js.map +1 -1
- package/packages/plugins/docker/package.json +5 -1
- package/packages/plugins/faker/dist/index.d.ts +2 -41
- package/packages/plugins/faker/dist/index.d.ts.map +1 -1
- package/packages/plugins/faker/dist/index.js.map +1 -1
- package/packages/plugins/faker/package.json +5 -1
- package/packages/plugins/network/dist/index.d.ts +2 -43
- package/packages/plugins/network/dist/index.d.ts.map +1 -1
- package/packages/plugins/network/dist/index.js +1 -2
- package/packages/plugins/network/dist/index.js.map +1 -1
- package/packages/plugins/network/package.json +5 -1
- package/packages/plugins/port/dist/index.d.ts +2 -45
- package/packages/plugins/port/dist/index.d.ts.map +1 -1
- package/packages/plugins/port/dist/index.js.map +1 -1
- package/packages/plugins/port/package.json +5 -1
- package/packages/plugins/tsconfig.base.json +17 -0
package/dist/index.js
CHANGED
|
@@ -1,244 +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
|
-
import * as
|
|
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 progressBar = (percent, width = 30, showPercent = true) => {
|
|
185
|
-
const filled = Math.round(percent / 100 * width);
|
|
186
|
-
const empty = width - filled;
|
|
187
|
-
let color = theme.success;
|
|
188
|
-
if (percent > 70) color = theme.warning;
|
|
189
|
-
if (percent > 90) color = theme.error;
|
|
190
|
-
const bar = color("\u2588".repeat(filled)) + theme.dim("\u2591".repeat(empty));
|
|
191
|
-
return showPercent ? `${bar} ${percent.toFixed(0)}%` : bar;
|
|
192
|
-
};
|
|
193
|
-
var bubble = {
|
|
194
|
-
say: (text, width = 50) => {
|
|
195
|
-
const lines = [];
|
|
196
|
-
const innerWidth = width - 4;
|
|
197
|
-
const words = text.split(" ");
|
|
198
|
-
let currentLine = "";
|
|
199
|
-
const wrappedLines = [];
|
|
200
|
-
for (const word of words) {
|
|
201
|
-
if ((currentLine + " " + word).trim().length <= innerWidth) {
|
|
202
|
-
currentLine = (currentLine + " " + word).trim();
|
|
203
|
-
} else {
|
|
204
|
-
if (currentLine) wrappedLines.push(currentLine);
|
|
205
|
-
currentLine = word;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
if (currentLine) wrappedLines.push(currentLine);
|
|
209
|
-
lines.push(theme.dim(" \u256D" + "\u2500".repeat(innerWidth + 2) + "\u256E"));
|
|
210
|
-
for (const line of wrappedLines) {
|
|
211
|
-
const padding = innerWidth - line.length;
|
|
212
|
-
lines.push(theme.dim(" \u2502 ") + line + " ".repeat(padding) + theme.dim(" \u2502"));
|
|
213
|
-
}
|
|
214
|
-
lines.push(theme.dim(" \u2570" + "\u2500".repeat(innerWidth + 2) + "\u256F"));
|
|
215
|
-
lines.push(theme.dim(" \u2572"));
|
|
216
|
-
lines.push(theme.dim(" \u2572"));
|
|
217
|
-
return lines.join("\n");
|
|
218
|
-
},
|
|
219
|
-
think: (text, width = 50) => {
|
|
220
|
-
const lines = [];
|
|
221
|
-
const innerWidth = width - 4;
|
|
222
|
-
lines.push(theme.dim(" \u256D" + "\u2500".repeat(innerWidth + 2) + "\u256E"));
|
|
223
|
-
const padding = innerWidth - text.length;
|
|
224
|
-
lines.push(theme.dim(" \u2502 ") + text + " ".repeat(Math.max(0, padding)) + theme.dim(" \u2502"));
|
|
225
|
-
lines.push(theme.dim(" \u2570" + "\u2500".repeat(innerWidth + 2) + "\u256F"));
|
|
226
|
-
lines.push(theme.dim(" \u25CB"));
|
|
227
|
-
lines.push(theme.dim(" \u25CB"));
|
|
228
|
-
return lines.join("\n");
|
|
229
|
-
}
|
|
230
|
-
};
|
|
231
|
-
var categoryIcons = {
|
|
232
|
-
"Utilities": "\u{1F527}",
|
|
233
|
-
"Fun": "\u{1F3AE}",
|
|
234
|
-
"Creative": "\u{1F3A8}",
|
|
235
|
-
"Dev": "\u{1F4BB}",
|
|
236
|
-
"Info": "\u{1F4E1}"
|
|
237
|
-
};
|
|
238
|
-
var spinnerFrames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
36
|
+
import chalk2 from "chalk";
|
|
239
37
|
|
|
240
38
|
// src/ui/slime-animated.ts
|
|
241
|
-
import
|
|
39
|
+
import chalk from "chalk";
|
|
242
40
|
var C = {
|
|
243
41
|
P1: "#4A235A",
|
|
244
42
|
// Darkest edge
|
|
@@ -265,15 +63,15 @@ var C = {
|
|
|
265
63
|
RD: "#E74C3C"
|
|
266
64
|
// Red (angry)
|
|
267
65
|
};
|
|
268
|
-
var b = (hex) =>
|
|
269
|
-
var dot =
|
|
270
|
-
var star =
|
|
271
|
-
var heart =
|
|
272
|
-
var z =
|
|
273
|
-
var Z =
|
|
274
|
-
var eye =
|
|
275
|
-
var shine =
|
|
276
|
-
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 ");
|
|
277
75
|
var slimeFrames = {
|
|
278
76
|
happy: () => {
|
|
279
77
|
const { P1, P2, P3, P4, P5, BK, PK } = C;
|
|
@@ -290,7 +88,7 @@ var slimeFrames = {
|
|
|
290
88
|
},
|
|
291
89
|
excited: () => {
|
|
292
90
|
const { P1, P2, P3, P4, P5, BK, PK, YL } = C;
|
|
293
|
-
const starEye =
|
|
91
|
+
const starEye = chalk.bgHex(YL).hex(C.WH)("\u2605 ");
|
|
294
92
|
return [
|
|
295
93
|
` ${star} ${dot} ${star} ${dot} ${star}`,
|
|
296
94
|
` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
|
|
@@ -304,7 +102,7 @@ var slimeFrames = {
|
|
|
304
102
|
},
|
|
305
103
|
love: () => {
|
|
306
104
|
const { P1, P2, P3, P4, P5, BK, PK } = C;
|
|
307
|
-
const heartEye =
|
|
105
|
+
const heartEye = chalk.bgHex(PK).hex(C.WH)("\u2665 ");
|
|
308
106
|
return [
|
|
309
107
|
` ${heart} ${heart}`,
|
|
310
108
|
` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
|
|
@@ -318,7 +116,7 @@ var slimeFrames = {
|
|
|
318
116
|
},
|
|
319
117
|
sleepy: () => {
|
|
320
118
|
const { P1, P2, P3, P4, P5, BK } = C;
|
|
321
|
-
const closedEye =
|
|
119
|
+
const closedEye = chalk.bgHex(P3).hex(BK)("\u2500\u2500");
|
|
322
120
|
return [
|
|
323
121
|
` ${z} ${z} ${Z}`,
|
|
324
122
|
` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
|
|
@@ -332,10 +130,10 @@ var slimeFrames = {
|
|
|
332
130
|
},
|
|
333
131
|
thinking: () => {
|
|
334
132
|
const { P1, P2, P3, P4, P5, BK, YL } = C;
|
|
335
|
-
const thinkEye =
|
|
336
|
-
const lookUpEye =
|
|
133
|
+
const thinkEye = chalk.bgHex(C.BK).hex(C.WH)(" \xB7");
|
|
134
|
+
const lookUpEye = chalk.bgHex(C.BK).hex(C.WH)("\xB7 ");
|
|
337
135
|
return [
|
|
338
|
-
` ${
|
|
136
|
+
` ${chalk.hex(YL)("?")}`,
|
|
339
137
|
` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
|
|
340
138
|
` ${b(P5)}${b(P4)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P4)}${b(P5)}`,
|
|
341
139
|
` ${b(P4)}${b(P3)}${thinkEye}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${lookUpEye}${b(P3)}${b(P4)}`,
|
|
@@ -347,9 +145,9 @@ var slimeFrames = {
|
|
|
347
145
|
},
|
|
348
146
|
surprised: () => {
|
|
349
147
|
const { P1, P2, P3, P4, P5, BK, YL } = C;
|
|
350
|
-
const bigEye =
|
|
148
|
+
const bigEye = chalk.bgHex(BK).hex(C.WH)("\u25C9 ");
|
|
351
149
|
return [
|
|
352
|
-
` ${
|
|
150
|
+
` ${chalk.hex(YL)("!!")}`,
|
|
353
151
|
` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
|
|
354
152
|
` ${b(P5)}${b(P4)}${b(P3)}${shine2}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P4)}${b(P5)}`,
|
|
355
153
|
` ${b(P4)}${b(P3)}${bigEye}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${bigEye}${b(P3)}${b(P4)}`,
|
|
@@ -361,8 +159,8 @@ var slimeFrames = {
|
|
|
361
159
|
},
|
|
362
160
|
sad: () => {
|
|
363
161
|
const { P1, P2, P3, P4, P5, BK, BL } = C;
|
|
364
|
-
const sadEye =
|
|
365
|
-
const tear =
|
|
162
|
+
const sadEye = chalk.bgHex(BK).hex(C.WH)(" \xB7");
|
|
163
|
+
const tear = chalk.bgHex(BL)(" ");
|
|
366
164
|
return [
|
|
367
165
|
` ${dot} ${dot} ${dot}`,
|
|
368
166
|
` ${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}`,
|
|
@@ -376,7 +174,7 @@ var slimeFrames = {
|
|
|
376
174
|
},
|
|
377
175
|
wink: () => {
|
|
378
176
|
const { P1, P2, P3, P4, P5, BK, PK } = C;
|
|
379
|
-
const winkEye =
|
|
177
|
+
const winkEye = chalk.bgHex(P3).hex(BK)("> ");
|
|
380
178
|
return [
|
|
381
179
|
` ${star} ${dot}`,
|
|
382
180
|
` ${b(P5)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P5)}`,
|
|
@@ -390,10 +188,10 @@ var slimeFrames = {
|
|
|
390
188
|
},
|
|
391
189
|
angry: () => {
|
|
392
190
|
const { P1, P2, P3, P4, BK, RD } = C;
|
|
393
|
-
const angryEye =
|
|
394
|
-
const angryEye2 =
|
|
191
|
+
const angryEye = chalk.bgHex(BK).hex(RD)("> ");
|
|
192
|
+
const angryEye2 = chalk.bgHex(BK).hex(RD)(" <");
|
|
395
193
|
return [
|
|
396
|
-
` ${
|
|
194
|
+
` ${chalk.hex(RD)("# @!")}`,
|
|
397
195
|
` ${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}${b(P4)}`,
|
|
398
196
|
` ${b(P4)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${b(P4)}`,
|
|
399
197
|
` ${b(P4)}${b(P3)}${angryEye}${b(P3)}${b(P3)}${b(P3)}${b(P3)}${angryEye2}${b(P3)}${b(P4)}`,
|
|
@@ -439,15 +237,15 @@ function getStartupMood() {
|
|
|
439
237
|
return "happy";
|
|
440
238
|
}
|
|
441
239
|
var miniSlime = {
|
|
442
|
-
happy:
|
|
443
|
-
excited:
|
|
444
|
-
love:
|
|
445
|
-
sleepy:
|
|
446
|
-
sad:
|
|
447
|
-
surprised:
|
|
448
|
-
wink:
|
|
449
|
-
thinking:
|
|
450
|
-
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)(")")
|
|
451
249
|
};
|
|
452
250
|
var validMoods = Object.keys(slimeFrames);
|
|
453
251
|
function react(mood, message) {
|
|
@@ -517,16 +315,16 @@ var C2 = {
|
|
|
517
315
|
PK: "#E91E63"
|
|
518
316
|
// Pink (tongue)
|
|
519
317
|
};
|
|
520
|
-
var b2 = (hex) =>
|
|
521
|
-
var dot2 =
|
|
318
|
+
var b2 = (hex) => chalk2.bgHex(hex)(" ");
|
|
319
|
+
var dot2 = chalk2.hex(C2.WH)("\xB7");
|
|
522
320
|
function getSlimeLines(isBlinking, _mood) {
|
|
523
321
|
const { P1, P2, P3, P4, P5, WH, BK, PK } = C2;
|
|
524
|
-
const openEye =
|
|
525
|
-
const closedEye =
|
|
322
|
+
const openEye = chalk2.bgHex(BK).hex(WH)(" \xB7");
|
|
323
|
+
const closedEye = chalk2.bgHex(P3).hex(BK)("\u2500\u2500");
|
|
526
324
|
const eyeL = isBlinking ? closedEye : openEye;
|
|
527
325
|
const eyeR = isBlinking ? closedEye : openEye;
|
|
528
|
-
const shine3 =
|
|
529
|
-
const shine22 =
|
|
326
|
+
const shine3 = chalk2.bgHex(P3).hex(WH)(" \xB7");
|
|
327
|
+
const shine22 = chalk2.bgHex(P4).hex(WH)("\xB7 ");
|
|
530
328
|
const miniBlob = `${b2(P3)}`;
|
|
531
329
|
return [
|
|
532
330
|
` ${dot2} ${dot2}`,
|
|
@@ -543,7 +341,7 @@ var MIN_WIDTH_FOR_MASCOT2 = 90;
|
|
|
543
341
|
var MIN_WIDTH_FOR_FULL_LOGO = 55;
|
|
544
342
|
var MIN_WIDTH_FOR_COMPACT = 30;
|
|
545
343
|
async function displayBanner(simple = false) {
|
|
546
|
-
return new Promise((
|
|
344
|
+
return new Promise((resolve5) => {
|
|
547
345
|
const termWidth = process.stdout.columns || 80;
|
|
548
346
|
figlet("ZAMMY", {
|
|
549
347
|
font: "ANSI Shadow",
|
|
@@ -557,7 +355,7 @@ async function displayBanner(simple = false) {
|
|
|
557
355
|
console.log(theme.secondary(` "${greeting}"`));
|
|
558
356
|
console.log(theme.dim(" Type /help for commands"));
|
|
559
357
|
console.log("");
|
|
560
|
-
|
|
358
|
+
resolve5();
|
|
561
359
|
return;
|
|
562
360
|
}
|
|
563
361
|
let figletLines = [];
|
|
@@ -590,7 +388,7 @@ async function displayBanner(simple = false) {
|
|
|
590
388
|
console.log(theme.dim(` ${symbols.arrow} Type ${theme.primary("/")} to browse commands or ${theme.primary("/help")} for full list`));
|
|
591
389
|
console.log(theme.dim(` ${symbols.arrow} Shell commands start with ${theme.primary("!")} (e.g., ${theme.primary("!ls")}, ${theme.primary("!git")})`));
|
|
592
390
|
console.log("");
|
|
593
|
-
|
|
391
|
+
resolve5();
|
|
594
392
|
return;
|
|
595
393
|
}
|
|
596
394
|
const figletWidth = 50;
|
|
@@ -620,7 +418,7 @@ async function displayBanner(simple = false) {
|
|
|
620
418
|
console.log(theme.dim(` ${symbols.arrow} Type ${theme.primary("/")} to browse commands or ${theme.primary("/help")} for full list`));
|
|
621
419
|
console.log(theme.dim(` ${symbols.arrow} Shell commands start with ${theme.primary("!")} (e.g., ${theme.primary("!ls")}, ${theme.primary("!git")})`));
|
|
622
420
|
console.log("");
|
|
623
|
-
|
|
421
|
+
resolve5();
|
|
624
422
|
});
|
|
625
423
|
});
|
|
626
424
|
}
|
|
@@ -630,42 +428,6 @@ function getPrompt() {
|
|
|
630
428
|
return `${theme.b.primary("zammy")}${theme.dim(symbols.arrow)} `;
|
|
631
429
|
}
|
|
632
430
|
|
|
633
|
-
// src/commands/registry.ts
|
|
634
|
-
var commands = /* @__PURE__ */ new Map();
|
|
635
|
-
function registerCommand(command) {
|
|
636
|
-
commands.set(command.name, { ...command, source: "core" });
|
|
637
|
-
}
|
|
638
|
-
function registerPluginCommand(command, pluginName) {
|
|
639
|
-
commands.set(command.name, { ...command, source: "plugin", pluginName });
|
|
640
|
-
}
|
|
641
|
-
function unregisterPluginCommands(pluginName) {
|
|
642
|
-
for (const [name, cmd] of commands.entries()) {
|
|
643
|
-
if (cmd.source === "plugin" && cmd.pluginName === pluginName) {
|
|
644
|
-
commands.delete(name);
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
function getCommand(name) {
|
|
649
|
-
return commands.get(name);
|
|
650
|
-
}
|
|
651
|
-
function getAllCommands() {
|
|
652
|
-
return Array.from(commands.values());
|
|
653
|
-
}
|
|
654
|
-
function getPluginCommands() {
|
|
655
|
-
return Array.from(commands.values()).filter((cmd) => cmd.source === "plugin");
|
|
656
|
-
}
|
|
657
|
-
function checkCommandConflict(name) {
|
|
658
|
-
const existing = commands.get(name);
|
|
659
|
-
if (!existing) {
|
|
660
|
-
return { exists: false };
|
|
661
|
-
}
|
|
662
|
-
return {
|
|
663
|
-
exists: true,
|
|
664
|
-
source: existing.source,
|
|
665
|
-
pluginName: existing.pluginName
|
|
666
|
-
};
|
|
667
|
-
}
|
|
668
|
-
|
|
669
431
|
// src/commands/utilities/help.ts
|
|
670
432
|
var categories = {
|
|
671
433
|
"Utilities": ["help", "exit", "calc", "password", "stats", "time", "countdown", "timer", "todo", "history"],
|
|
@@ -680,10 +442,10 @@ registerCommand({
|
|
|
680
442
|
description: "Show all available commands",
|
|
681
443
|
usage: "/help [command]",
|
|
682
444
|
async execute(args2) {
|
|
683
|
-
const
|
|
445
|
+
const commands = getAllCommands();
|
|
684
446
|
if (args2.length > 0) {
|
|
685
447
|
const cmdName = args2[0].replace(/^\//, "");
|
|
686
|
-
const cmd =
|
|
448
|
+
const cmd = commands.find((c) => c.name === cmdName);
|
|
687
449
|
if (cmd) {
|
|
688
450
|
console.log("");
|
|
689
451
|
console.log(box.draw([
|
|
@@ -711,9 +473,9 @@ registerCommand({
|
|
|
711
473
|
console.log(` ${symbols.rocket} ${theme.gradient("ZAMMY COMMANDS")} ${symbols.rocket}`);
|
|
712
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")}`);
|
|
713
475
|
console.log("");
|
|
714
|
-
const maxNameLength = Math.max(...
|
|
476
|
+
const maxNameLength = Math.max(...commands.map((c) => c.name.length));
|
|
715
477
|
for (const [category, cmdNames] of Object.entries(categories)) {
|
|
716
|
-
const categoryCommands =
|
|
478
|
+
const categoryCommands = commands.filter((c) => cmdNames.includes(c.name));
|
|
717
479
|
if (categoryCommands.length === 0) continue;
|
|
718
480
|
const icon = categoryIcons[category] || symbols.folder;
|
|
719
481
|
console.log(` ${icon} ${theme.b.secondary(category)}`);
|
|
@@ -741,7 +503,7 @@ registerCommand({
|
|
|
741
503
|
}
|
|
742
504
|
const categorizedNames = Object.values(categories).flat();
|
|
743
505
|
const pluginCmdNames = pluginCmds.map((c) => c.name);
|
|
744
|
-
const uncategorized =
|
|
506
|
+
const uncategorized = commands.filter(
|
|
745
507
|
(c) => !categorizedNames.includes(c.name) && !pluginCmdNames.includes(c.name) && c.source === "core"
|
|
746
508
|
);
|
|
747
509
|
if (uncategorized.length > 0) {
|
|
@@ -814,21 +576,126 @@ registerCommand({
|
|
|
814
576
|
});
|
|
815
577
|
|
|
816
578
|
// src/handlers/utilities/calc.ts
|
|
817
|
-
function
|
|
818
|
-
const
|
|
819
|
-
|
|
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
|
+
}
|
|
820
609
|
return null;
|
|
821
610
|
}
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
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;
|
|
828
622
|
return result;
|
|
829
|
-
}
|
|
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
|
+
}
|
|
830
689
|
return null;
|
|
831
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;
|
|
832
699
|
}
|
|
833
700
|
function formatNumber(num) {
|
|
834
701
|
if (Math.abs(num) < 1e-4 || Math.abs(num) > 1e10) {
|
|
@@ -1192,15 +1059,16 @@ registerCommand({
|
|
|
1192
1059
|
console.log("");
|
|
1193
1060
|
let remaining = totalSeconds;
|
|
1194
1061
|
let spinnerIndex = 0;
|
|
1195
|
-
return new Promise((
|
|
1062
|
+
return new Promise((resolve5) => {
|
|
1196
1063
|
const interval = setInterval(() => {
|
|
1197
1064
|
process.stdout.write("\r\x1B[K");
|
|
1198
1065
|
if (remaining <= 0) {
|
|
1199
1066
|
clearInterval(interval);
|
|
1067
|
+
process.removeListener("SIGINT", cleanup);
|
|
1200
1068
|
console.log(` ${symbols.sparkle} ${theme.success("TIME'S UP!")} ${symbols.sparkle}`);
|
|
1201
1069
|
console.log("");
|
|
1202
1070
|
process.stdout.write("\x07");
|
|
1203
|
-
|
|
1071
|
+
resolve5();
|
|
1204
1072
|
return;
|
|
1205
1073
|
}
|
|
1206
1074
|
const spinner = spinnerFrames[spinnerIndex % spinnerFrames.length];
|
|
@@ -1212,6 +1080,14 @@ registerCommand({
|
|
|
1212
1080
|
remaining--;
|
|
1213
1081
|
spinnerIndex++;
|
|
1214
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);
|
|
1215
1091
|
process.stdout.write(` ${theme.secondary(spinnerFrames[0])} ${theme.primary(formatTime(remaining))} remaining...`);
|
|
1216
1092
|
});
|
|
1217
1093
|
}
|
|
@@ -1473,7 +1349,7 @@ registerCommand({
|
|
|
1473
1349
|
let history = [];
|
|
1474
1350
|
try {
|
|
1475
1351
|
if (existsSync2(HISTORY_FILE)) {
|
|
1476
|
-
const lines = readFileSync2(HISTORY_FILE, "utf8").split(
|
|
1352
|
+
const lines = readFileSync2(HISTORY_FILE, "utf8").split(/\r?\n/).filter((l) => l);
|
|
1477
1353
|
history = lines.map((line) => {
|
|
1478
1354
|
const [time, ...rest] = line.split("|");
|
|
1479
1355
|
return { time, cmd: rest.join("|") };
|
|
@@ -1868,7 +1744,7 @@ registerCommand({
|
|
|
1868
1744
|
console.log("");
|
|
1869
1745
|
console.log(bubble.say(joke.setup, 55));
|
|
1870
1746
|
console.log(` ${symbols.sparkle}`);
|
|
1871
|
-
await new Promise((
|
|
1747
|
+
await new Promise((resolve5) => setTimeout(resolve5, 1500));
|
|
1872
1748
|
console.log("");
|
|
1873
1749
|
console.log(` ${theme.gold(" \u2726")} ${theme.b.success(joke.punchline)} ${theme.gold("\u2726")}`);
|
|
1874
1750
|
console.log("");
|
|
@@ -2318,7 +2194,10 @@ registerCommand({
|
|
|
2318
2194
|
console.log(theme.dim(" Use /pomodoro status to check progress"));
|
|
2319
2195
|
console.log(theme.dim(" Use /pomodoro skip to skip to break"));
|
|
2320
2196
|
console.log("");
|
|
2321
|
-
if (state.interval)
|
|
2197
|
+
if (state.interval) {
|
|
2198
|
+
clearTimeout(state.interval);
|
|
2199
|
+
state.interval = null;
|
|
2200
|
+
}
|
|
2322
2201
|
state.interval = setTimeout(() => {
|
|
2323
2202
|
if (state.running) {
|
|
2324
2203
|
console.log("\n");
|
|
@@ -2327,6 +2206,7 @@ registerCommand({
|
|
|
2327
2206
|
console.log("\n");
|
|
2328
2207
|
state.sessions++;
|
|
2329
2208
|
state.running = false;
|
|
2209
|
+
state.interval = null;
|
|
2330
2210
|
}
|
|
2331
2211
|
}, DURATIONS.work);
|
|
2332
2212
|
return;
|
|
@@ -2336,7 +2216,10 @@ registerCommand({
|
|
|
2336
2216
|
console.log(theme.dim(" Pomodoro is not running"));
|
|
2337
2217
|
return;
|
|
2338
2218
|
}
|
|
2339
|
-
if (state.interval)
|
|
2219
|
+
if (state.interval) {
|
|
2220
|
+
clearTimeout(state.interval);
|
|
2221
|
+
state.interval = null;
|
|
2222
|
+
}
|
|
2340
2223
|
state.running = false;
|
|
2341
2224
|
console.log("");
|
|
2342
2225
|
console.log(` ${symbols.cross} ${theme.secondary("Pomodoro stopped")}`);
|
|
@@ -2349,7 +2232,10 @@ registerCommand({
|
|
|
2349
2232
|
console.log(theme.dim(" Pomodoro is not running"));
|
|
2350
2233
|
return;
|
|
2351
2234
|
}
|
|
2352
|
-
if (state.interval)
|
|
2235
|
+
if (state.interval) {
|
|
2236
|
+
clearTimeout(state.interval);
|
|
2237
|
+
state.interval = null;
|
|
2238
|
+
}
|
|
2353
2239
|
if (state.mode === "work") {
|
|
2354
2240
|
state.sessions++;
|
|
2355
2241
|
state.mode = state.sessions % 4 === 0 ? "longbreak" : "break";
|
|
@@ -2372,6 +2258,7 @@ registerCommand({
|
|
|
2372
2258
|
${symbols.bell} ${state.mode === "work" ? "Focus session" : "Break"} complete!
|
|
2373
2259
|
`);
|
|
2374
2260
|
state.running = false;
|
|
2261
|
+
state.interval = null;
|
|
2375
2262
|
}
|
|
2376
2263
|
}, state.endTime - Date.now());
|
|
2377
2264
|
return;
|
|
@@ -2884,7 +2771,7 @@ registerCommand({
|
|
|
2884
2771
|
});
|
|
2885
2772
|
|
|
2886
2773
|
// src/commands/creative/color.ts
|
|
2887
|
-
import
|
|
2774
|
+
import chalk3 from "chalk";
|
|
2888
2775
|
|
|
2889
2776
|
// src/handlers/creative/color.ts
|
|
2890
2777
|
function hexToRgb(hex) {
|
|
@@ -3033,7 +2920,7 @@ registerCommand({
|
|
|
3033
2920
|
console.log("");
|
|
3034
2921
|
console.log(` ${symbols.palette} ${theme.gradient("COLOR CONVERTER")} ${symbols.palette}`);
|
|
3035
2922
|
console.log("");
|
|
3036
|
-
const colorBlock =
|
|
2923
|
+
const colorBlock = chalk3.bgHex(hex).hex(textColor);
|
|
3037
2924
|
console.log(` ${colorBlock(" ")}`);
|
|
3038
2925
|
console.log(` ${colorBlock(" ")}`);
|
|
3039
2926
|
console.log(` ${colorBlock(` ${hex.toUpperCase()} `.slice(0, 40))}`);
|
|
@@ -3048,14 +2935,14 @@ registerCommand({
|
|
|
3048
2935
|
let shadesLine = " ";
|
|
3049
2936
|
const shades = generateShades(rgb);
|
|
3050
2937
|
for (const shade of shades) {
|
|
3051
|
-
shadesLine +=
|
|
2938
|
+
shadesLine += chalk3.bgRgb(shade.r, shade.g, shade.b)(" ");
|
|
3052
2939
|
}
|
|
3053
2940
|
console.log(shadesLine);
|
|
3054
2941
|
console.log(` ${theme.dim("Tints:")}`);
|
|
3055
2942
|
let tintsLine = " ";
|
|
3056
2943
|
const tints = generateTints(rgb);
|
|
3057
2944
|
for (const tint of tints) {
|
|
3058
|
-
tintsLine +=
|
|
2945
|
+
tintsLine += chalk3.bgRgb(tint.r, tint.g, tint.b)(" ");
|
|
3059
2946
|
}
|
|
3060
2947
|
console.log(tintsLine);
|
|
3061
2948
|
console.log("");
|
|
@@ -3162,8 +3049,18 @@ var SUPPORTED_METHODS = ["base64", "url", "hex"];
|
|
|
3162
3049
|
function isValidMethod(method) {
|
|
3163
3050
|
return SUPPORTED_METHODS.includes(method.toLowerCase());
|
|
3164
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
|
+
}
|
|
3165
3061
|
function encodeText(text, method, direction) {
|
|
3166
3062
|
let output;
|
|
3063
|
+
let error;
|
|
3167
3064
|
if (direction === "encode") {
|
|
3168
3065
|
switch (method) {
|
|
3169
3066
|
case "base64":
|
|
@@ -3179,13 +3076,38 @@ function encodeText(text, method, direction) {
|
|
|
3179
3076
|
} else {
|
|
3180
3077
|
switch (method) {
|
|
3181
3078
|
case "base64":
|
|
3182
|
-
|
|
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
|
+
}
|
|
3183
3090
|
break;
|
|
3184
3091
|
case "url":
|
|
3185
|
-
|
|
3092
|
+
try {
|
|
3093
|
+
output = decodeURIComponent(text);
|
|
3094
|
+
} catch (e) {
|
|
3095
|
+
output = "";
|
|
3096
|
+
error = "Failed to decode URL: malformed URI sequence";
|
|
3097
|
+
}
|
|
3186
3098
|
break;
|
|
3187
3099
|
case "hex":
|
|
3188
|
-
|
|
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
|
+
}
|
|
3189
3111
|
break;
|
|
3190
3112
|
}
|
|
3191
3113
|
}
|
|
@@ -3193,7 +3115,8 @@ function encodeText(text, method, direction) {
|
|
|
3193
3115
|
method: method.toUpperCase(),
|
|
3194
3116
|
direction,
|
|
3195
3117
|
input: text,
|
|
3196
|
-
output
|
|
3118
|
+
output,
|
|
3119
|
+
...error && { error }
|
|
3197
3120
|
};
|
|
3198
3121
|
}
|
|
3199
3122
|
|
|
@@ -3509,9 +3432,9 @@ import http from "http";
|
|
|
3509
3432
|
import { URL } from "url";
|
|
3510
3433
|
async function makeRequest(urlStr, options = { method: "GET" }) {
|
|
3511
3434
|
const startTime2 = Date.now();
|
|
3512
|
-
return new Promise((
|
|
3435
|
+
return new Promise((resolve5) => {
|
|
3513
3436
|
const timeout = setTimeout(() => {
|
|
3514
|
-
|
|
3437
|
+
resolve5({ success: false, error: "Request timed out" });
|
|
3515
3438
|
}, options.timeout || 3e4);
|
|
3516
3439
|
try {
|
|
3517
3440
|
const url = new URL(urlStr.startsWith("http") ? urlStr : `https://${urlStr}`);
|
|
@@ -3533,7 +3456,7 @@ async function makeRequest(urlStr, options = { method: "GET" }) {
|
|
|
3533
3456
|
});
|
|
3534
3457
|
res.on("end", () => {
|
|
3535
3458
|
clearTimeout(timeout);
|
|
3536
|
-
|
|
3459
|
+
resolve5({
|
|
3537
3460
|
success: true,
|
|
3538
3461
|
statusCode: res.statusCode,
|
|
3539
3462
|
statusMessage: res.statusMessage,
|
|
@@ -3545,7 +3468,7 @@ async function makeRequest(urlStr, options = { method: "GET" }) {
|
|
|
3545
3468
|
});
|
|
3546
3469
|
req.on("error", (error) => {
|
|
3547
3470
|
clearTimeout(timeout);
|
|
3548
|
-
|
|
3471
|
+
resolve5({ success: false, error: error.message });
|
|
3549
3472
|
});
|
|
3550
3473
|
if (options.body) {
|
|
3551
3474
|
req.write(options.body);
|
|
@@ -3553,7 +3476,7 @@ async function makeRequest(urlStr, options = { method: "GET" }) {
|
|
|
3553
3476
|
req.end();
|
|
3554
3477
|
} catch (error) {
|
|
3555
3478
|
clearTimeout(timeout);
|
|
3556
|
-
|
|
3479
|
+
resolve5({ success: false, error: error instanceof Error ? error.message : "Request failed" });
|
|
3557
3480
|
}
|
|
3558
3481
|
});
|
|
3559
3482
|
}
|
|
@@ -3852,408 +3775,6 @@ registerCommand({
|
|
|
3852
3775
|
}
|
|
3853
3776
|
});
|
|
3854
3777
|
|
|
3855
|
-
// src/plugins/loader.ts
|
|
3856
|
-
import { existsSync as existsSync8, readdirSync as readdirSync2, readFileSync as readFileSync7, mkdirSync as mkdirSync2 } from "fs";
|
|
3857
|
-
import { join as join6, dirname as dirname3 } from "path";
|
|
3858
|
-
import { homedir as homedir3 } from "os";
|
|
3859
|
-
import { pathToFileURL, fileURLToPath as fileURLToPath2 } from "url";
|
|
3860
|
-
|
|
3861
|
-
// src/plugins/api.ts
|
|
3862
|
-
import { execSync, spawn as nodeSpawn } from "child_process";
|
|
3863
|
-
import { join as join5 } from "path";
|
|
3864
|
-
|
|
3865
|
-
// src/plugins/storage.ts
|
|
3866
|
-
import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync3, mkdirSync } from "fs";
|
|
3867
|
-
import { join as join4 } from "path";
|
|
3868
|
-
function createPluginStorage(pluginName, dataDir) {
|
|
3869
|
-
const storagePath = join4(dataDir, "data.json");
|
|
3870
|
-
if (!existsSync7(dataDir)) {
|
|
3871
|
-
mkdirSync(dataDir, { recursive: true });
|
|
3872
|
-
}
|
|
3873
|
-
function loadData() {
|
|
3874
|
-
try {
|
|
3875
|
-
if (existsSync7(storagePath)) {
|
|
3876
|
-
const content = readFileSync5(storagePath, "utf-8");
|
|
3877
|
-
return JSON.parse(content);
|
|
3878
|
-
}
|
|
3879
|
-
} catch {
|
|
3880
|
-
}
|
|
3881
|
-
return {};
|
|
3882
|
-
}
|
|
3883
|
-
function saveData(data) {
|
|
3884
|
-
try {
|
|
3885
|
-
writeFileSync3(storagePath, JSON.stringify(data, null, 2), "utf-8");
|
|
3886
|
-
} catch (error) {
|
|
3887
|
-
console.error(`Failed to save plugin storage for ${pluginName}:`, error);
|
|
3888
|
-
}
|
|
3889
|
-
}
|
|
3890
|
-
return {
|
|
3891
|
-
get(key) {
|
|
3892
|
-
const data = loadData();
|
|
3893
|
-
return data[key];
|
|
3894
|
-
},
|
|
3895
|
-
set(key, value) {
|
|
3896
|
-
const data = loadData();
|
|
3897
|
-
data[key] = value;
|
|
3898
|
-
saveData(data);
|
|
3899
|
-
},
|
|
3900
|
-
delete(key) {
|
|
3901
|
-
const data = loadData();
|
|
3902
|
-
delete data[key];
|
|
3903
|
-
saveData(data);
|
|
3904
|
-
},
|
|
3905
|
-
clear() {
|
|
3906
|
-
saveData({});
|
|
3907
|
-
},
|
|
3908
|
-
getAll() {
|
|
3909
|
-
return loadData();
|
|
3910
|
-
}
|
|
3911
|
-
};
|
|
3912
|
-
}
|
|
3913
|
-
|
|
3914
|
-
// src/plugins/api.ts
|
|
3915
|
-
import { readFileSync as readFileSync6 } from "fs";
|
|
3916
|
-
import { fileURLToPath } from "url";
|
|
3917
|
-
import { dirname as dirname2 } from "path";
|
|
3918
|
-
function getZammyVersion() {
|
|
3919
|
-
try {
|
|
3920
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
3921
|
-
const __dirname = dirname2(__filename);
|
|
3922
|
-
const pkgPath = join5(__dirname, "..", "..", "package.json");
|
|
3923
|
-
const pkg = JSON.parse(readFileSync6(pkgPath, "utf-8"));
|
|
3924
|
-
return pkg.version || "0.0.0";
|
|
3925
|
-
} catch {
|
|
3926
|
-
return "0.0.0";
|
|
3927
|
-
}
|
|
3928
|
-
}
|
|
3929
|
-
function createPluginUI() {
|
|
3930
|
-
return {
|
|
3931
|
-
theme: {
|
|
3932
|
-
primary: theme.primary,
|
|
3933
|
-
secondary: theme.secondary,
|
|
3934
|
-
accent: theme.accent,
|
|
3935
|
-
success: theme.success,
|
|
3936
|
-
warning: theme.warning,
|
|
3937
|
-
error: theme.error,
|
|
3938
|
-
info: theme.info,
|
|
3939
|
-
dim: theme.dim,
|
|
3940
|
-
gradient: theme.gradient
|
|
3941
|
-
},
|
|
3942
|
-
symbols: {
|
|
3943
|
-
check: symbols.check,
|
|
3944
|
-
cross: symbols.cross,
|
|
3945
|
-
star: symbols.star,
|
|
3946
|
-
arrow: symbols.arrow,
|
|
3947
|
-
bullet: symbols.bullet,
|
|
3948
|
-
folder: symbols.folder,
|
|
3949
|
-
file: "\u{1F4C4}",
|
|
3950
|
-
// 📄
|
|
3951
|
-
warning: symbols.warning,
|
|
3952
|
-
info: symbols.info,
|
|
3953
|
-
rocket: symbols.rocket,
|
|
3954
|
-
sparkles: symbols.sparkle
|
|
3955
|
-
},
|
|
3956
|
-
box: (content, options) => {
|
|
3957
|
-
const lines = content.split("\n");
|
|
3958
|
-
const width = Math.max(...lines.map((l) => l.replace(/\x1B\[[0-9;]*m/g, "").length)) + 4;
|
|
3959
|
-
return box.draw(lines, width);
|
|
3960
|
-
},
|
|
3961
|
-
progressBar: (current, total, width) => {
|
|
3962
|
-
const percent = Math.round(current / total * 100);
|
|
3963
|
-
return progressBar(percent, width || 30);
|
|
3964
|
-
}
|
|
3965
|
-
};
|
|
3966
|
-
}
|
|
3967
|
-
function createPluginLogger(pluginName) {
|
|
3968
|
-
const prefix = theme.dim(`[${pluginName}]`);
|
|
3969
|
-
return {
|
|
3970
|
-
info: (message) => console.log(`${prefix} ${theme.info(message)}`),
|
|
3971
|
-
warn: (message) => console.log(`${prefix} ${theme.warning(message)}`),
|
|
3972
|
-
error: (message) => console.log(`${prefix} ${theme.error(message)}`),
|
|
3973
|
-
debug: (message) => {
|
|
3974
|
-
if (process.env.ZAMMY_DEBUG) {
|
|
3975
|
-
console.log(`${prefix} ${theme.dim(message)}`);
|
|
3976
|
-
}
|
|
3977
|
-
}
|
|
3978
|
-
};
|
|
3979
|
-
}
|
|
3980
|
-
function createPluginShell(manifest) {
|
|
3981
|
-
if (!manifest.permissions?.shell) {
|
|
3982
|
-
return void 0;
|
|
3983
|
-
}
|
|
3984
|
-
return {
|
|
3985
|
-
exec: (command, options) => {
|
|
3986
|
-
try {
|
|
3987
|
-
return execSync(command, {
|
|
3988
|
-
encoding: "utf-8",
|
|
3989
|
-
timeout: options?.timeout || 3e4,
|
|
3990
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
3991
|
-
});
|
|
3992
|
-
} catch (error) {
|
|
3993
|
-
if (error && typeof error === "object" && "stdout" in error) {
|
|
3994
|
-
return error.stdout || "";
|
|
3995
|
-
}
|
|
3996
|
-
throw error;
|
|
3997
|
-
}
|
|
3998
|
-
},
|
|
3999
|
-
spawn: (command, args2) => {
|
|
4000
|
-
return new Promise((resolve6) => {
|
|
4001
|
-
const proc = nodeSpawn(command, args2 || [], {
|
|
4002
|
-
shell: true,
|
|
4003
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
4004
|
-
});
|
|
4005
|
-
let stdout = "";
|
|
4006
|
-
let stderr = "";
|
|
4007
|
-
proc.stdout?.on("data", (data) => {
|
|
4008
|
-
stdout += data.toString();
|
|
4009
|
-
});
|
|
4010
|
-
proc.stderr?.on("data", (data) => {
|
|
4011
|
-
stderr += data.toString();
|
|
4012
|
-
});
|
|
4013
|
-
proc.on("close", (code) => {
|
|
4014
|
-
resolve6({ stdout, stderr, code: code || 0 });
|
|
4015
|
-
});
|
|
4016
|
-
proc.on("error", () => {
|
|
4017
|
-
resolve6({ stdout, stderr, code: 1 });
|
|
4018
|
-
});
|
|
4019
|
-
});
|
|
4020
|
-
}
|
|
4021
|
-
};
|
|
4022
|
-
}
|
|
4023
|
-
function createPluginAPI(manifest, pluginPath) {
|
|
4024
|
-
const dataDir = pluginPath;
|
|
4025
|
-
const context = {
|
|
4026
|
-
pluginName: manifest.name,
|
|
4027
|
-
pluginVersion: manifest.version,
|
|
4028
|
-
zammyVersion: getZammyVersion(),
|
|
4029
|
-
dataDir,
|
|
4030
|
-
cwd: process.cwd()
|
|
4031
|
-
};
|
|
4032
|
-
return {
|
|
4033
|
-
registerCommand: (command) => {
|
|
4034
|
-
registerPluginCommand(command, manifest.name);
|
|
4035
|
-
},
|
|
4036
|
-
registerCommands: (commands2) => {
|
|
4037
|
-
for (const command of commands2) {
|
|
4038
|
-
registerPluginCommand(command, manifest.name);
|
|
4039
|
-
}
|
|
4040
|
-
},
|
|
4041
|
-
ui: createPluginUI(),
|
|
4042
|
-
storage: createPluginStorage(manifest.name, dataDir),
|
|
4043
|
-
log: createPluginLogger(manifest.name),
|
|
4044
|
-
context,
|
|
4045
|
-
shell: createPluginShell(manifest)
|
|
4046
|
-
};
|
|
4047
|
-
}
|
|
4048
|
-
|
|
4049
|
-
// src/plugins/loader.ts
|
|
4050
|
-
var PLUGINS_DIR = join6(homedir3(), ".zammy", "plugins");
|
|
4051
|
-
function getZammyVersion2() {
|
|
4052
|
-
try {
|
|
4053
|
-
const __filename = fileURLToPath2(import.meta.url);
|
|
4054
|
-
const __dirname = dirname3(__filename);
|
|
4055
|
-
const possiblePaths = [
|
|
4056
|
-
join6(__dirname, "package.json"),
|
|
4057
|
-
// Same dir (bundled: dist/)
|
|
4058
|
-
join6(__dirname, "..", "package.json"),
|
|
4059
|
-
// One up (bundled: project root)
|
|
4060
|
-
join6(__dirname, "..", "..", "package.json")
|
|
4061
|
-
// Two up (source: src/plugins/)
|
|
4062
|
-
];
|
|
4063
|
-
for (const pkgPath of possiblePaths) {
|
|
4064
|
-
if (existsSync8(pkgPath)) {
|
|
4065
|
-
const pkg = JSON.parse(readFileSync7(pkgPath, "utf-8"));
|
|
4066
|
-
if (pkg.name === "zammy" && pkg.version) {
|
|
4067
|
-
return pkg.version;
|
|
4068
|
-
}
|
|
4069
|
-
}
|
|
4070
|
-
}
|
|
4071
|
-
return "0.0.0";
|
|
4072
|
-
} catch {
|
|
4073
|
-
return "0.0.0";
|
|
4074
|
-
}
|
|
4075
|
-
}
|
|
4076
|
-
function compareVersions(a, b3) {
|
|
4077
|
-
const partsA = a.split(".").map((n) => parseInt(n, 10) || 0);
|
|
4078
|
-
const partsB = b3.split(".").map((n) => parseInt(n, 10) || 0);
|
|
4079
|
-
for (let i = 0; i < 3; i++) {
|
|
4080
|
-
const numA = partsA[i] || 0;
|
|
4081
|
-
const numB = partsB[i] || 0;
|
|
4082
|
-
if (numA < numB) return -1;
|
|
4083
|
-
if (numA > numB) return 1;
|
|
4084
|
-
}
|
|
4085
|
-
return 0;
|
|
4086
|
-
}
|
|
4087
|
-
function checkVersionCompatibility(manifest, zammyVersion) {
|
|
4088
|
-
const minVersion = manifest.zammy?.minVersion;
|
|
4089
|
-
const maxVersion = manifest.zammy?.maxVersion;
|
|
4090
|
-
if (minVersion && compareVersions(zammyVersion, minVersion) < 0) {
|
|
4091
|
-
return {
|
|
4092
|
-
compatible: false,
|
|
4093
|
-
reason: `Requires Zammy v${minVersion}+, but you have v${zammyVersion}`
|
|
4094
|
-
};
|
|
4095
|
-
}
|
|
4096
|
-
if (maxVersion && compareVersions(zammyVersion, maxVersion) > 0) {
|
|
4097
|
-
return {
|
|
4098
|
-
compatible: false,
|
|
4099
|
-
reason: `Incompatible with Zammy v${zammyVersion} (max: v${maxVersion})`
|
|
4100
|
-
};
|
|
4101
|
-
}
|
|
4102
|
-
return { compatible: true };
|
|
4103
|
-
}
|
|
4104
|
-
var discoveredPlugins = /* @__PURE__ */ new Map();
|
|
4105
|
-
var loadedPlugins = /* @__PURE__ */ new Map();
|
|
4106
|
-
function ensurePluginsDir() {
|
|
4107
|
-
if (!existsSync8(PLUGINS_DIR)) {
|
|
4108
|
-
mkdirSync2(PLUGINS_DIR, { recursive: true });
|
|
4109
|
-
}
|
|
4110
|
-
}
|
|
4111
|
-
function getPluginsDir() {
|
|
4112
|
-
return PLUGINS_DIR;
|
|
4113
|
-
}
|
|
4114
|
-
async function discoverPlugins() {
|
|
4115
|
-
ensurePluginsDir();
|
|
4116
|
-
discoveredPlugins.clear();
|
|
4117
|
-
if (!existsSync8(PLUGINS_DIR)) {
|
|
4118
|
-
return [];
|
|
4119
|
-
}
|
|
4120
|
-
const zammyVersion = getZammyVersion2();
|
|
4121
|
-
const entries = readdirSync2(PLUGINS_DIR, { withFileTypes: true });
|
|
4122
|
-
const manifests = [];
|
|
4123
|
-
for (const entry of entries) {
|
|
4124
|
-
if (!entry.isDirectory()) continue;
|
|
4125
|
-
const pluginPath = join6(PLUGINS_DIR, entry.name);
|
|
4126
|
-
const manifestPath = join6(pluginPath, "zammy-plugin.json");
|
|
4127
|
-
if (!existsSync8(manifestPath)) continue;
|
|
4128
|
-
try {
|
|
4129
|
-
const manifestContent = readFileSync7(manifestPath, "utf-8");
|
|
4130
|
-
const manifest = JSON.parse(manifestContent);
|
|
4131
|
-
if (!manifest.name || !manifest.version || !manifest.main || !manifest.commands) {
|
|
4132
|
-
console.log(theme.warning(` ${symbols.warning} Invalid manifest for plugin in ${entry.name}`));
|
|
4133
|
-
continue;
|
|
4134
|
-
}
|
|
4135
|
-
const compatibility = checkVersionCompatibility(manifest, zammyVersion);
|
|
4136
|
-
if (!compatibility.compatible) {
|
|
4137
|
-
console.log(theme.warning(` ${symbols.warning} Plugin '${manifest.name}' skipped: ${compatibility.reason}`));
|
|
4138
|
-
continue;
|
|
4139
|
-
}
|
|
4140
|
-
discoveredPlugins.set(manifest.name, { manifest, path: pluginPath });
|
|
4141
|
-
manifests.push(manifest);
|
|
4142
|
-
} catch (error) {
|
|
4143
|
-
console.log(theme.warning(` ${symbols.warning} Failed to read manifest for ${entry.name}`));
|
|
4144
|
-
}
|
|
4145
|
-
}
|
|
4146
|
-
return manifests;
|
|
4147
|
-
}
|
|
4148
|
-
async function loadPlugin(name) {
|
|
4149
|
-
if (loadedPlugins.has(name)) {
|
|
4150
|
-
const existing = loadedPlugins.get(name);
|
|
4151
|
-
if (existing.state === "error") {
|
|
4152
|
-
return null;
|
|
4153
|
-
}
|
|
4154
|
-
return existing;
|
|
4155
|
-
}
|
|
4156
|
-
const discovered = discoveredPlugins.get(name);
|
|
4157
|
-
if (!discovered) {
|
|
4158
|
-
return null;
|
|
4159
|
-
}
|
|
4160
|
-
const { manifest, path: pluginPath } = discovered;
|
|
4161
|
-
try {
|
|
4162
|
-
const mainPath = join6(pluginPath, manifest.main);
|
|
4163
|
-
if (!existsSync8(mainPath)) {
|
|
4164
|
-
throw new Error(`Plugin entry point not found: ${mainPath}`);
|
|
4165
|
-
}
|
|
4166
|
-
const moduleUrl = pathToFileURL(mainPath).href;
|
|
4167
|
-
const module = await import(moduleUrl);
|
|
4168
|
-
const plugin = module.default;
|
|
4169
|
-
if (!plugin || typeof plugin.activate !== "function") {
|
|
4170
|
-
throw new Error("Plugin must export a default object with an activate function");
|
|
4171
|
-
}
|
|
4172
|
-
const api = createPluginAPI(manifest, pluginPath);
|
|
4173
|
-
try {
|
|
4174
|
-
await plugin.activate(api);
|
|
4175
|
-
} catch (activationError) {
|
|
4176
|
-
const msg = activationError instanceof Error ? activationError.message : String(activationError);
|
|
4177
|
-
throw new Error(`Plugin activation failed: ${msg}`);
|
|
4178
|
-
}
|
|
4179
|
-
const loaded = {
|
|
4180
|
-
manifest,
|
|
4181
|
-
instance: plugin,
|
|
4182
|
-
path: pluginPath,
|
|
4183
|
-
state: "active"
|
|
4184
|
-
};
|
|
4185
|
-
loadedPlugins.set(name, loaded);
|
|
4186
|
-
return loaded;
|
|
4187
|
-
} catch (error) {
|
|
4188
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4189
|
-
console.log(theme.error(` ${symbols.cross} Failed to load plugin '${name}': ${errorMessage}`));
|
|
4190
|
-
const failedPlugin = {
|
|
4191
|
-
manifest,
|
|
4192
|
-
instance: { activate: async () => {
|
|
4193
|
-
} },
|
|
4194
|
-
path: pluginPath,
|
|
4195
|
-
state: "error"
|
|
4196
|
-
};
|
|
4197
|
-
loadedPlugins.set(name, failedPlugin);
|
|
4198
|
-
return null;
|
|
4199
|
-
}
|
|
4200
|
-
}
|
|
4201
|
-
async function unloadPlugin(name) {
|
|
4202
|
-
const loaded = loadedPlugins.get(name);
|
|
4203
|
-
if (!loaded) {
|
|
4204
|
-
return false;
|
|
4205
|
-
}
|
|
4206
|
-
try {
|
|
4207
|
-
if (loaded.instance.deactivate) {
|
|
4208
|
-
await loaded.instance.deactivate();
|
|
4209
|
-
}
|
|
4210
|
-
unregisterPluginCommands(name);
|
|
4211
|
-
loadedPlugins.delete(name);
|
|
4212
|
-
return true;
|
|
4213
|
-
} catch (error) {
|
|
4214
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4215
|
-
console.log(theme.error(` ${symbols.cross} Failed to unload plugin '${name}': ${errorMessage}`));
|
|
4216
|
-
return false;
|
|
4217
|
-
}
|
|
4218
|
-
}
|
|
4219
|
-
function getDiscoveredPlugins() {
|
|
4220
|
-
return Array.from(discoveredPlugins.values()).map((p) => p.manifest);
|
|
4221
|
-
}
|
|
4222
|
-
function isPluginLoaded(name) {
|
|
4223
|
-
return loadedPlugins.has(name);
|
|
4224
|
-
}
|
|
4225
|
-
async function initPluginLoader() {
|
|
4226
|
-
const manifests = await discoverPlugins();
|
|
4227
|
-
for (const manifest of manifests) {
|
|
4228
|
-
for (const cmdName of manifest.commands) {
|
|
4229
|
-
const lazyExecute = async (args2) => {
|
|
4230
|
-
const loaded = await loadPlugin(manifest.name);
|
|
4231
|
-
if (!loaded) {
|
|
4232
|
-
console.log(theme.error(` ${symbols.cross} Failed to load plugin '${manifest.name}'`));
|
|
4233
|
-
console.log(theme.dim(` Try reinstalling: /plugin remove ${manifest.name} && /plugin install ${manifest.name}`));
|
|
4234
|
-
return;
|
|
4235
|
-
}
|
|
4236
|
-
const realCommand = getCommand(cmdName);
|
|
4237
|
-
if (realCommand && realCommand.execute !== lazyExecute) {
|
|
4238
|
-
await realCommand.execute(args2);
|
|
4239
|
-
} else {
|
|
4240
|
-
console.log(theme.error(` ${symbols.cross} Plugin '${manifest.name}' did not register command '${cmdName}'`));
|
|
4241
|
-
console.log(theme.dim(` The plugin may be misconfigured or corrupted.`));
|
|
4242
|
-
}
|
|
4243
|
-
};
|
|
4244
|
-
registerPluginCommand(
|
|
4245
|
-
{
|
|
4246
|
-
name: cmdName,
|
|
4247
|
-
description: `[${manifest.displayName || manifest.name}] Plugin command`,
|
|
4248
|
-
usage: `/${cmdName}`,
|
|
4249
|
-
execute: lazyExecute
|
|
4250
|
-
},
|
|
4251
|
-
manifest.name
|
|
4252
|
-
);
|
|
4253
|
-
}
|
|
4254
|
-
}
|
|
4255
|
-
}
|
|
4256
|
-
|
|
4257
3778
|
// src/commands/plugin/list.ts
|
|
4258
3779
|
async function listPlugins() {
|
|
4259
3780
|
await discoverPlugins();
|
|
@@ -4291,358 +3812,96 @@ async function listPlugins() {
|
|
|
4291
3812
|
}
|
|
4292
3813
|
}
|
|
4293
3814
|
|
|
4294
|
-
// src/
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
const
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
];
|
|
4312
|
-
for (const pkgPath of possiblePaths) {
|
|
4313
|
-
if (existsSync9(pkgPath)) {
|
|
4314
|
-
const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
|
|
4315
|
-
if (pkg.name === "zammy" && pkg.version) {
|
|
4316
|
-
return pkg.version;
|
|
4317
|
-
}
|
|
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);
|
|
4318
3832
|
}
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
}
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
}
|
|
4334
|
-
return 0;
|
|
4335
|
-
}
|
|
4336
|
-
function checkVersionCompatibility2(manifest) {
|
|
4337
|
-
const zammyVersion = getZammyVersion3();
|
|
4338
|
-
const minVersion = manifest.zammy?.minVersion;
|
|
4339
|
-
const maxVersion = manifest.zammy?.maxVersion;
|
|
4340
|
-
if (minVersion && compareVersions2(zammyVersion, minVersion) < 0) {
|
|
4341
|
-
return {
|
|
4342
|
-
compatible: false,
|
|
4343
|
-
reason: `Requires Zammy v${minVersion}+, but you have v${zammyVersion}`
|
|
4344
|
-
};
|
|
4345
|
-
}
|
|
4346
|
-
if (maxVersion && compareVersions2(zammyVersion, maxVersion) > 0) {
|
|
4347
|
-
return {
|
|
4348
|
-
compatible: false,
|
|
4349
|
-
reason: `Incompatible with Zammy v${zammyVersion} (max supported: v${maxVersion})`
|
|
4350
|
-
};
|
|
4351
|
-
}
|
|
4352
|
-
return { compatible: true };
|
|
4353
|
-
}
|
|
4354
|
-
async function extractTarGz(tarGzPath, destDir) {
|
|
4355
|
-
try {
|
|
4356
|
-
execSync2(`tar -xzf "${tarGzPath}" -C "${destDir}"`, {
|
|
4357
|
-
encoding: "utf-8",
|
|
4358
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
4359
|
-
});
|
|
4360
|
-
return;
|
|
4361
|
-
} catch {
|
|
4362
|
-
}
|
|
4363
|
-
const tarPath = tarGzPath.replace(/\.tgz$|\.tar\.gz$/, ".tar");
|
|
4364
|
-
await pipeline(
|
|
4365
|
-
createReadStream(tarGzPath),
|
|
4366
|
-
createGunzip(),
|
|
4367
|
-
createWriteStream(tarPath)
|
|
4368
|
-
);
|
|
4369
|
-
try {
|
|
4370
|
-
execSync2(`tar -xf "${tarPath}" -C "${destDir}"`, {
|
|
4371
|
-
encoding: "utf-8",
|
|
4372
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
4373
|
-
});
|
|
4374
|
-
rmSync(tarPath, { force: true });
|
|
4375
|
-
return;
|
|
4376
|
-
} catch {
|
|
4377
|
-
rmSync(tarPath, { force: true });
|
|
4378
|
-
}
|
|
4379
|
-
if (isWindows) {
|
|
4380
|
-
try {
|
|
4381
|
-
execSync2(`powershell -Command "tar -xf '${tarPath}' -C '${destDir}'"`, {
|
|
4382
|
-
encoding: "utf-8",
|
|
4383
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
4384
|
-
});
|
|
4385
|
-
return;
|
|
4386
|
-
} catch {
|
|
4387
|
-
throw new Error(
|
|
4388
|
-
"Unable to extract plugin archive. Please ensure tar is available.\nOn Windows 10+, tar should be built-in. Try running: tar --version"
|
|
4389
|
-
);
|
|
4390
|
-
}
|
|
4391
|
-
}
|
|
4392
|
-
throw new Error("Unable to extract plugin archive. Please ensure tar is installed.");
|
|
4393
|
-
}
|
|
4394
|
-
function validateManifest(manifest) {
|
|
4395
|
-
const errors = [];
|
|
4396
|
-
if (!manifest || typeof manifest !== "object") {
|
|
4397
|
-
return { valid: false, errors: ["Manifest must be an object"] };
|
|
4398
|
-
}
|
|
4399
|
-
const m = manifest;
|
|
4400
|
-
if (!m.name || typeof m.name !== "string") {
|
|
4401
|
-
errors.push('Missing or invalid "name" field');
|
|
4402
|
-
}
|
|
4403
|
-
if (!m.version || typeof m.version !== "string") {
|
|
4404
|
-
errors.push('Missing or invalid "version" field');
|
|
4405
|
-
}
|
|
4406
|
-
if (!m.main || typeof m.main !== "string") {
|
|
4407
|
-
errors.push('Missing or invalid "main" field');
|
|
4408
|
-
}
|
|
4409
|
-
if (!m.commands || !Array.isArray(m.commands) || m.commands.length === 0) {
|
|
4410
|
-
errors.push('Missing or invalid "commands" field (must be non-empty array)');
|
|
4411
|
-
}
|
|
4412
|
-
if (!m.zammy || typeof m.zammy !== "object") {
|
|
4413
|
-
errors.push('Missing or invalid "zammy" field');
|
|
4414
|
-
} else {
|
|
4415
|
-
const zammy = m.zammy;
|
|
4416
|
-
if (!zammy.minVersion || typeof zammy.minVersion !== "string") {
|
|
4417
|
-
errors.push('Missing or invalid "zammy.minVersion" field');
|
|
4418
|
-
}
|
|
4419
|
-
}
|
|
4420
|
-
return { valid: errors.length === 0, errors };
|
|
4421
|
-
}
|
|
4422
|
-
function checkConflicts(manifest) {
|
|
4423
|
-
const conflicts = [];
|
|
4424
|
-
for (const cmd of manifest.commands) {
|
|
4425
|
-
const conflict = checkCommandConflict(cmd);
|
|
4426
|
-
if (conflict.exists) {
|
|
4427
|
-
if (conflict.source === "core") {
|
|
4428
|
-
conflicts.push(`Command '/${cmd}' conflicts with core zammy command`);
|
|
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);
|
|
4429
3847
|
} else {
|
|
4430
|
-
|
|
3848
|
+
stdout.write("\n");
|
|
3849
|
+
resolve5(false);
|
|
4431
3850
|
}
|
|
4432
|
-
}
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
}
|
|
4436
|
-
function formatPermissions(manifest) {
|
|
4437
|
-
const perms = [];
|
|
4438
|
-
const p = manifest.permissions;
|
|
4439
|
-
if (!p) return perms;
|
|
4440
|
-
if (p.shell) {
|
|
4441
|
-
perms.push(`${symbols.warning} shell: Can run system commands`);
|
|
4442
|
-
}
|
|
4443
|
-
if (p.filesystem) {
|
|
4444
|
-
if (p.filesystem === true) {
|
|
4445
|
-
perms.push(`${symbols.warning} filesystem: Full file system access`);
|
|
4446
|
-
} else if (Array.isArray(p.filesystem)) {
|
|
4447
|
-
perms.push(`${symbols.info} filesystem: Access to ${p.filesystem.join(", ")}`);
|
|
4448
|
-
}
|
|
4449
|
-
}
|
|
4450
|
-
if (p.network) {
|
|
4451
|
-
if (p.network === true) {
|
|
4452
|
-
perms.push(`${symbols.warning} network: Full network access`);
|
|
4453
|
-
} else if (Array.isArray(p.network)) {
|
|
4454
|
-
perms.push(`${symbols.info} network: Access to ${p.network.join(", ")}`);
|
|
4455
|
-
}
|
|
4456
|
-
}
|
|
4457
|
-
return perms;
|
|
4458
|
-
}
|
|
4459
|
-
async function installFromLocal(sourcePath) {
|
|
4460
|
-
try {
|
|
4461
|
-
const absPath = resolve3(sourcePath);
|
|
4462
|
-
if (!existsSync9(absPath)) {
|
|
4463
|
-
return { success: false, error: `Path not found: ${absPath}` };
|
|
4464
|
-
}
|
|
4465
|
-
const manifestPath = join7(absPath, "zammy-plugin.json");
|
|
4466
|
-
if (!existsSync9(manifestPath)) {
|
|
4467
|
-
return { success: false, error: "No zammy-plugin.json found in source directory" };
|
|
4468
|
-
}
|
|
4469
|
-
const manifestContent = readFileSync8(manifestPath, "utf-8");
|
|
4470
|
-
let manifest;
|
|
4471
|
-
try {
|
|
4472
|
-
manifest = JSON.parse(manifestContent);
|
|
4473
|
-
} catch {
|
|
4474
|
-
return { success: false, error: "Invalid JSON in zammy-plugin.json" };
|
|
4475
|
-
}
|
|
4476
|
-
const validation = validateManifest(manifest);
|
|
4477
|
-
if (!validation.valid) {
|
|
4478
|
-
return { success: false, error: `Invalid manifest: ${validation.errors.join(", ")}` };
|
|
4479
|
-
}
|
|
4480
|
-
const versionCheck = checkVersionCompatibility2(manifest);
|
|
4481
|
-
if (!versionCheck.compatible) {
|
|
4482
|
-
return { success: false, error: versionCheck.reason };
|
|
4483
|
-
}
|
|
4484
|
-
const mainPath = join7(absPath, manifest.main);
|
|
4485
|
-
if (!existsSync9(mainPath)) {
|
|
4486
|
-
return { success: false, error: `Entry point not found: ${manifest.main}` };
|
|
4487
|
-
}
|
|
4488
|
-
ensurePluginsDir();
|
|
4489
|
-
const targetDir = join7(getPluginsDir(), manifest.name);
|
|
4490
|
-
if (existsSync9(targetDir)) {
|
|
4491
|
-
rmSync(targetDir, { recursive: true, force: true });
|
|
4492
|
-
}
|
|
4493
|
-
cpSync(absPath, targetDir, { recursive: true });
|
|
4494
|
-
return { success: true, manifest };
|
|
4495
|
-
} catch (error) {
|
|
4496
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
4497
|
-
return { success: false, error: message };
|
|
4498
|
-
}
|
|
4499
|
-
}
|
|
4500
|
-
async function installFromNpm(packageName) {
|
|
4501
|
-
const tempDir = join7(tmpdir(), `zammy-plugin-${Date.now()}`);
|
|
4502
|
-
try {
|
|
4503
|
-
mkdirSync3(tempDir, { recursive: true });
|
|
4504
|
-
console.log(theme.dim(` Downloading ${packageName}...`));
|
|
4505
|
-
execSync2(`npm pack ${packageName} --pack-destination="${tempDir}"`, {
|
|
4506
|
-
encoding: "utf-8",
|
|
4507
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
4508
|
-
timeout: 6e4
|
|
4509
|
-
});
|
|
4510
|
-
const files = readdirSync3(tempDir);
|
|
4511
|
-
const tarball = files.find((f) => f.endsWith(".tgz"));
|
|
4512
|
-
if (!tarball) {
|
|
4513
|
-
return { success: false, error: "Failed to download package" };
|
|
4514
|
-
}
|
|
4515
|
-
const extractDir = join7(tempDir, "extract");
|
|
4516
|
-
mkdirSync3(extractDir);
|
|
4517
|
-
await extractTarGz(join7(tempDir, tarball), extractDir);
|
|
4518
|
-
const packageDir = join7(extractDir, "package");
|
|
4519
|
-
if (!existsSync9(packageDir)) {
|
|
4520
|
-
return { success: false, error: "Invalid package structure" };
|
|
4521
|
-
}
|
|
4522
|
-
return await installFromLocal(packageDir);
|
|
4523
|
-
} catch (error) {
|
|
4524
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
4525
|
-
return { success: false, error: `npm install failed: ${message}` };
|
|
4526
|
-
} finally {
|
|
4527
|
-
try {
|
|
4528
|
-
rmSync(tempDir, { recursive: true, force: true });
|
|
4529
|
-
} catch {
|
|
4530
|
-
}
|
|
4531
|
-
}
|
|
4532
|
-
}
|
|
4533
|
-
async function installFromGithub(repo) {
|
|
4534
|
-
const tempDir = join7(tmpdir(), `zammy-plugin-${Date.now()}`);
|
|
4535
|
-
try {
|
|
4536
|
-
let repoPath = repo.replace(/^github:/, "");
|
|
4537
|
-
let branch = "main";
|
|
4538
|
-
if (repoPath.includes("#")) {
|
|
4539
|
-
[repoPath, branch] = repoPath.split("#");
|
|
4540
|
-
}
|
|
4541
|
-
mkdirSync3(tempDir, { recursive: true });
|
|
4542
|
-
console.log(theme.dim(` Cloning ${repoPath}...`));
|
|
4543
|
-
execSync2(`git clone --depth 1 --branch ${branch} https://github.com/${repoPath}.git "${tempDir}"`, {
|
|
4544
|
-
encoding: "utf-8",
|
|
4545
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
4546
|
-
timeout: 12e4
|
|
4547
|
-
});
|
|
4548
|
-
const pkgJsonPath = join7(tempDir, "package.json");
|
|
4549
|
-
if (existsSync9(pkgJsonPath)) {
|
|
4550
|
-
const pkgJson = JSON.parse(readFileSync8(pkgJsonPath, "utf-8"));
|
|
4551
|
-
if (pkgJson.scripts?.build) {
|
|
4552
|
-
console.log(theme.dim(` Installing dependencies...`));
|
|
4553
|
-
execSync2("npm install", { cwd: tempDir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 12e4 });
|
|
4554
|
-
console.log(theme.dim(` Building...`));
|
|
4555
|
-
execSync2("npm run build", { cwd: tempDir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 12e4 });
|
|
4556
|
-
}
|
|
4557
|
-
}
|
|
4558
|
-
return await installFromLocal(tempDir);
|
|
4559
|
-
} catch (error) {
|
|
4560
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
4561
|
-
return { success: false, error: `GitHub install failed: ${message}` };
|
|
4562
|
-
} finally {
|
|
4563
|
-
try {
|
|
4564
|
-
rmSync(tempDir, { recursive: true, force: true });
|
|
4565
|
-
} catch {
|
|
4566
|
-
}
|
|
4567
|
-
}
|
|
3851
|
+
};
|
|
3852
|
+
stdin.once("data", onData);
|
|
3853
|
+
});
|
|
4568
3854
|
}
|
|
4569
|
-
async function
|
|
4570
|
-
const
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
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
|
+
}
|
|
4587
3898
|
}
|
|
4588
|
-
}
|
|
4589
|
-
|
|
4590
|
-
}
|
|
4591
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
4592
|
-
return { success: false, error: `Git install failed: ${message}` };
|
|
4593
|
-
} finally {
|
|
4594
|
-
try {
|
|
4595
|
-
rmSync(tempDir, { recursive: true, force: true });
|
|
4596
|
-
} catch {
|
|
4597
|
-
}
|
|
4598
|
-
}
|
|
4599
|
-
}
|
|
4600
|
-
function removePlugin(name) {
|
|
4601
|
-
try {
|
|
4602
|
-
const pluginDir = join7(getPluginsDir(), name);
|
|
4603
|
-
if (!existsSync9(pluginDir)) {
|
|
4604
|
-
return { success: false, error: `Plugin '${name}' not found` };
|
|
4605
|
-
}
|
|
4606
|
-
rmSync(pluginDir, { recursive: true, force: true });
|
|
4607
|
-
return { success: true };
|
|
4608
|
-
} catch (error) {
|
|
4609
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
4610
|
-
return { success: false, error: message };
|
|
4611
|
-
}
|
|
4612
|
-
}
|
|
4613
|
-
function detectSourceType(source) {
|
|
4614
|
-
if (source.startsWith("./") || source.startsWith("/") || source.startsWith("..") || /^[A-Za-z]:/.test(source)) {
|
|
4615
|
-
return "local";
|
|
4616
|
-
}
|
|
4617
|
-
if (source.startsWith("github:")) {
|
|
4618
|
-
return "github";
|
|
4619
|
-
}
|
|
4620
|
-
if (source.includes("github.com")) {
|
|
4621
|
-
return "github";
|
|
4622
|
-
}
|
|
4623
|
-
if (source.endsWith(".git") || source.startsWith("git@") || source.startsWith("git://")) {
|
|
4624
|
-
return "git";
|
|
4625
|
-
}
|
|
4626
|
-
if (/^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(source)) {
|
|
4627
|
-
return "npm";
|
|
4628
|
-
}
|
|
4629
|
-
return "unknown";
|
|
3899
|
+
};
|
|
3900
|
+
stdin.on("data", onData);
|
|
3901
|
+
});
|
|
4630
3902
|
}
|
|
4631
3903
|
|
|
4632
3904
|
// src/commands/plugin/install.ts
|
|
4633
|
-
import * as readline from "readline";
|
|
4634
|
-
async function confirm(message) {
|
|
4635
|
-
const rl = readline.createInterface({
|
|
4636
|
-
input: process.stdin,
|
|
4637
|
-
output: process.stdout
|
|
4638
|
-
});
|
|
4639
|
-
return new Promise((resolve6) => {
|
|
4640
|
-
rl.question(`${message} [y/N] `, (answer) => {
|
|
4641
|
-
rl.close();
|
|
4642
|
-
resolve6(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
4643
|
-
});
|
|
4644
|
-
});
|
|
4645
|
-
}
|
|
4646
3905
|
async function installPlugin(args2) {
|
|
4647
3906
|
const source = args2[0];
|
|
4648
3907
|
if (!source) {
|
|
@@ -4749,19 +4008,6 @@ async function installPlugin(args2) {
|
|
|
4749
4008
|
}
|
|
4750
4009
|
|
|
4751
4010
|
// src/commands/plugin/remove.ts
|
|
4752
|
-
import * as readline2 from "readline";
|
|
4753
|
-
async function confirm2(message) {
|
|
4754
|
-
const rl = readline2.createInterface({
|
|
4755
|
-
input: process.stdin,
|
|
4756
|
-
output: process.stdout
|
|
4757
|
-
});
|
|
4758
|
-
return new Promise((resolve6) => {
|
|
4759
|
-
rl.question(`${message} [y/N] `, (answer) => {
|
|
4760
|
-
rl.close();
|
|
4761
|
-
resolve6(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
4762
|
-
});
|
|
4763
|
-
});
|
|
4764
|
-
}
|
|
4765
4011
|
async function removePluginCommand(args2) {
|
|
4766
4012
|
const forceIndex = args2.findIndex((a) => a === "-y" || a === "--yes");
|
|
4767
4013
|
const skipConfirm = forceIndex !== -1;
|
|
@@ -4809,7 +4055,7 @@ async function removePluginCommand(args2) {
|
|
|
4809
4055
|
console.log(` ${theme.dim("Commands:")} ${plugin.commands.map((c) => "/" + c).join(", ")}`);
|
|
4810
4056
|
console.log("");
|
|
4811
4057
|
if (!skipConfirm) {
|
|
4812
|
-
const proceed = await
|
|
4058
|
+
const proceed = await confirm(` ${theme.warning("Remove this plugin?")}`);
|
|
4813
4059
|
if (!proceed) {
|
|
4814
4060
|
console.log(theme.dim(" Removal cancelled"));
|
|
4815
4061
|
return;
|
|
@@ -4828,22 +4074,8 @@ async function removePluginCommand(args2) {
|
|
|
4828
4074
|
}
|
|
4829
4075
|
|
|
4830
4076
|
// src/commands/plugin/create.ts
|
|
4831
|
-
import { existsSync as
|
|
4832
|
-
import { join as
|
|
4833
|
-
import * as readline3 from "readline";
|
|
4834
|
-
async function prompt(message, defaultValue) {
|
|
4835
|
-
const rl = readline3.createInterface({
|
|
4836
|
-
input: process.stdin,
|
|
4837
|
-
output: process.stdout
|
|
4838
|
-
});
|
|
4839
|
-
const suffix = defaultValue ? ` ${theme.dim(`(${defaultValue})`)}` : "";
|
|
4840
|
-
return new Promise((resolvePromise) => {
|
|
4841
|
-
rl.question(` ${message}${suffix}: `, (answer) => {
|
|
4842
|
-
rl.close();
|
|
4843
|
-
resolvePromise(answer.trim() || defaultValue || "");
|
|
4844
|
-
});
|
|
4845
|
-
});
|
|
4846
|
-
}
|
|
4077
|
+
import { existsSync as existsSync7, mkdirSync, writeFileSync as writeFileSync3 } from "fs";
|
|
4078
|
+
import { join as join4, resolve as resolve3 } from "path";
|
|
4847
4079
|
function generateManifest(name, displayName, description, commandName) {
|
|
4848
4080
|
return JSON.stringify({
|
|
4849
4081
|
name,
|
|
@@ -4865,12 +4097,17 @@ function generatePackageJson(name, description) {
|
|
|
4865
4097
|
description,
|
|
4866
4098
|
type: "module",
|
|
4867
4099
|
main: "dist/index.js",
|
|
4100
|
+
types: "dist/index.d.ts",
|
|
4868
4101
|
scripts: {
|
|
4869
4102
|
build: "tsc",
|
|
4870
4103
|
dev: "tsc --watch"
|
|
4871
4104
|
},
|
|
4872
|
-
keywords: ["zammy-plugin"],
|
|
4105
|
+
keywords: ["zammy-plugin", "zammy", "cli", "plugin"],
|
|
4106
|
+
peerDependencies: {
|
|
4107
|
+
zammy: "^1.3.0"
|
|
4108
|
+
},
|
|
4873
4109
|
devDependencies: {
|
|
4110
|
+
zammy: "^1.3.0",
|
|
4874
4111
|
typescript: "^5.3.0"
|
|
4875
4112
|
}
|
|
4876
4113
|
}, null, 2);
|
|
@@ -4894,65 +4131,7 @@ function generateTsConfig() {
|
|
|
4894
4131
|
function generateEntryPoint(commandName, displayName) {
|
|
4895
4132
|
return `// ${displayName} - A zammy plugin
|
|
4896
4133
|
|
|
4897
|
-
|
|
4898
|
-
interface Command {
|
|
4899
|
-
name: string;
|
|
4900
|
-
description: string;
|
|
4901
|
-
usage: string;
|
|
4902
|
-
execute: (args: string[]) => Promise<void>;
|
|
4903
|
-
}
|
|
4904
|
-
|
|
4905
|
-
interface PluginAPI {
|
|
4906
|
-
registerCommand(command: Command): void;
|
|
4907
|
-
ui: {
|
|
4908
|
-
theme: {
|
|
4909
|
-
primary: (text: string) => string;
|
|
4910
|
-
secondary: (text: string) => string;
|
|
4911
|
-
accent: (text: string) => string;
|
|
4912
|
-
success: (text: string) => string;
|
|
4913
|
-
warning: (text: string) => string;
|
|
4914
|
-
error: (text: string) => string;
|
|
4915
|
-
info: (text: string) => string;
|
|
4916
|
-
dim: (text: string) => string;
|
|
4917
|
-
gradient: (text: string) => string;
|
|
4918
|
-
};
|
|
4919
|
-
symbols: {
|
|
4920
|
-
check: string;
|
|
4921
|
-
cross: string;
|
|
4922
|
-
star: string;
|
|
4923
|
-
arrow: string;
|
|
4924
|
-
bullet: string;
|
|
4925
|
-
folder: string;
|
|
4926
|
-
file: string;
|
|
4927
|
-
warning: string;
|
|
4928
|
-
info: string;
|
|
4929
|
-
rocket: string;
|
|
4930
|
-
sparkles: string;
|
|
4931
|
-
};
|
|
4932
|
-
};
|
|
4933
|
-
storage: {
|
|
4934
|
-
get<T>(key: string): T | undefined;
|
|
4935
|
-
set<T>(key: string, value: T): void;
|
|
4936
|
-
delete(key: string): void;
|
|
4937
|
-
};
|
|
4938
|
-
log: {
|
|
4939
|
-
info(message: string): void;
|
|
4940
|
-
warn(message: string): void;
|
|
4941
|
-
error(message: string): void;
|
|
4942
|
-
};
|
|
4943
|
-
context: {
|
|
4944
|
-
pluginName: string;
|
|
4945
|
-
pluginVersion: string;
|
|
4946
|
-
zammyVersion: string;
|
|
4947
|
-
dataDir: string;
|
|
4948
|
-
cwd: string;
|
|
4949
|
-
};
|
|
4950
|
-
}
|
|
4951
|
-
|
|
4952
|
-
interface ZammyPlugin {
|
|
4953
|
-
activate(api: PluginAPI): Promise<void> | void;
|
|
4954
|
-
deactivate?(): Promise<void> | void;
|
|
4955
|
-
}
|
|
4134
|
+
import type { PluginAPI, ZammyPlugin } from 'zammy/plugins';
|
|
4956
4135
|
|
|
4957
4136
|
const plugin: ZammyPlugin = {
|
|
4958
4137
|
activate(api: PluginAPI) {
|
|
@@ -5033,22 +4212,22 @@ async function createPlugin(args2) {
|
|
|
5033
4212
|
const displayName = await prompt("Display name", name.replace(/^zammy-plugin-/, "").replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()));
|
|
5034
4213
|
const description = await prompt("Description", "A zammy plugin");
|
|
5035
4214
|
const commandName = await prompt("Main command name", name.replace(/^zammy-plugin-/, "").replace(/-/g, ""));
|
|
5036
|
-
const targetDir =
|
|
5037
|
-
if (
|
|
4215
|
+
const targetDir = resolve3(process.cwd(), name);
|
|
4216
|
+
if (existsSync7(targetDir)) {
|
|
5038
4217
|
console.log(theme.error(` ${symbols.cross} Directory already exists: ${name}`));
|
|
5039
4218
|
return;
|
|
5040
4219
|
}
|
|
5041
4220
|
console.log("");
|
|
5042
4221
|
console.log(theme.dim(` Creating plugin in ${targetDir}...`));
|
|
5043
4222
|
try {
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
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));
|
|
5052
4231
|
console.log("");
|
|
5053
4232
|
console.log(` ${symbols.check} ${theme.success("Plugin created successfully!")}`);
|
|
5054
4233
|
console.log("");
|
|
@@ -5121,14 +4300,14 @@ registerCommand({
|
|
|
5121
4300
|
});
|
|
5122
4301
|
|
|
5123
4302
|
// src/cli.ts
|
|
5124
|
-
import { exec, execSync
|
|
5125
|
-
import { existsSync as
|
|
5126
|
-
import { resolve as
|
|
5127
|
-
import { homedir as
|
|
5128
|
-
import
|
|
5129
|
-
var
|
|
4303
|
+
import { exec, execSync, spawn } from "child_process";
|
|
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";
|
|
4306
|
+
import { homedir as homedir3, platform as platform2, networkInterfaces } from "os";
|
|
4307
|
+
import chalk4 from "chalk";
|
|
4308
|
+
var isWindows = platform2() === "win32";
|
|
5130
4309
|
function translateCommand(cmd) {
|
|
5131
|
-
if (!
|
|
4310
|
+
if (!isWindows) return cmd;
|
|
5132
4311
|
const parts = cmd.trim().split(/\s+/);
|
|
5133
4312
|
const command = parts[0].toLowerCase();
|
|
5134
4313
|
const args2 = parts.slice(1);
|
|
@@ -5180,16 +4359,16 @@ function translateCommand(cmd) {
|
|
|
5180
4359
|
function handleCd(args2) {
|
|
5181
4360
|
let targetPath = args2.trim();
|
|
5182
4361
|
if (!targetPath || targetPath === "~") {
|
|
5183
|
-
targetPath =
|
|
4362
|
+
targetPath = homedir3();
|
|
5184
4363
|
} else if (targetPath.startsWith("~/")) {
|
|
5185
|
-
targetPath =
|
|
4364
|
+
targetPath = resolve4(homedir3(), targetPath.slice(2));
|
|
5186
4365
|
} else if (targetPath === "-") {
|
|
5187
4366
|
console.log(theme.dim(process.cwd()));
|
|
5188
4367
|
return;
|
|
5189
4368
|
} else {
|
|
5190
|
-
targetPath =
|
|
4369
|
+
targetPath = resolve4(process.cwd(), targetPath);
|
|
5191
4370
|
}
|
|
5192
|
-
if (!
|
|
4371
|
+
if (!existsSync8(targetPath)) {
|
|
5193
4372
|
console.log(`${miniSlime.sad} ${theme.error(`Directory not found: ${targetPath}`)}`);
|
|
5194
4373
|
return;
|
|
5195
4374
|
}
|
|
@@ -5209,13 +4388,13 @@ function handlePwd() {
|
|
|
5209
4388
|
console.log(theme.primary(process.cwd()));
|
|
5210
4389
|
}
|
|
5211
4390
|
function handleCat(args2) {
|
|
5212
|
-
const filePath =
|
|
5213
|
-
if (!
|
|
4391
|
+
const filePath = resolve4(process.cwd(), args2.trim());
|
|
4392
|
+
if (!existsSync8(filePath)) {
|
|
5214
4393
|
console.log(`${miniSlime.sad} ${theme.error(`File not found: ${args2}`)}`);
|
|
5215
4394
|
return;
|
|
5216
4395
|
}
|
|
5217
4396
|
try {
|
|
5218
|
-
const content =
|
|
4397
|
+
const content = readFileSync5(filePath, "utf-8");
|
|
5219
4398
|
const ext = extname(filePath).toLowerCase();
|
|
5220
4399
|
if ([".js", ".ts", ".jsx", ".tsx", ".json", ".css", ".html", ".py", ".go", ".rs"].includes(ext)) {
|
|
5221
4400
|
console.log(highlightSyntax(content, ext));
|
|
@@ -5232,13 +4411,13 @@ function highlightSyntax(content, ext) {
|
|
|
5232
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"]
|
|
5233
4412
|
};
|
|
5234
4413
|
const kw = ext === ".py" ? keywords.py : keywords.js;
|
|
5235
|
-
return content.split(
|
|
5236
|
-
line = line.replace(/(["'`])(?:(?!\1)[^\\]|\\.)*?\1/g, (match) =>
|
|
5237
|
-
line = line.replace(/(\/\/.*$|#.*$)/g, (match) =>
|
|
5238
|
-
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));
|
|
5239
4418
|
kw.forEach((keyword) => {
|
|
5240
4419
|
const regex = new RegExp(`\\b(${keyword})\\b`, "g");
|
|
5241
|
-
line = line.replace(regex,
|
|
4420
|
+
line = line.replace(regex, chalk4.hex("#C678DD")(keyword));
|
|
5242
4421
|
});
|
|
5243
4422
|
return line;
|
|
5244
4423
|
}).join("\n");
|
|
@@ -5303,24 +4482,24 @@ var fileIcons = {
|
|
|
5303
4482
|
"default": { icon: "\u{1F4C4}", color: "#6C7A89" }
|
|
5304
4483
|
};
|
|
5305
4484
|
function formatSize(bytes) {
|
|
5306
|
-
if (bytes === 0) return
|
|
4485
|
+
if (bytes === 0) return chalk4.dim(" 0 B");
|
|
5307
4486
|
const units = ["B", "KB", "MB", "GB", "TB"];
|
|
5308
4487
|
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
5309
4488
|
const size = (bytes / Math.pow(1024, i)).toFixed(i > 0 ? 1 : 0);
|
|
5310
|
-
return
|
|
4489
|
+
return chalk4.hex("#98C379")(size.padStart(5) + " " + units[i].padEnd(2));
|
|
5311
4490
|
}
|
|
5312
4491
|
function handleLs(args2) {
|
|
5313
4492
|
const parts = args2.trim().split(/\s+/).filter(Boolean);
|
|
5314
4493
|
const showAll = parts.some((a) => a === "-a" || a === "-la" || a === "-al");
|
|
5315
4494
|
const showLong = parts.some((a) => a === "-l" || a === "-la" || a === "-al");
|
|
5316
4495
|
const pathArgs = parts.filter((a) => !a.startsWith("-"));
|
|
5317
|
-
const targetPath = pathArgs.length > 0 ?
|
|
5318
|
-
if (!
|
|
4496
|
+
const targetPath = pathArgs.length > 0 ? resolve4(process.cwd(), pathArgs[0]) : process.cwd();
|
|
4497
|
+
if (!existsSync8(targetPath)) {
|
|
5319
4498
|
console.log(theme.error(`Directory not found: ${targetPath}`));
|
|
5320
4499
|
return;
|
|
5321
4500
|
}
|
|
5322
4501
|
try {
|
|
5323
|
-
const entries =
|
|
4502
|
+
const entries = readdirSync2(targetPath, { withFileTypes: true });
|
|
5324
4503
|
const filtered = showAll ? entries : entries.filter((e) => !e.name.startsWith("."));
|
|
5325
4504
|
console.log("");
|
|
5326
4505
|
console.log(theme.dim(` ${targetPath}`));
|
|
@@ -5336,7 +4515,7 @@ function handleLs(args2) {
|
|
|
5336
4515
|
return a.name.localeCompare(b3.name);
|
|
5337
4516
|
});
|
|
5338
4517
|
for (const entry of sorted) {
|
|
5339
|
-
const fullPath =
|
|
4518
|
+
const fullPath = resolve4(targetPath, entry.name);
|
|
5340
4519
|
const isDir = entry.isDirectory();
|
|
5341
4520
|
const ext = isDir ? "dir" : extname(entry.name).toLowerCase();
|
|
5342
4521
|
const iconInfo = fileIcons[ext] || fileIcons["default"];
|
|
@@ -5344,14 +4523,14 @@ function handleLs(args2) {
|
|
|
5344
4523
|
if (showLong) {
|
|
5345
4524
|
try {
|
|
5346
4525
|
const stats = statSync2(fullPath);
|
|
5347
|
-
const size = isDir ?
|
|
4526
|
+
const size = isDir ? chalk4.dim(" <DIR>") : formatSize(stats.size);
|
|
5348
4527
|
const date = stats.mtime.toLocaleDateString("en-US", { month: "short", day: "2-digit", year: "numeric" });
|
|
5349
|
-
line +=
|
|
4528
|
+
line += chalk4.dim(date.padEnd(13)) + size + " ";
|
|
5350
4529
|
} catch {
|
|
5351
|
-
line +=
|
|
4530
|
+
line += chalk4.dim(" ") + " ";
|
|
5352
4531
|
}
|
|
5353
4532
|
}
|
|
5354
|
-
const name = isDir ?
|
|
4533
|
+
const name = isDir ? chalk4.hex(iconInfo.color).bold(entry.name + "/") : chalk4.hex(iconInfo.color)(entry.name);
|
|
5355
4534
|
line += name;
|
|
5356
4535
|
console.log(line);
|
|
5357
4536
|
}
|
|
@@ -5365,19 +4544,19 @@ function handleLs(args2) {
|
|
|
5365
4544
|
function handleTree(args2, maxDepth = 3) {
|
|
5366
4545
|
const parts = args2.trim().split(/\s+/).filter(Boolean);
|
|
5367
4546
|
const pathArgs = parts.filter((a) => !a.startsWith("-"));
|
|
5368
|
-
const targetPath = pathArgs.length > 0 ?
|
|
5369
|
-
if (!
|
|
4547
|
+
const targetPath = pathArgs.length > 0 ? resolve4(process.cwd(), pathArgs[0]) : process.cwd();
|
|
4548
|
+
if (!existsSync8(targetPath)) {
|
|
5370
4549
|
console.log(theme.error(`Directory not found: ${targetPath}`));
|
|
5371
4550
|
return;
|
|
5372
4551
|
}
|
|
5373
4552
|
console.log("");
|
|
5374
|
-
console.log(theme.primary(` \u{1F4C1} ${
|
|
4553
|
+
console.log(theme.primary(` \u{1F4C1} ${basename3(targetPath)}/`));
|
|
5375
4554
|
let dirCount = 0;
|
|
5376
4555
|
let fileCount = 0;
|
|
5377
4556
|
function printTree(dir, prefix, depth) {
|
|
5378
4557
|
if (depth > maxDepth) return;
|
|
5379
4558
|
try {
|
|
5380
|
-
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) => {
|
|
5381
4560
|
if (a.isDirectory() && !b3.isDirectory()) return -1;
|
|
5382
4561
|
if (!a.isDirectory() && b3.isDirectory()) return 1;
|
|
5383
4562
|
return a.name.localeCompare(b3.name);
|
|
@@ -5389,11 +4568,11 @@ function handleTree(args2, maxDepth = 3) {
|
|
|
5389
4568
|
const iconInfo = fileIcons[ext] || fileIcons["default"];
|
|
5390
4569
|
if (entry.isDirectory()) {
|
|
5391
4570
|
dirCount++;
|
|
5392
|
-
console.log(theme.dim(prefix + connector) + iconInfo.icon + " " +
|
|
5393
|
-
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);
|
|
5394
4573
|
} else {
|
|
5395
4574
|
fileCount++;
|
|
5396
|
-
console.log(theme.dim(prefix + connector) + iconInfo.icon + " " +
|
|
4575
|
+
console.log(theme.dim(prefix + connector) + iconInfo.icon + " " + chalk4.hex(iconInfo.color)(entry.name));
|
|
5397
4576
|
}
|
|
5398
4577
|
});
|
|
5399
4578
|
} catch {
|
|
@@ -5404,18 +4583,18 @@ function handleTree(args2, maxDepth = 3) {
|
|
|
5404
4583
|
console.log(theme.dim(` ${dirCount} directories, ${fileCount} files`));
|
|
5405
4584
|
console.log("");
|
|
5406
4585
|
}
|
|
5407
|
-
var bookmarksFile =
|
|
4586
|
+
var bookmarksFile = join5(homedir3(), ".zammy-bookmarks.json");
|
|
5408
4587
|
function loadBookmarks() {
|
|
5409
4588
|
try {
|
|
5410
|
-
if (
|
|
5411
|
-
return JSON.parse(
|
|
4589
|
+
if (existsSync8(bookmarksFile)) {
|
|
4590
|
+
return JSON.parse(readFileSync5(bookmarksFile, "utf-8"));
|
|
5412
4591
|
}
|
|
5413
4592
|
} catch {
|
|
5414
4593
|
}
|
|
5415
4594
|
return {};
|
|
5416
4595
|
}
|
|
5417
4596
|
function saveBookmarks(bookmarks) {
|
|
5418
|
-
|
|
4597
|
+
writeFileSync4(bookmarksFile, JSON.stringify(bookmarks, null, 2));
|
|
5419
4598
|
}
|
|
5420
4599
|
function handleBookmark(args2) {
|
|
5421
4600
|
const parts = args2.trim().split(/\s+/);
|
|
@@ -5471,7 +4650,7 @@ function handleBookmark(args2) {
|
|
|
5471
4650
|
console.log(theme.primary(" \u{1F4CD} Directory Bookmarks"));
|
|
5472
4651
|
console.log("");
|
|
5473
4652
|
for (const key of keys.sort()) {
|
|
5474
|
-
const exists =
|
|
4653
|
+
const exists = existsSync8(bookmarks[key]);
|
|
5475
4654
|
const status = exists ? theme.success(symbols.check) : theme.error(symbols.cross);
|
|
5476
4655
|
console.log(` ${status} ${theme.primary(key.padEnd(15))} ${theme.dim("\u2192")} ${bookmarks[key]}`);
|
|
5477
4656
|
}
|
|
@@ -5488,10 +4667,10 @@ function handleFind(args2) {
|
|
|
5488
4667
|
function searchDir(dir, depth = 0) {
|
|
5489
4668
|
if (depth > 5 || results.length >= maxResults) return;
|
|
5490
4669
|
try {
|
|
5491
|
-
const entries =
|
|
4670
|
+
const entries = readdirSync2(dir, { withFileTypes: true });
|
|
5492
4671
|
for (const entry of entries) {
|
|
5493
4672
|
if (entry.name.startsWith(".") || ["node_modules", ".git", "dist", "build"].includes(entry.name)) continue;
|
|
5494
|
-
const fullPath =
|
|
4673
|
+
const fullPath = resolve4(dir, entry.name);
|
|
5495
4674
|
const matchPattern = pattern.replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
5496
4675
|
const regex = new RegExp(matchPattern, "i");
|
|
5497
4676
|
if (regex.test(entry.name)) {
|
|
@@ -5515,9 +4694,9 @@ function handleFind(args2) {
|
|
|
5515
4694
|
const relativePath = result.path.replace(searchPath, ".").replace(/\\/g, "/");
|
|
5516
4695
|
const ext = result.isDir ? "dir" : extname(result.path).toLowerCase();
|
|
5517
4696
|
const iconInfo = fileIcons[ext] || fileIcons["default"];
|
|
5518
|
-
const fileName =
|
|
4697
|
+
const fileName = basename3(result.path);
|
|
5519
4698
|
const dirPath = relativePath.slice(0, -fileName.length);
|
|
5520
|
-
console.log(` ${iconInfo.icon} ${theme.dim(dirPath)}${
|
|
4699
|
+
console.log(` ${iconInfo.icon} ${theme.dim(dirPath)}${chalk4.hex(iconInfo.color)(fileName)}${result.isDir ? "/" : ""}`);
|
|
5521
4700
|
}
|
|
5522
4701
|
if (results.length >= maxResults) {
|
|
5523
4702
|
console.log("");
|
|
@@ -5527,8 +4706,8 @@ function handleFind(args2) {
|
|
|
5527
4706
|
console.log("");
|
|
5528
4707
|
}
|
|
5529
4708
|
function handleDu(args2) {
|
|
5530
|
-
const targetPath = args2.trim() ?
|
|
5531
|
-
if (!
|
|
4709
|
+
const targetPath = args2.trim() ? resolve4(process.cwd(), args2.trim()) : process.cwd();
|
|
4710
|
+
if (!existsSync8(targetPath)) {
|
|
5532
4711
|
console.log(theme.error(` Path not found: ${targetPath}`));
|
|
5533
4712
|
return;
|
|
5534
4713
|
}
|
|
@@ -5536,10 +4715,10 @@ function handleDu(args2) {
|
|
|
5536
4715
|
console.log("");
|
|
5537
4716
|
console.log(theme.dim(" Calculating sizes..."));
|
|
5538
4717
|
try {
|
|
5539
|
-
const entries =
|
|
4718
|
+
const entries = readdirSync2(targetPath, { withFileTypes: true });
|
|
5540
4719
|
for (const entry of entries) {
|
|
5541
4720
|
if (entry.name.startsWith(".")) continue;
|
|
5542
|
-
const fullPath =
|
|
4721
|
+
const fullPath = resolve4(targetPath, entry.name);
|
|
5543
4722
|
let size = 0;
|
|
5544
4723
|
let skipped = false;
|
|
5545
4724
|
try {
|
|
@@ -5565,7 +4744,7 @@ function handleDu(args2) {
|
|
|
5565
4744
|
items.sort((a, b3) => b3.size - a.size);
|
|
5566
4745
|
const totalSize = items.reduce((sum, item) => sum + item.size, 0);
|
|
5567
4746
|
console.log("");
|
|
5568
|
-
console.log(theme.primary(` \u{1F4CA} Disk Usage: ${
|
|
4747
|
+
console.log(theme.primary(` \u{1F4CA} Disk Usage: ${basename3(targetPath)}`));
|
|
5569
4748
|
console.log(theme.dim(` Total: ${formatSizeSimple(totalSize)}`));
|
|
5570
4749
|
console.log("");
|
|
5571
4750
|
const maxItems = 15;
|
|
@@ -5579,10 +4758,10 @@ function handleDu(args2) {
|
|
|
5579
4758
|
const percent = totalSize > 0 ? item.size / totalSize * 100 : 0;
|
|
5580
4759
|
const barWidth = 20;
|
|
5581
4760
|
const filled = Math.round(percent / 100 * barWidth);
|
|
5582
|
-
const bar =
|
|
4761
|
+
const bar = chalk4.hex("#4ECDC4")("\u2588".repeat(filled)) + chalk4.dim("\u2591".repeat(barWidth - filled));
|
|
5583
4762
|
const icon = item.isDir ? "\u{1F4C1}" : "\u{1F4C4}";
|
|
5584
4763
|
const name = item.name.length > 25 ? item.name.slice(0, 22) + "..." : item.name.padEnd(25);
|
|
5585
|
-
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)}%`)}`);
|
|
5586
4765
|
}
|
|
5587
4766
|
if (items.length > maxItems) {
|
|
5588
4767
|
console.log(theme.dim(` ... and ${items.length - maxItems} more items`));
|
|
@@ -5598,10 +4777,10 @@ function getDirSize2(dir, depth = 0, maxDepth = 4) {
|
|
|
5598
4777
|
if (depth > maxDepth) return 0;
|
|
5599
4778
|
let size = 0;
|
|
5600
4779
|
try {
|
|
5601
|
-
const entries =
|
|
4780
|
+
const entries = readdirSync2(dir, { withFileTypes: true });
|
|
5602
4781
|
for (const entry of entries) {
|
|
5603
4782
|
if (skipDirs.has(entry.name)) continue;
|
|
5604
|
-
const fullPath =
|
|
4783
|
+
const fullPath = resolve4(dir, entry.name);
|
|
5605
4784
|
if (entry.isDirectory()) {
|
|
5606
4785
|
size += getDirSize2(fullPath, depth + 1, maxDepth);
|
|
5607
4786
|
} else {
|
|
@@ -5625,7 +4804,7 @@ function handleGit(args2) {
|
|
|
5625
4804
|
const subcommand = args2.trim().split(/\s+/)[0] || "status";
|
|
5626
4805
|
console.log("");
|
|
5627
4806
|
try {
|
|
5628
|
-
|
|
4807
|
+
execSync("git rev-parse --is-inside-work-tree", { stdio: "pipe", timeout: 5e3 });
|
|
5629
4808
|
} catch {
|
|
5630
4809
|
console.log(theme.error(" Not a git repository"));
|
|
5631
4810
|
console.log("");
|
|
@@ -5635,10 +4814,10 @@ function handleGit(args2) {
|
|
|
5635
4814
|
switch (subcommand) {
|
|
5636
4815
|
case "status":
|
|
5637
4816
|
case "s": {
|
|
5638
|
-
const branch =
|
|
5639
|
-
console.log(` ${symbols.rocket} ${theme.primary("Branch:")} ${
|
|
4817
|
+
const branch = execSync("git branch --show-current", { encoding: "utf-8", timeout: 5e3 }).trim();
|
|
4818
|
+
console.log(` ${symbols.rocket} ${theme.primary("Branch:")} ${chalk4.hex("#98C379")(branch)}`);
|
|
5640
4819
|
console.log("");
|
|
5641
|
-
const status =
|
|
4820
|
+
const status = execSync("git status --porcelain", { encoding: "utf-8", timeout: 5e3 });
|
|
5642
4821
|
if (!status.trim()) {
|
|
5643
4822
|
console.log(` ${symbols.check} ${theme.success("Working tree clean")}`);
|
|
5644
4823
|
} else {
|
|
@@ -5661,12 +4840,12 @@ function handleGit(args2) {
|
|
|
5661
4840
|
}
|
|
5662
4841
|
if (staged.length > 0) {
|
|
5663
4842
|
console.log(theme.success(" Staged changes:"));
|
|
5664
|
-
staged.forEach((f) => console.log(` ${symbols.check} ${
|
|
4843
|
+
staged.forEach((f) => console.log(` ${symbols.check} ${chalk4.hex("#98C379")(f)}`));
|
|
5665
4844
|
console.log("");
|
|
5666
4845
|
}
|
|
5667
4846
|
if (modified.length > 0) {
|
|
5668
4847
|
console.log(theme.warning(" Modified:"));
|
|
5669
|
-
modified.forEach((f) => console.log(` ${symbols.bullet} ${
|
|
4848
|
+
modified.forEach((f) => console.log(` ${symbols.bullet} ${chalk4.hex("#E5C07B")(f)}`));
|
|
5670
4849
|
console.log("");
|
|
5671
4850
|
}
|
|
5672
4851
|
if (untracked.length > 0) {
|
|
@@ -5675,35 +4854,35 @@ function handleGit(args2) {
|
|
|
5675
4854
|
console.log("");
|
|
5676
4855
|
}
|
|
5677
4856
|
}
|
|
5678
|
-
const log =
|
|
4857
|
+
const log = execSync("git log --oneline -3", { encoding: "utf-8", timeout: 3e3 }).trim();
|
|
5679
4858
|
if (log) {
|
|
5680
4859
|
console.log(theme.dim(" Recent commits:"));
|
|
5681
4860
|
log.split("\n").forEach((line) => {
|
|
5682
4861
|
const [hash, ...msg] = line.split(" ");
|
|
5683
|
-
console.log(` ${
|
|
4862
|
+
console.log(` ${chalk4.hex("#61AFEF")(hash)} ${theme.dim(msg.join(" "))}`);
|
|
5684
4863
|
});
|
|
5685
4864
|
}
|
|
5686
4865
|
break;
|
|
5687
4866
|
}
|
|
5688
4867
|
case "log":
|
|
5689
4868
|
case "l": {
|
|
5690
|
-
const log =
|
|
4869
|
+
const log = execSync("git log --oneline -10", { encoding: "utf-8", timeout: 3e3 }).trim();
|
|
5691
4870
|
console.log(theme.primary(" \u{1F4DC} Recent Commits"));
|
|
5692
4871
|
console.log("");
|
|
5693
4872
|
log.split("\n").forEach((line) => {
|
|
5694
4873
|
const [hash, ...msg] = line.split(" ");
|
|
5695
|
-
console.log(` ${
|
|
4874
|
+
console.log(` ${chalk4.hex("#61AFEF")(hash)} ${msg.join(" ")}`);
|
|
5696
4875
|
});
|
|
5697
4876
|
break;
|
|
5698
4877
|
}
|
|
5699
4878
|
case "branch":
|
|
5700
4879
|
case "b": {
|
|
5701
|
-
const branches =
|
|
4880
|
+
const branches = execSync("git branch -a", { encoding: "utf-8", timeout: 3e3 }).trim();
|
|
5702
4881
|
console.log(theme.primary(" \u{1F33F} Branches"));
|
|
5703
4882
|
console.log("");
|
|
5704
4883
|
branches.split("\n").forEach((line) => {
|
|
5705
4884
|
if (line.startsWith("*")) {
|
|
5706
|
-
console.log(` ${
|
|
4885
|
+
console.log(` ${chalk4.hex("#98C379")(line)}`);
|
|
5707
4886
|
} else {
|
|
5708
4887
|
console.log(` ${theme.dim(line)}`);
|
|
5709
4888
|
}
|
|
@@ -5711,7 +4890,7 @@ function handleGit(args2) {
|
|
|
5711
4890
|
break;
|
|
5712
4891
|
}
|
|
5713
4892
|
default:
|
|
5714
|
-
const result =
|
|
4893
|
+
const result = execSync(`git ${args2}`, { encoding: "utf-8", timeout: 1e4 });
|
|
5715
4894
|
console.log(result);
|
|
5716
4895
|
}
|
|
5717
4896
|
} catch (error) {
|
|
@@ -5720,23 +4899,23 @@ function handleGit(args2) {
|
|
|
5720
4899
|
}
|
|
5721
4900
|
console.log("");
|
|
5722
4901
|
}
|
|
5723
|
-
var isMac =
|
|
5724
|
-
var isLinux =
|
|
4902
|
+
var isMac = platform2() === "darwin";
|
|
4903
|
+
var isLinux = platform2() === "linux";
|
|
5725
4904
|
function getClipboardCopyCmd() {
|
|
5726
|
-
if (
|
|
4905
|
+
if (isWindows) return "clip";
|
|
5727
4906
|
if (isMac) return "pbcopy";
|
|
5728
4907
|
try {
|
|
5729
|
-
|
|
4908
|
+
execSync("which xclip", { stdio: "pipe" });
|
|
5730
4909
|
return "xclip -selection clipboard";
|
|
5731
4910
|
} catch {
|
|
5732
4911
|
return "xsel --clipboard --input";
|
|
5733
4912
|
}
|
|
5734
4913
|
}
|
|
5735
4914
|
function getClipboardPasteCmd() {
|
|
5736
|
-
if (
|
|
4915
|
+
if (isWindows) return 'powershell -command "Get-Clipboard"';
|
|
5737
4916
|
if (isMac) return "pbpaste";
|
|
5738
4917
|
try {
|
|
5739
|
-
|
|
4918
|
+
execSync("which xclip", { stdio: "pipe" });
|
|
5740
4919
|
return "xclip -selection clipboard -o";
|
|
5741
4920
|
} catch {
|
|
5742
4921
|
return "xsel --clipboard --output";
|
|
@@ -5750,10 +4929,10 @@ function handleClipboard(args2) {
|
|
|
5750
4929
|
if (action === "copy" && content) {
|
|
5751
4930
|
try {
|
|
5752
4931
|
const copyCmd = getClipboardCopyCmd();
|
|
5753
|
-
if (
|
|
5754
|
-
|
|
4932
|
+
if (isWindows) {
|
|
4933
|
+
execSync(`echo ${content} | ${copyCmd}`, { stdio: "pipe", timeout: 3e3 });
|
|
5755
4934
|
} else {
|
|
5756
|
-
|
|
4935
|
+
execSync(`echo "${content}" | ${copyCmd}`, { stdio: "pipe", timeout: 3e3 });
|
|
5757
4936
|
}
|
|
5758
4937
|
console.log(` ${symbols.check} ${theme.success("Copied to clipboard")}`);
|
|
5759
4938
|
} catch {
|
|
@@ -5765,7 +4944,7 @@ function handleClipboard(args2) {
|
|
|
5765
4944
|
} else if (action === "paste") {
|
|
5766
4945
|
try {
|
|
5767
4946
|
const pasteCmd = getClipboardPasteCmd();
|
|
5768
|
-
const result =
|
|
4947
|
+
const result = execSync(pasteCmd, { encoding: "utf-8", timeout: 3e3 }).trim();
|
|
5769
4948
|
console.log(` ${symbols.clipboard} ${theme.dim("Clipboard contents:")}`);
|
|
5770
4949
|
console.log("");
|
|
5771
4950
|
console.log(result);
|
|
@@ -5776,14 +4955,14 @@ function handleClipboard(args2) {
|
|
|
5776
4955
|
}
|
|
5777
4956
|
}
|
|
5778
4957
|
} else if (action === "file" && parts[1]) {
|
|
5779
|
-
const filePath =
|
|
5780
|
-
if (
|
|
4958
|
+
const filePath = resolve4(process.cwd(), parts[1]);
|
|
4959
|
+
if (existsSync8(filePath)) {
|
|
5781
4960
|
try {
|
|
5782
4961
|
const copyCmd = getClipboardCopyCmd();
|
|
5783
|
-
if (
|
|
5784
|
-
|
|
4962
|
+
if (isWindows) {
|
|
4963
|
+
execSync(`type "${filePath}" | ${copyCmd}`, { stdio: "pipe", timeout: 5e3 });
|
|
5785
4964
|
} else {
|
|
5786
|
-
|
|
4965
|
+
execSync(`cat "${filePath}" | ${copyCmd}`, { stdio: "pipe", timeout: 5e3 });
|
|
5787
4966
|
}
|
|
5788
4967
|
console.log(` ${symbols.check} ${theme.success("File contents copied to clipboard")}`);
|
|
5789
4968
|
} catch {
|
|
@@ -5809,14 +4988,14 @@ function handleClipboard(args2) {
|
|
|
5809
4988
|
console.log("");
|
|
5810
4989
|
}
|
|
5811
4990
|
function handlePretty(args2) {
|
|
5812
|
-
const filePath =
|
|
5813
|
-
if (!
|
|
4991
|
+
const filePath = resolve4(process.cwd(), args2.trim());
|
|
4992
|
+
if (!existsSync8(filePath)) {
|
|
5814
4993
|
console.log(theme.error(` File not found: ${args2}`));
|
|
5815
4994
|
return;
|
|
5816
4995
|
}
|
|
5817
4996
|
console.log("");
|
|
5818
4997
|
try {
|
|
5819
|
-
const content =
|
|
4998
|
+
const content = readFileSync5(filePath, "utf-8");
|
|
5820
4999
|
const ext = extname(filePath).toLowerCase();
|
|
5821
5000
|
if (ext === ".json") {
|
|
5822
5001
|
const parsed = JSON.parse(content);
|
|
@@ -5832,7 +5011,7 @@ function handlePretty(args2) {
|
|
|
5832
5011
|
console.log("");
|
|
5833
5012
|
}
|
|
5834
5013
|
function highlightJson(json) {
|
|
5835
|
-
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));
|
|
5836
5015
|
}
|
|
5837
5016
|
var activeWatcher = null;
|
|
5838
5017
|
function handleWatch(args2) {
|
|
@@ -5863,8 +5042,8 @@ function handleWatch(args2) {
|
|
|
5863
5042
|
console.log("");
|
|
5864
5043
|
return;
|
|
5865
5044
|
}
|
|
5866
|
-
const filePath =
|
|
5867
|
-
if (!
|
|
5045
|
+
const filePath = resolve4(process.cwd(), action);
|
|
5046
|
+
if (!existsSync8(filePath)) {
|
|
5868
5047
|
console.log(theme.error(` File not found: ${action}`));
|
|
5869
5048
|
console.log("");
|
|
5870
5049
|
return;
|
|
@@ -5891,8 +5070,8 @@ function handleWatch(args2) {
|
|
|
5891
5070
|
console.log(theme.dim(' (Type "!watch stop" to stop watching)'));
|
|
5892
5071
|
console.log("");
|
|
5893
5072
|
try {
|
|
5894
|
-
const content =
|
|
5895
|
-
const lines = content.split(
|
|
5073
|
+
const content = readFileSync5(filePath, "utf-8");
|
|
5074
|
+
const lines = content.split(/\r?\n/).slice(-10);
|
|
5896
5075
|
lines.forEach((line) => console.log(theme.dim(line)));
|
|
5897
5076
|
} catch {
|
|
5898
5077
|
console.log(theme.dim(" (Unable to read initial content)"));
|
|
@@ -5900,12 +5079,12 @@ function handleWatch(args2) {
|
|
|
5900
5079
|
watchFile(filePath, { interval: 500 }, (curr, prev) => {
|
|
5901
5080
|
if (curr.size > lastSize) {
|
|
5902
5081
|
try {
|
|
5903
|
-
const newContent =
|
|
5904
|
-
const allLines = newContent.split(
|
|
5082
|
+
const newContent = readFileSync5(filePath, "utf-8");
|
|
5083
|
+
const allLines = newContent.split(/\r?\n/);
|
|
5905
5084
|
const oldLines = Math.floor(prev.size / 50);
|
|
5906
5085
|
const newLines = allLines.slice(-Math.max(1, allLines.length - oldLines));
|
|
5907
5086
|
newLines.forEach((line) => {
|
|
5908
|
-
if (line.trim()) console.log(
|
|
5087
|
+
if (line.trim()) console.log(chalk4.hex("#98C379")(line));
|
|
5909
5088
|
});
|
|
5910
5089
|
} catch {
|
|
5911
5090
|
}
|
|
@@ -5918,12 +5097,12 @@ function handleServe(args2) {
|
|
|
5918
5097
|
console.log("");
|
|
5919
5098
|
console.log(` ${symbols.rocket} ${theme.primary("Starting HTTP server...")}`);
|
|
5920
5099
|
console.log(` ${theme.dim("Serving:")} ${process.cwd()}`);
|
|
5921
|
-
console.log(` ${theme.dim("URL:")} ${
|
|
5100
|
+
console.log(` ${theme.dim("URL:")} ${chalk4.hex("#61AFEF")(`http://localhost:${port}`)}`);
|
|
5922
5101
|
console.log("");
|
|
5923
5102
|
console.log(theme.dim(" Press Ctrl+C to stop"));
|
|
5924
5103
|
console.log("");
|
|
5925
5104
|
try {
|
|
5926
|
-
const npx =
|
|
5105
|
+
const npx = isWindows ? "npx.cmd" : "npx";
|
|
5927
5106
|
spawn(npx, ["serve", "-p", String(port)], {
|
|
5928
5107
|
cwd: process.cwd(),
|
|
5929
5108
|
stdio: "inherit"
|
|
@@ -5938,8 +5117,8 @@ function handlePs() {
|
|
|
5938
5117
|
console.log("");
|
|
5939
5118
|
try {
|
|
5940
5119
|
let result;
|
|
5941
|
-
if (
|
|
5942
|
-
result =
|
|
5120
|
+
if (isWindows) {
|
|
5121
|
+
result = execSync('tasklist /FO CSV /NH | findstr /V "System Idle"', { encoding: "utf-8", timeout: 5e3 });
|
|
5943
5122
|
const lines = result.trim().split("\n").slice(0, 15);
|
|
5944
5123
|
console.log(theme.dim(" Name PID Memory"));
|
|
5945
5124
|
console.log(theme.dim(" \u2500".repeat(25)));
|
|
@@ -5949,11 +5128,11 @@ function handlePs() {
|
|
|
5949
5128
|
const name = parts[0].slice(0, 28).padEnd(30);
|
|
5950
5129
|
const pid = parts[1].padStart(8);
|
|
5951
5130
|
const mem = parts[4];
|
|
5952
|
-
console.log(` ${name}${pid} ${
|
|
5131
|
+
console.log(` ${name}${pid} ${chalk4.hex("#98C379")(mem)}`);
|
|
5953
5132
|
}
|
|
5954
5133
|
});
|
|
5955
5134
|
} else {
|
|
5956
|
-
result =
|
|
5135
|
+
result = execSync("ps aux | head -15", { encoding: "utf-8", timeout: 5e3 });
|
|
5957
5136
|
console.log(result);
|
|
5958
5137
|
}
|
|
5959
5138
|
} catch {
|
|
@@ -5976,7 +5155,7 @@ function handleEnv(args2) {
|
|
|
5976
5155
|
filtered.slice(0, maxShow).forEach((key) => {
|
|
5977
5156
|
const value = env[key] || "";
|
|
5978
5157
|
const displayValue = value.length > 50 ? value.slice(0, 47) + "..." : value;
|
|
5979
|
-
console.log(` ${
|
|
5158
|
+
console.log(` ${chalk4.hex("#E06C75")(key.padEnd(25))} ${theme.dim("=")} ${displayValue}`);
|
|
5980
5159
|
});
|
|
5981
5160
|
if (filtered.length > maxShow) {
|
|
5982
5161
|
console.log(theme.dim(` ... and ${filtered.length - maxShow} more`));
|
|
@@ -6005,22 +5184,22 @@ function handleIp() {
|
|
|
6005
5184
|
if (localIps.length === 0) {
|
|
6006
5185
|
console.log(` ${theme.dim("(No network interfaces found)")}`);
|
|
6007
5186
|
} else {
|
|
6008
|
-
localIps.forEach((ip) => console.log(` ${
|
|
5187
|
+
localIps.forEach((ip) => console.log(` ${chalk4.hex("#98C379")(ip)}`));
|
|
6009
5188
|
}
|
|
6010
5189
|
console.log("");
|
|
6011
5190
|
console.log(theme.dim(" Public IP:"));
|
|
6012
5191
|
try {
|
|
6013
5192
|
let result;
|
|
6014
5193
|
try {
|
|
6015
|
-
result =
|
|
5194
|
+
result = execSync("curl -s ifconfig.me", { encoding: "utf-8", timeout: 5e3 }).trim();
|
|
6016
5195
|
} catch {
|
|
6017
|
-
if (
|
|
6018
|
-
result =
|
|
5196
|
+
if (isWindows) {
|
|
5197
|
+
result = execSync('powershell -command "(Invoke-WebRequest -Uri ifconfig.me -UseBasicParsing).Content"', { encoding: "utf-8", timeout: 5e3 }).trim();
|
|
6019
5198
|
} else {
|
|
6020
5199
|
throw new Error("curl not available");
|
|
6021
5200
|
}
|
|
6022
5201
|
}
|
|
6023
|
-
console.log(` ${
|
|
5202
|
+
console.log(` ${chalk4.hex("#61AFEF")(result)}`);
|
|
6024
5203
|
} catch {
|
|
6025
5204
|
console.log(` ${theme.dim("(Could not fetch - requires curl or internet)")}`);
|
|
6026
5205
|
}
|
|
@@ -6037,21 +5216,21 @@ function handleEpoch(args2) {
|
|
|
6037
5216
|
if (!input || input === "now") {
|
|
6038
5217
|
const now = /* @__PURE__ */ new Date();
|
|
6039
5218
|
console.log(` ${theme.dim("Current Time:")}`);
|
|
6040
|
-
console.log(` ${
|
|
6041
|
-
console.log(` ${
|
|
6042
|
-
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)")}`);
|
|
6043
5222
|
} else if (/^\d{10,13}$/.test(input)) {
|
|
6044
5223
|
const ms = input.length === 10 ? parseInt(input) * 1e3 : parseInt(input);
|
|
6045
5224
|
const date = new Date(ms);
|
|
6046
|
-
console.log(` ${theme.dim("Epoch:")} ${
|
|
6047
|
-
console.log(` ${theme.dim("Date:")} ${
|
|
6048
|
-
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())}`);
|
|
6049
5228
|
} else {
|
|
6050
5229
|
const date = new Date(input);
|
|
6051
5230
|
if (!isNaN(date.getTime())) {
|
|
6052
|
-
console.log(` ${theme.dim("Date:")} ${
|
|
6053
|
-
console.log(` ${theme.dim("Unix:")} ${
|
|
6054
|
-
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)")}`);
|
|
6055
5234
|
} else {
|
|
6056
5235
|
console.log(theme.error(` Cannot parse: ${input}`));
|
|
6057
5236
|
console.log(theme.dim(' Examples: epoch now, epoch 1703788800, epoch "2024-01-01"'));
|
|
@@ -6075,19 +5254,19 @@ async function handleHttp(args2) {
|
|
|
6075
5254
|
return;
|
|
6076
5255
|
}
|
|
6077
5256
|
const fullUrl = url.startsWith("http") ? url : `https://${url}`;
|
|
6078
|
-
console.log(` ${symbols.rocket} ${theme.dim(method)} ${
|
|
5257
|
+
console.log(` ${symbols.rocket} ${theme.dim(method)} ${chalk4.hex("#61AFEF")(fullUrl)}`);
|
|
6079
5258
|
console.log("");
|
|
6080
5259
|
try {
|
|
6081
5260
|
let result;
|
|
6082
5261
|
try {
|
|
6083
5262
|
const curlCmd = method === "HEAD" ? `curl -sI "${fullUrl}"` : `curl -s -X ${method} "${fullUrl}"`;
|
|
6084
|
-
result =
|
|
5263
|
+
result = execSync(curlCmd, { encoding: "utf-8", timeout: 1e4 });
|
|
6085
5264
|
} catch {
|
|
6086
|
-
if (
|
|
5265
|
+
if (isWindows) {
|
|
6087
5266
|
if (method === "HEAD") {
|
|
6088
|
-
result =
|
|
5267
|
+
result = execSync(`powershell -command "(Invoke-WebRequest -Uri '${fullUrl}' -Method Head -UseBasicParsing).Headers | ConvertTo-Json"`, { encoding: "utf-8", timeout: 1e4 });
|
|
6089
5268
|
} else {
|
|
6090
|
-
result =
|
|
5269
|
+
result = execSync(`powershell -command "(Invoke-WebRequest -Uri '${fullUrl}' -Method ${method} -UseBasicParsing).Content"`, { encoding: "utf-8", timeout: 1e4 });
|
|
6091
5270
|
}
|
|
6092
5271
|
} else {
|
|
6093
5272
|
throw new Error("curl not available");
|
|
@@ -6125,22 +5304,22 @@ function handleDiff(args2) {
|
|
|
6125
5304
|
console.log("");
|
|
6126
5305
|
return;
|
|
6127
5306
|
}
|
|
6128
|
-
const path1 =
|
|
6129
|
-
const path2 =
|
|
6130
|
-
if (!
|
|
5307
|
+
const path1 = resolve4(process.cwd(), file1);
|
|
5308
|
+
const path2 = resolve4(process.cwd(), file2);
|
|
5309
|
+
if (!existsSync8(path1)) {
|
|
6131
5310
|
console.log(theme.error(` File not found: ${file1}`));
|
|
6132
5311
|
console.log("");
|
|
6133
5312
|
return;
|
|
6134
5313
|
}
|
|
6135
|
-
if (!
|
|
5314
|
+
if (!existsSync8(path2)) {
|
|
6136
5315
|
console.log(theme.error(` File not found: ${file2}`));
|
|
6137
5316
|
console.log("");
|
|
6138
5317
|
return;
|
|
6139
5318
|
}
|
|
6140
5319
|
try {
|
|
6141
|
-
const content1 =
|
|
6142
|
-
const content2 =
|
|
6143
|
-
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)}`));
|
|
6144
5323
|
console.log("");
|
|
6145
5324
|
const maxLines = Math.max(content1.length, content2.length);
|
|
6146
5325
|
let differences = 0;
|
|
@@ -6149,8 +5328,8 @@ function handleDiff(args2) {
|
|
|
6149
5328
|
const line2 = content2[i] || "";
|
|
6150
5329
|
if (line1 !== line2) {
|
|
6151
5330
|
differences++;
|
|
6152
|
-
console.log(
|
|
6153
|
-
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)}`));
|
|
6154
5333
|
console.log("");
|
|
6155
5334
|
}
|
|
6156
5335
|
}
|
|
@@ -6167,18 +5346,18 @@ function handleDiff(args2) {
|
|
|
6167
5346
|
}
|
|
6168
5347
|
console.log("");
|
|
6169
5348
|
}
|
|
6170
|
-
var aliasesFile =
|
|
5349
|
+
var aliasesFile = join5(homedir3(), ".zammy-aliases.json");
|
|
6171
5350
|
function loadAliases() {
|
|
6172
5351
|
try {
|
|
6173
|
-
if (
|
|
6174
|
-
return JSON.parse(
|
|
5352
|
+
if (existsSync8(aliasesFile)) {
|
|
5353
|
+
return JSON.parse(readFileSync5(aliasesFile, "utf-8"));
|
|
6175
5354
|
}
|
|
6176
5355
|
} catch {
|
|
6177
5356
|
}
|
|
6178
5357
|
return {};
|
|
6179
5358
|
}
|
|
6180
5359
|
function saveAliases(aliases) {
|
|
6181
|
-
|
|
5360
|
+
writeFileSync4(aliasesFile, JSON.stringify(aliases, null, 2));
|
|
6182
5361
|
}
|
|
6183
5362
|
function handleAlias(args2) {
|
|
6184
5363
|
const parts = args2.trim().split(/\s+/);
|
|
@@ -6208,7 +5387,7 @@ function handleAlias(args2) {
|
|
|
6208
5387
|
console.log(theme.dim(` Running: ${aliases[name]}`));
|
|
6209
5388
|
console.log("");
|
|
6210
5389
|
try {
|
|
6211
|
-
const result =
|
|
5390
|
+
const result = execSync(aliases[name], { encoding: "utf-8", cwd: process.cwd(), timeout: 3e4 });
|
|
6212
5391
|
console.log(result);
|
|
6213
5392
|
} catch (error) {
|
|
6214
5393
|
const err = error;
|
|
@@ -6240,7 +5419,7 @@ function handleNotify(args2) {
|
|
|
6240
5419
|
const message = args2.trim() || "Notification from Zammy CLI";
|
|
6241
5420
|
console.log("");
|
|
6242
5421
|
try {
|
|
6243
|
-
if (
|
|
5422
|
+
if (isWindows) {
|
|
6244
5423
|
const ps = `
|
|
6245
5424
|
[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null
|
|
6246
5425
|
[Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null
|
|
@@ -6249,10 +5428,10 @@ function handleNotify(args2) {
|
|
|
6249
5428
|
$notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("Zammy CLI")
|
|
6250
5429
|
$notifier.Show([Windows.UI.Notifications.ToastNotification]::new($template))
|
|
6251
5430
|
`;
|
|
6252
|
-
|
|
5431
|
+
execSync(`powershell -command "${ps.replace(/\n/g, " ")}"`, { stdio: "pipe", timeout: 5e3 });
|
|
6253
5432
|
} else {
|
|
6254
|
-
const cmd =
|
|
6255
|
-
|
|
5433
|
+
const cmd = platform2() === "darwin" ? `osascript -e 'display notification "${message}" with title "Zammy CLI"'` : `notify-send "Zammy CLI" "${message}"`;
|
|
5434
|
+
execSync(cmd, { stdio: "pipe", timeout: 3e3 });
|
|
6256
5435
|
}
|
|
6257
5436
|
console.log(` ${symbols.check} ${theme.success("Notification sent")}`);
|
|
6258
5437
|
} catch {
|
|
@@ -6282,8 +5461,8 @@ function handleGrep(args2) {
|
|
|
6282
5461
|
function searchFile(filePath) {
|
|
6283
5462
|
if (results.length >= maxResults) return;
|
|
6284
5463
|
try {
|
|
6285
|
-
const content =
|
|
6286
|
-
const lines = content.split(
|
|
5464
|
+
const content = readFileSync5(filePath, "utf-8");
|
|
5465
|
+
const lines = content.split(/\r?\n/);
|
|
6287
5466
|
lines.forEach((line, index) => {
|
|
6288
5467
|
if (results.length >= maxResults) return;
|
|
6289
5468
|
if (regex.test(line)) {
|
|
@@ -6300,11 +5479,11 @@ function handleGrep(args2) {
|
|
|
6300
5479
|
function searchDir(dir, depth = 0) {
|
|
6301
5480
|
if (depth > 4 || results.length >= maxResults) return;
|
|
6302
5481
|
try {
|
|
6303
|
-
const entries =
|
|
5482
|
+
const entries = readdirSync2(dir, { withFileTypes: true });
|
|
6304
5483
|
for (const entry of entries) {
|
|
6305
5484
|
if (results.length >= maxResults) break;
|
|
6306
5485
|
if (entry.name.startsWith(".") || ["node_modules", ".git", "dist", "build"].includes(entry.name)) continue;
|
|
6307
|
-
const fullPath =
|
|
5486
|
+
const fullPath = resolve4(dir, entry.name);
|
|
6308
5487
|
if (entry.isDirectory()) {
|
|
6309
5488
|
searchDir(fullPath, depth + 1);
|
|
6310
5489
|
} else {
|
|
@@ -6327,9 +5506,9 @@ function handleGrep(args2) {
|
|
|
6327
5506
|
for (const result of results) {
|
|
6328
5507
|
const highlightedContent = result.content.replace(
|
|
6329
5508
|
regex,
|
|
6330
|
-
(match) =>
|
|
5509
|
+
(match) => chalk4.hex("#FF6B6B").bold(match)
|
|
6331
5510
|
);
|
|
6332
|
-
console.log(` ${theme.dim(result.file)}:${
|
|
5511
|
+
console.log(` ${theme.dim(result.file)}:${chalk4.hex("#61AFEF")(result.line)}`);
|
|
6333
5512
|
console.log(` ${highlightedContent}`);
|
|
6334
5513
|
console.log("");
|
|
6335
5514
|
}
|
|
@@ -6340,30 +5519,30 @@ function handleGrep(args2) {
|
|
|
6340
5519
|
console.log("");
|
|
6341
5520
|
}
|
|
6342
5521
|
function handleWc(args2) {
|
|
6343
|
-
const filePath =
|
|
5522
|
+
const filePath = resolve4(process.cwd(), args2.trim());
|
|
6344
5523
|
console.log("");
|
|
6345
5524
|
if (!args2.trim()) {
|
|
6346
5525
|
console.log(theme.error(" Usage: wc <file>"));
|
|
6347
5526
|
console.log("");
|
|
6348
5527
|
return;
|
|
6349
5528
|
}
|
|
6350
|
-
if (!
|
|
5529
|
+
if (!existsSync8(filePath)) {
|
|
6351
5530
|
console.log(theme.error(` File not found: ${args2}`));
|
|
6352
5531
|
console.log("");
|
|
6353
5532
|
return;
|
|
6354
5533
|
}
|
|
6355
5534
|
try {
|
|
6356
|
-
const content =
|
|
6357
|
-
const lines = content.split(
|
|
5535
|
+
const content = readFileSync5(filePath, "utf-8");
|
|
5536
|
+
const lines = content.split(/\r?\n/).length;
|
|
6358
5537
|
const words = content.split(/\s+/).filter((w) => w.length > 0).length;
|
|
6359
5538
|
const chars = content.length;
|
|
6360
5539
|
const bytes = Buffer.byteLength(content, "utf-8");
|
|
6361
|
-
console.log(theme.primary(` \u{1F4CA} ${
|
|
5540
|
+
console.log(theme.primary(` \u{1F4CA} ${basename3(args2)}`));
|
|
6362
5541
|
console.log("");
|
|
6363
|
-
console.log(` ${
|
|
6364
|
-
console.log(` ${
|
|
6365
|
-
console.log(` ${
|
|
6366
|
-
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")}`);
|
|
6367
5546
|
} catch {
|
|
6368
5547
|
console.log(theme.error(" Failed to read file"));
|
|
6369
5548
|
}
|
|
@@ -6383,19 +5562,19 @@ function handleHead(args2) {
|
|
|
6383
5562
|
console.log("");
|
|
6384
5563
|
return;
|
|
6385
5564
|
}
|
|
6386
|
-
const fullPath =
|
|
6387
|
-
if (!
|
|
5565
|
+
const fullPath = resolve4(process.cwd(), filePath);
|
|
5566
|
+
if (!existsSync8(fullPath)) {
|
|
6388
5567
|
console.log(theme.error(` File not found: ${filePath}`));
|
|
6389
5568
|
console.log("");
|
|
6390
5569
|
return;
|
|
6391
5570
|
}
|
|
6392
5571
|
try {
|
|
6393
|
-
const content =
|
|
6394
|
-
const fileLines = content.split(
|
|
6395
|
-
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)}:`));
|
|
6396
5575
|
console.log("");
|
|
6397
5576
|
fileLines.forEach((line, i) => {
|
|
6398
|
-
console.log(` ${
|
|
5577
|
+
console.log(` ${chalk4.dim((i + 1).toString().padStart(4))} ${line}`);
|
|
6399
5578
|
});
|
|
6400
5579
|
} catch {
|
|
6401
5580
|
console.log(theme.error(" Failed to read file"));
|
|
@@ -6597,19 +5776,19 @@ async function parseAndExecute(input) {
|
|
|
6597
5776
|
}
|
|
6598
5777
|
|
|
6599
5778
|
// src/index.ts
|
|
6600
|
-
import { readdirSync as
|
|
6601
|
-
import { fileURLToPath
|
|
6602
|
-
import { dirname
|
|
6603
|
-
import
|
|
5779
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync6 } from "fs";
|
|
5780
|
+
import { fileURLToPath } from "url";
|
|
5781
|
+
import { dirname, join as join6 } from "path";
|
|
5782
|
+
import chalk5 from "chalk";
|
|
6604
5783
|
var SLIME_COLOR = "#9B59B6";
|
|
6605
5784
|
var EYE_COLOR = "#1A1A2E";
|
|
6606
5785
|
var MIN_WIDTH_FOR_IDLE = 40;
|
|
6607
5786
|
var MIN_WIDTH_FOR_MENU = 50;
|
|
6608
5787
|
var miniSlimeFrames = [
|
|
6609
5788
|
// Open eyes
|
|
6610
|
-
|
|
5789
|
+
chalk5.hex(SLIME_COLOR)("(") + chalk5.hex(EYE_COLOR)("\u25CF") + chalk5.hex(SLIME_COLOR)("\u1D17") + chalk5.hex(EYE_COLOR)("\u25CF") + chalk5.hex(SLIME_COLOR)(")"),
|
|
6611
5790
|
// Blink (closed eyes)
|
|
6612
|
-
|
|
5791
|
+
chalk5.hex(SLIME_COLOR)("(") + chalk5.hex(EYE_COLOR)("\u2500") + chalk5.hex(SLIME_COLOR)("\u1D17") + chalk5.hex(EYE_COLOR)("\u2500") + chalk5.hex(SLIME_COLOR)(")")
|
|
6613
5792
|
];
|
|
6614
5793
|
var idleAnimationInterval = null;
|
|
6615
5794
|
var isUserTyping = false;
|
|
@@ -6684,10 +5863,10 @@ function setIdle() {
|
|
|
6684
5863
|
var args = process.argv.slice(2);
|
|
6685
5864
|
if (args.includes("--version") || args.includes("-v")) {
|
|
6686
5865
|
try {
|
|
6687
|
-
const __filename =
|
|
6688
|
-
const __dirname =
|
|
6689
|
-
const pkgPath =
|
|
6690
|
-
const pkg = JSON.parse(
|
|
5866
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
5867
|
+
const __dirname = dirname(__filename);
|
|
5868
|
+
const pkgPath = join6(__dirname, "..", "package.json");
|
|
5869
|
+
const pkg = JSON.parse(readFileSync6(pkgPath, "utf-8"));
|
|
6691
5870
|
console.log(`zammy v${pkg.version}`);
|
|
6692
5871
|
} catch {
|
|
6693
5872
|
console.log("zammy v1.0.0");
|
|
@@ -6768,9 +5947,9 @@ var SHELL_COMMANDS = [
|
|
|
6768
5947
|
{ name: "mv", description: "Move files" }
|
|
6769
5948
|
];
|
|
6770
5949
|
function getFilteredCommands(filter) {
|
|
6771
|
-
const
|
|
6772
|
-
if (!filter) return
|
|
6773
|
-
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()));
|
|
6774
5953
|
}
|
|
6775
5954
|
function getFilteredShellCommands(filter) {
|
|
6776
5955
|
if (!filter) return SHELL_COMMANDS;
|
|
@@ -6901,14 +6080,14 @@ function navigateMenu(direction, currentLine) {
|
|
|
6901
6080
|
renderMenu(currentLine);
|
|
6902
6081
|
}
|
|
6903
6082
|
function completer(line) {
|
|
6904
|
-
const
|
|
6083
|
+
const commands = getAllCommands().map((c) => "/" + c.name);
|
|
6905
6084
|
if (line.startsWith("/")) {
|
|
6906
6085
|
const input = line.toLowerCase();
|
|
6907
6086
|
if (input.startsWith("/asciiart ")) {
|
|
6908
6087
|
const afterCommand = line.slice("/asciiart ".length);
|
|
6909
6088
|
const searchTerm = afterCommand.startsWith("@") ? afterCommand.slice(1) : afterCommand;
|
|
6910
6089
|
try {
|
|
6911
|
-
const files =
|
|
6090
|
+
const files = readdirSync3(process.cwd());
|
|
6912
6091
|
const imageFiles = files.filter((f) => {
|
|
6913
6092
|
const ext = f.toLowerCase().slice(f.lastIndexOf("."));
|
|
6914
6093
|
return IMAGE_EXTENSIONS.includes(ext);
|
|
@@ -6922,7 +6101,7 @@ function completer(line) {
|
|
|
6922
6101
|
return [[], line];
|
|
6923
6102
|
}
|
|
6924
6103
|
}
|
|
6925
|
-
const matches =
|
|
6104
|
+
const matches = commands.filter((c) => c.toLowerCase().startsWith(input));
|
|
6926
6105
|
return [matches.length ? matches : [], line];
|
|
6927
6106
|
}
|
|
6928
6107
|
if (line.startsWith("!")) {
|
|
@@ -6939,7 +6118,7 @@ async function main() {
|
|
|
6939
6118
|
}
|
|
6940
6119
|
await displayBanner(isSimpleMode);
|
|
6941
6120
|
await initPluginLoader();
|
|
6942
|
-
const rl =
|
|
6121
|
+
const rl = readline.createInterface({
|
|
6943
6122
|
input: process.stdin,
|
|
6944
6123
|
output: process.stdout,
|
|
6945
6124
|
terminal: isTTY,
|