oh-pi 0.1.84 → 0.1.85
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/dist/bin/oh-pi.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oh-pi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.85",
|
|
4
4
|
"description": "One-click setup for pi-coding-agent. Like oh-my-zsh for pi.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"!**/*.spec.ts"
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|
|
18
|
-
"
|
|
18
|
+
"clean": "node -e \"require('node:fs').rmSync('dist',{ recursive: true, force: true })\"",
|
|
19
|
+
"build": "npm run clean && tsc",
|
|
19
20
|
"dev": "tsc --watch",
|
|
20
21
|
"start": "node dist/bin/oh-pi.js",
|
|
21
22
|
"test": "vitest run",
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export interface HorizontalTabItem {
|
|
2
|
-
label: string;
|
|
3
|
-
summary: () => string;
|
|
4
|
-
details?: () => string[];
|
|
5
|
-
edit: () => Promise<void>;
|
|
6
|
-
}
|
|
7
|
-
interface HorizontalTabsOptions {
|
|
8
|
-
title: string;
|
|
9
|
-
tabs: HorizontalTabItem[];
|
|
10
|
-
canFinish: () => boolean;
|
|
11
|
-
finishBlockedMessage?: () => string;
|
|
12
|
-
}
|
|
13
|
-
type TabAction = "left" | "right" | "edit" | "finish" | "cancel" | {
|
|
14
|
-
jump: number;
|
|
15
|
-
};
|
|
16
|
-
interface KeypressLike {
|
|
17
|
-
name?: string;
|
|
18
|
-
ctrl?: boolean;
|
|
19
|
-
}
|
|
20
|
-
export declare function mapTabAction(str: string, key: KeypressLike, tabCount: number): TabAction | null;
|
|
21
|
-
export declare function runHorizontalTabs(opts: HorizontalTabsOptions): Promise<void>;
|
|
22
|
-
export {};
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import * as p from "@clack/prompts";
|
|
2
|
-
import chalk from "chalk";
|
|
3
|
-
import { emitKeypressEvents } from "node:readline";
|
|
4
|
-
import { t } from "../i18n.js";
|
|
5
|
-
function clearScreen() {
|
|
6
|
-
process.stdout.write("\x1b[2J\x1b[H");
|
|
7
|
-
}
|
|
8
|
-
export function mapTabAction(str, key, tabCount) {
|
|
9
|
-
if (key.ctrl && key.name === "c")
|
|
10
|
-
return "cancel";
|
|
11
|
-
if (key.name === "left")
|
|
12
|
-
return "left";
|
|
13
|
-
if (key.name === "right")
|
|
14
|
-
return "right";
|
|
15
|
-
if (key.name === "return" || key.name === "enter" || key.name === "space" || key.name === "e")
|
|
16
|
-
return "edit";
|
|
17
|
-
if (key.name === "f")
|
|
18
|
-
return "finish";
|
|
19
|
-
if (/^[1-9]$/.test(str)) {
|
|
20
|
-
const idx = Number(str) - 1;
|
|
21
|
-
if (idx >= 0 && idx < tabCount)
|
|
22
|
-
return { jump: idx };
|
|
23
|
-
}
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
function waitForAction(tabCount) {
|
|
27
|
-
return new Promise((resolve) => {
|
|
28
|
-
const stdin = process.stdin;
|
|
29
|
-
const isRawCapable = !!stdin.isTTY && typeof stdin.setRawMode === "function";
|
|
30
|
-
emitKeypressEvents(stdin);
|
|
31
|
-
if (isRawCapable)
|
|
32
|
-
stdin.setRawMode(true);
|
|
33
|
-
const done = (action) => {
|
|
34
|
-
stdin.off("keypress", onKeypress);
|
|
35
|
-
if (isRawCapable)
|
|
36
|
-
stdin.setRawMode(false);
|
|
37
|
-
resolve(action);
|
|
38
|
-
};
|
|
39
|
-
const onKeypress = (str, key) => {
|
|
40
|
-
const action = mapTabAction(str, key, tabCount);
|
|
41
|
-
if (action)
|
|
42
|
-
done(action);
|
|
43
|
-
};
|
|
44
|
-
stdin.on("keypress", onKeypress);
|
|
45
|
-
if (!stdin.isTTY) {
|
|
46
|
-
done("cancel");
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
function renderTabs(title, tabs, activeIndex, notice) {
|
|
51
|
-
clearScreen();
|
|
52
|
-
console.log(chalk.bold(title));
|
|
53
|
-
console.log();
|
|
54
|
-
const tabLine = tabs
|
|
55
|
-
.map((tab, i) => {
|
|
56
|
-
const label = `${i + 1}. ${tab.label}`;
|
|
57
|
-
return i === activeIndex
|
|
58
|
-
? chalk.bgCyan.black(` ${label} `)
|
|
59
|
-
: chalk.gray(` ${label} `);
|
|
60
|
-
})
|
|
61
|
-
.join(chalk.gray(" | "));
|
|
62
|
-
console.log(tabLine);
|
|
63
|
-
console.log(chalk.dim(t("custom.tabControls")));
|
|
64
|
-
console.log();
|
|
65
|
-
const active = tabs[activeIndex];
|
|
66
|
-
console.log(chalk.cyan(active.summary()));
|
|
67
|
-
const details = active.details?.() ?? [];
|
|
68
|
-
for (const line of details)
|
|
69
|
-
console.log(line);
|
|
70
|
-
if (notice) {
|
|
71
|
-
console.log();
|
|
72
|
-
console.log(chalk.yellow(notice));
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
export async function runHorizontalTabs(opts) {
|
|
76
|
-
const tabs = opts.tabs;
|
|
77
|
-
let activeIndex = 0;
|
|
78
|
-
let notice;
|
|
79
|
-
while (true) {
|
|
80
|
-
renderTabs(opts.title, tabs, activeIndex, notice);
|
|
81
|
-
notice = undefined;
|
|
82
|
-
const action = await waitForAction(tabs.length);
|
|
83
|
-
if (action === "cancel") {
|
|
84
|
-
p.cancel(t("cancelled"));
|
|
85
|
-
process.exit(0);
|
|
86
|
-
}
|
|
87
|
-
if (action === "left") {
|
|
88
|
-
activeIndex = (activeIndex - 1 + tabs.length) % tabs.length;
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
if (action === "right") {
|
|
92
|
-
activeIndex = (activeIndex + 1) % tabs.length;
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
if (action === "finish") {
|
|
96
|
-
if (opts.canFinish()) {
|
|
97
|
-
clearScreen();
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
notice = opts.finishBlockedMessage?.() ?? t("custom.needProviders");
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
if (action === "edit") {
|
|
104
|
-
await tabs[activeIndex].edit();
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
107
|
-
if (typeof action === "object" && "jump" in action) {
|
|
108
|
-
activeIndex = action.jump;
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { mapTabAction } from "./horizontal-tabs.js";
|
|
3
|
-
describe("mapTabAction", () => {
|
|
4
|
-
it("maps enter and return to edit", () => {
|
|
5
|
-
expect(mapTabAction("", { name: "enter" }, 5)).toBe("edit");
|
|
6
|
-
expect(mapTabAction("", { name: "return" }, 5)).toBe("edit");
|
|
7
|
-
});
|
|
8
|
-
it("maps arrows and finish", () => {
|
|
9
|
-
expect(mapTabAction("", { name: "left" }, 5)).toBe("left");
|
|
10
|
-
expect(mapTabAction("", { name: "right" }, 5)).toBe("right");
|
|
11
|
-
expect(mapTabAction("", { name: "f" }, 5)).toBe("finish");
|
|
12
|
-
});
|
|
13
|
-
it("maps jump index within range", () => {
|
|
14
|
-
expect(mapTabAction("3", { name: "3" }, 5)).toEqual({ jump: 2 });
|
|
15
|
-
expect(mapTabAction("9", { name: "9" }, 5)).toBeNull();
|
|
16
|
-
});
|
|
17
|
-
});
|