pi-fold 4.1.2 → 4.1.3
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.
|
@@ -225,6 +225,7 @@ export * from "./lib/persistence.ts";
|
|
|
225
225
|
export * from "./lib/policy.ts";
|
|
226
226
|
export * from "./lib/rollback.ts";
|
|
227
227
|
export * from "./lib/scheduling.ts";
|
|
228
|
+
export * from "./lib/status-widget.ts";
|
|
228
229
|
export * from "./lib/selection.ts";
|
|
229
230
|
export * from "./lib/transcript.ts";
|
|
230
231
|
|
|
@@ -746,11 +747,18 @@ export function registerActiveContext(pi: any, options: {
|
|
|
746
747
|
};
|
|
747
748
|
}, { placement: "belowEditor" });
|
|
748
749
|
};
|
|
749
|
-
const foldBarModel = (input: {
|
|
750
|
+
const foldBarModel = (ctx: any, input: {
|
|
750
751
|
share: number | null; budgetTokens: number; staged: number; roots: number; weighed: boolean;
|
|
751
752
|
}): FoldBarModel => {
|
|
752
753
|
const state = persistence.state;
|
|
753
|
-
|
|
754
|
+
// THE SAME SNAPSHOT /fold-status PRICES AGAINST. `markFreedBytes` answers ZERO, silently,
|
|
755
|
+
// for a span it cannot locate contiguously in the snapshot it is handed, and the last
|
|
756
|
+
// context event's snapshot can trail the branch the marks were cut from; the bar read
|
|
757
|
+
// "5 staged, 0 to free" beside a status command pricing the same marks at 41,877
|
|
758
|
+
// tokens (Shane, 2026-09-02, session 01a06272). The authoritative snapshot is memoized
|
|
759
|
+
// on the branch length, so reading it here costs nothing while nothing has changed.
|
|
760
|
+
let snapshot = lifecycle.latestSnapshot;
|
|
761
|
+
try { snapshot = authoritativeSnapshotFor(ctx); } catch { }
|
|
754
762
|
let stagedTokens = 0;
|
|
755
763
|
let placeholderChars = 0;
|
|
756
764
|
let hiddenChars = 0;
|
|
@@ -801,7 +809,7 @@ export function registerActiveContext(pi: any, options: {
|
|
|
801
809
|
try {
|
|
802
810
|
installFoldBar(ctx);
|
|
803
811
|
if (foldBar.installed) {
|
|
804
|
-
foldBar.model = foldBarModel({
|
|
812
|
+
foldBar.model = foldBarModel(ctx, {
|
|
805
813
|
share, budgetTokens: capacity.budgetTokens, staged, roots,
|
|
806
814
|
weighed: ladder.bandTopMeasurement !== null &&
|
|
807
815
|
ladder.bandTopMeasurement === measurements.lastProviderMeasurement,
|
|
@@ -66,11 +66,33 @@ export interface FoldBarTheme {
|
|
|
66
66
|
fg(color: "dim" | "muted" | "text" | "warning" | "error", text: string): string;
|
|
67
67
|
bold(text: string): string;
|
|
68
68
|
getColorMode?(): "truecolor" | "256color";
|
|
69
|
+
getFgAnsi?(color: "text"): string;
|
|
70
|
+
name?: string;
|
|
69
71
|
}
|
|
70
72
|
|
|
71
|
-
// Crameri batlow10, classes 3, 6 and 8 (0-indexed)
|
|
72
|
-
//
|
|
73
|
-
|
|
73
|
+
// Crameri batlow10, three classes per background. Classes 3, 6 and 8 (0-indexed) read on
|
|
74
|
+
// a dark terminal; the lightest of them is 1.7:1 against white, so a light terminal steps
|
|
75
|
+
// two classes darker (2, 5 and 6), the same triple the README's light figure uses.
|
|
76
|
+
const BATLOW_ON_DARK = { raw: "#3C6D56", staged: "#D29343", folded: "#FDB7BC" } as const;
|
|
77
|
+
const BATLOW_ON_LIGHT = { raw: "#1C5A62", staged: "#9D892B", folded: "#D29343" } as const;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* WHICH WAY THE BACKGROUND GOES, read off the theme's own text colour rather than its
|
|
81
|
+
* name: a theme whose body text is dark is drawn on a light background. pi hands the
|
|
82
|
+
* text colour out as a truecolor escape, and a theme that does not (256-colour mode,
|
|
83
|
+
* or a host without the accessor) falls back to the name, then to dark.
|
|
84
|
+
*/
|
|
85
|
+
export function lightBackground(theme: FoldBarTheme): boolean {
|
|
86
|
+
try {
|
|
87
|
+
const ansi = theme.getFgAnsi?.("text") ?? "";
|
|
88
|
+
const match = /38;2;(\d+);(\d+);(\d+)/.exec(ansi);
|
|
89
|
+
if (match) {
|
|
90
|
+
const [r, g, b] = match.slice(1).map((v) => Number(v) / 255);
|
|
91
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b < 0.5;
|
|
92
|
+
}
|
|
93
|
+
} catch { }
|
|
94
|
+
return /light/i.test(theme.name ?? "");
|
|
95
|
+
}
|
|
74
96
|
|
|
75
97
|
const truecolor = (hex: string, text: string): string => {
|
|
76
98
|
const r = parseInt(hex.slice(1, 3), 16);
|
|
@@ -140,6 +162,7 @@ export function renderFoldBar(model: FoldBarModel, width: number, theme: FoldBar
|
|
|
140
162
|
width, theme.fg("dim", "..."));
|
|
141
163
|
}
|
|
142
164
|
const rich = theme.getColorMode?.() === "truecolor";
|
|
165
|
+
const BATLOW = lightBackground(theme) ? BATLOW_ON_LIGHT : BATLOW_ON_DARK;
|
|
143
166
|
const ink: Record<Cell, (text: string) => string> = {
|
|
144
167
|
raw: (t) => rich ? truecolor(BATLOW.raw, t) : theme.fg("muted", t),
|
|
145
168
|
staged: (t) => rich ? truecolor(BATLOW.staged, t) : theme.fg("text", t),
|