@groeponline/pi-wishcraft 1.3.1 → 1.4.0

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.
@@ -18,8 +18,9 @@ import { mergeSegmentsWithCustomItems } from "../config/powerline-config.ts";
18
18
  import { renderSegment } from "../segments/index.ts";
19
19
  import { ansi, colorEnabled, getFgAnsiCode } from "../theme/colors.ts";
20
20
  import { getSeparator } from "../theme/separators.ts";
21
- import { frameAt, getMotion } from "../motion/index.ts";
21
+ import { frameAt, getMotion, sweepPosition, trailGlyph } from "../motion/index.ts";
22
22
  import type { SignalRuntime } from "./controller.ts";
23
+ import { getContributedSignalSources } from "../extension/contrib/registry.ts";
23
24
 
24
25
  export interface SignalRenderOptions {
25
26
  separatorStyle: StatusLineSeparatorStyle;
@@ -50,7 +51,10 @@ export function renderSignal(
50
51
  },
51
52
  );
52
53
  const left = renderModules(merged.leftSegments, ctx);
53
- const right = renderModules(merged.rightSegments, ctx);
54
+ const right = [
55
+ ...renderModules(merged.rightSegments, ctx),
56
+ ...renderContributedSources(ctx),
57
+ ];
54
58
  const secondary = renderModules(merged.secondarySegments, ctx);
55
59
  const separator = getSeparator(options.separatorStyle).left;
56
60
 
@@ -91,11 +95,27 @@ export function renderActivity(
91
95
  const open = spec.caps.leftOpen ?? "";
92
96
  const close = spec.caps.leftClose ?? "";
93
97
  const dim = getFgAnsiCode("sep");
98
+ const hot = getFgAnsiCode("accent");
94
99
  const reset = colorEnabled() ? ansi.reset : "";
95
- const rail = runtime.active
96
- ? `${spec.separators.left}${glyph}${spec.separators.right}`
97
- : `${spec.separators.left}${spec.separators.right}`;
98
- return `${dim}${open}${rail}${close}${reset} ${label}`;
100
+ // ponytail: vivid sweep — 12-char rail with travelling head + 6-char trail, not a single glyph
101
+ const RAIL_WIDTH = 12;
102
+ let railInner: string;
103
+ if (!runtime.active) {
104
+ railInner = "━".repeat(RAIL_WIDTH);
105
+ } else {
106
+ const pos = sweepPosition(runtime.tick, RAIL_WIDTH, true);
107
+ let built = "";
108
+ for (let i = 0; i < RAIL_WIDTH; i++) {
109
+ const dist = Math.abs(i - pos);
110
+ if (dist === 0) built += glyph;
111
+ else if (dist <= 6) built += trailGlyph(dist, ascii);
112
+ else built += "━";
113
+ }
114
+ railInner = built;
115
+ }
116
+ const railColor = runtime.active ? hot : dim;
117
+ const rail = `${spec.separators.left}${railInner}${spec.separators.right}`;
118
+ return `${railColor}${open}${rail}${close}${reset} ${label}`;
99
119
  }
100
120
 
101
121
  function fitLanes(
@@ -164,6 +184,29 @@ function joinModules(modules: Module[], separator: string, width: number): strin
164
184
  return fitted.length ? ` ${fitted.map((module) => module.content).join(sep)} ` : "";
165
185
  }
166
186
 
187
+ const ANSI_CONTROL_RE = /\x1B(?:\][^\x07]*(?:\x07|\x1B\\)|\[[0-?]*[ -/]*[@-~]|[@-_])|\x9B[0-?]*[ -/]*[@-~]|\x9D[^\x07]*(?:\x07|\x1B\\)/g;
188
+
189
+ function stripAnsiControls(text: string): string {
190
+ return text.replace(ANSI_CONTROL_RE, "");
191
+ }
192
+
193
+ function renderContributedSources(ctx: SegmentContext): Module[] {
194
+ const out: Module[] = [];
195
+ for (const src of getContributedSignalSources()) {
196
+ try {
197
+ const raw = src.render?.(ctx);
198
+ if (!raw || typeof raw !== "string") continue;
199
+ const content = raw.trim();
200
+ if (!stripAnsiControls(content).trim()) continue;
201
+ // ponytail: fault-isolated — a throwing or empty source never takes down Signal
202
+ out.push({ content, width: visibleWidth(content) });
203
+ } catch {
204
+ // skip failing contribution
205
+ }
206
+ }
207
+ return out;
208
+ }
209
+
167
210
  function styledSeparator(separator: string): string {
168
211
  const color = getFgAnsiCode("sep");
169
212
  const reset = colorEnabled() ? ansi.reset : "";