@nevermorelove/ompp 0.2.0 → 0.2.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/ompp.js +39 -87
- package/package.json +5 -2
- package/modes/general/append.md +0 -3
- package/modes/general/config.yml +0 -8
package/README.md
CHANGED
|
@@ -63,7 +63,7 @@ inside an installed package. The first `ompp create` makes the folder for you.
|
|
|
63
63
|
|
|
64
64
|
A new mode is `ompp create <name>` (or plain `mkdir` plus files). No manifest,
|
|
65
65
|
no code. The wrapper reads the folder, so it never needs to change when you
|
|
66
|
-
add modes.
|
|
66
|
+
add modes.
|
|
67
67
|
|
|
68
68
|
## Precedence
|
|
69
69
|
|
package/ompp.js
CHANGED
|
@@ -278,88 +278,43 @@ function createMode(name) {
|
|
|
278
278
|
return 0;
|
|
279
279
|
}
|
|
280
280
|
|
|
281
|
-
function
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
if (value === null) reject(new Error("mode selection cancelled"));
|
|
294
|
-
else resolve(value);
|
|
295
|
-
};
|
|
296
|
-
|
|
297
|
-
const render = (first) => {
|
|
298
|
-
if (!first) process.stdout.write(`\u001b[${modes.length}A`);
|
|
299
|
-
const body = modes
|
|
300
|
-
.map((m, i) => (i === idx ? "> " + m : " " + m))
|
|
301
|
-
.map((l) => "\u001b[2K" + l)
|
|
302
|
-
.join("\n");
|
|
303
|
-
process.stdout.write("\u001b[?25l" + body + "\n");
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
function onData(buf) {
|
|
307
|
-
// A single read can carry several keys (arrow + Enter glued together,
|
|
308
|
-
// a paste). Walk key by key instead of matching the whole chunk.
|
|
309
|
-
const s = buf.toString();
|
|
310
|
-
let i = 0;
|
|
311
|
-
while (i < s.length) {
|
|
312
|
-
const ch = s[i];
|
|
313
|
-
if (ch === "\u001b") {
|
|
314
|
-
const seq = s.slice(i);
|
|
315
|
-
if (seq.startsWith("\u001b[A") || seq.startsWith("\u001b[B") ||
|
|
316
|
-
seq.startsWith("\u001b[C") || seq.startsWith("\u001b[D")) {
|
|
317
|
-
if (seq.startsWith("\u001b[A")) {
|
|
318
|
-
idx = (idx - 1 + modes.length) % modes.length;
|
|
319
|
-
render(false);
|
|
320
|
-
} else if (seq.startsWith("\u001b[B")) {
|
|
321
|
-
idx = (idx + 1) % modes.length;
|
|
322
|
-
render(false);
|
|
323
|
-
} // C/D: left/right, ignore
|
|
324
|
-
i += 3;
|
|
325
|
-
continue;
|
|
326
|
-
}
|
|
327
|
-
if (seq.length === 1) {
|
|
328
|
-
// Bare escape with nothing after it in this chunk: cancel.
|
|
329
|
-
finish(null);
|
|
330
|
-
process.exit(0);
|
|
331
|
-
}
|
|
332
|
-
i++; // unknown or split sequence, skip the escape byte
|
|
333
|
-
continue;
|
|
334
|
-
}
|
|
335
|
-
if (ch === "\r" || ch === "\n") return finish(modes[idx]);
|
|
336
|
-
if (ch === "\u0003") {
|
|
337
|
-
// Ctrl+C: restore the terminal and bail like a shell would.
|
|
338
|
-
finish(null);
|
|
339
|
-
process.exit(130);
|
|
340
|
-
}
|
|
341
|
-
if (ch === "q") {
|
|
342
|
-
finish(null);
|
|
343
|
-
process.exit(0);
|
|
344
|
-
}
|
|
345
|
-
if (ch === "j") {
|
|
346
|
-
idx = (idx + 1) % modes.length;
|
|
347
|
-
render(false);
|
|
348
|
-
}
|
|
349
|
-
if (ch === "k") {
|
|
350
|
-
idx = (idx - 1 + modes.length) % modes.length;
|
|
351
|
-
render(false);
|
|
352
|
-
}
|
|
353
|
-
i++;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
281
|
+
async function pickMode(modeNames) {
|
|
282
|
+
const { select, isCancel, cancel } = require("@clack/prompts");
|
|
283
|
+
const chosen = await select({
|
|
284
|
+
message: "Pick a mode",
|
|
285
|
+
options: modeNames.map((name) => ({ value: name, label: name })),
|
|
286
|
+
});
|
|
287
|
+
if (isCancel(chosen)) {
|
|
288
|
+
cancel("Cancelled");
|
|
289
|
+
process.exit(130);
|
|
290
|
+
}
|
|
291
|
+
return chosen;
|
|
292
|
+
}
|
|
356
293
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
294
|
+
// Non-TTY stdin: clack needs an interactive terminal, so numbered input.
|
|
295
|
+
function pickModePiped(modeNames) {
|
|
296
|
+
return new Promise((resolve, reject) => {
|
|
297
|
+
const readline = require("readline");
|
|
298
|
+
const rl = readline.createInterface({ input: process.stdin });
|
|
299
|
+
process.stdout.write("Select a mode:\n");
|
|
300
|
+
modeNames.forEach((m, i) => process.stdout.write(` ${i + 1}. ${m}\n`));
|
|
301
|
+
process.stdout.write(`Choice [1-${modeNames.length}]: `);
|
|
302
|
+
let done = false;
|
|
303
|
+
rl.once("line", (line) => {
|
|
304
|
+
done = true;
|
|
305
|
+
rl.close();
|
|
306
|
+
const n = parseInt(line.trim(), 10);
|
|
307
|
+
if (n >= 1 && n <= modeNames.length) resolve(modeNames[n - 1]);
|
|
308
|
+
else reject(new Error(`"${line.trim()}" is not a valid choice`));
|
|
309
|
+
});
|
|
310
|
+
rl.once("close", () => {
|
|
311
|
+
if (!done) reject(new Error("no mode selected"));
|
|
312
|
+
});
|
|
360
313
|
});
|
|
361
314
|
}
|
|
362
315
|
|
|
316
|
+
|
|
317
|
+
|
|
363
318
|
async function main() {
|
|
364
319
|
const argv = process.argv.slice(2);
|
|
365
320
|
|
|
@@ -371,7 +326,7 @@ async function main() {
|
|
|
371
326
|
const { modes, skipped } = discoverModes();
|
|
372
327
|
if (!modes.length) {
|
|
373
328
|
console.error(
|
|
374
|
-
`
|
|
329
|
+
`You have no modes yet. Create one with "ompp create <name>".`,
|
|
375
330
|
);
|
|
376
331
|
for (const s of SOURCES) console.error(`[ompp] looked in: ${s}`);
|
|
377
332
|
return 1;
|
|
@@ -405,7 +360,7 @@ async function main() {
|
|
|
405
360
|
}
|
|
406
361
|
if (!modes.length) {
|
|
407
362
|
console.error(
|
|
408
|
-
`
|
|
363
|
+
`You have no modes yet. Create one with "ompp create <name>".`,
|
|
409
364
|
);
|
|
410
365
|
for (const s of SOURCES) console.error(`[ompp] looked in: ${s}`);
|
|
411
366
|
return 1;
|
|
@@ -427,13 +382,10 @@ async function main() {
|
|
|
427
382
|
}
|
|
428
383
|
} else {
|
|
429
384
|
try {
|
|
430
|
-
|
|
431
|
-
? await
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
: await pickByNumber(modeNames).then((n) =>
|
|
435
|
-
modes.find((m) => m.name === n),
|
|
436
|
-
);
|
|
385
|
+
const name = process.stdin.isTTY
|
|
386
|
+
? await pickMode(modeNames)
|
|
387
|
+
: await pickModePiped(modeNames);
|
|
388
|
+
mode = modes.find((m) => m.name === name);
|
|
437
389
|
} catch (err) {
|
|
438
390
|
console.error(`[ompp] ${err.message}`);
|
|
439
391
|
return 1;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nevermorelove/ompp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Mode presets for the omp coding agent: one folder per mode, zero config code.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -24,5 +24,8 @@
|
|
|
24
24
|
"cli"
|
|
25
25
|
],
|
|
26
26
|
"author": "ForeverInLaw",
|
|
27
|
-
"license": "MIT"
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@clack/prompts": "^1.8.1"
|
|
30
|
+
}
|
|
28
31
|
}
|
package/modes/general/append.md
DELETED