@xynogen/pix-find 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xynogen/pix-find",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Pi tool — glob file search",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
package/src/find.test.ts CHANGED
@@ -6,7 +6,24 @@ import type {
6
6
  TextComponentCtor,
7
7
  ThemeLike,
8
8
  } from "@xynogen/pix-pretty/types";
9
- import { applyFindDefaults, DEFAULT_FIND_LIMIT, registerFindTool } from "./find";
9
+ import { applyFindDefaults, DEFAULT_FIND_LIMIT, globHighlight, registerFindTool } from "./find";
10
+
11
+ describe("globHighlight", () => {
12
+ it("keeps literal runs from a glob as case-insensitive alternatives", () => {
13
+ const re = globHighlight("**/*.test.ts");
14
+ expect(re).toBeInstanceOf(RegExp);
15
+ expect((re as RegExp).flags).toBe("gi");
16
+ expect("foo.test.ts".match(re as RegExp)).not.toBeNull();
17
+ });
18
+
19
+ it("highlights the extension of a simple glob", () => {
20
+ expect("app.ts".match(globHighlight("*.ts") as RegExp)?.[0]).toBe(".ts");
21
+ });
22
+
23
+ it("returns undefined when the glob has no meaningful literal run", () => {
24
+ expect(globHighlight("*")).toBeUndefined();
25
+ });
26
+ });
10
27
 
11
28
  class MockTextComponent {
12
29
  private text = "";
@@ -108,10 +125,12 @@ describe("registerFindTool", () => {
108
125
  } as unknown as RenderContextLike,
109
126
  );
110
127
 
111
- expect(result?.getText()).toContain("src/one.ts");
112
- expect(result?.getText()).toContain("src/two.ts");
128
+ const strip = (s: string) => s.replace(/\u001b\[[0-9;]*m/g, "");
129
+ const shown = strip(result?.getText() ?? "");
130
+ expect(shown).toContain("src/one.ts");
131
+ expect(shown).toContain("src/two.ts");
113
132
  // No floating count header in the framed view — the collapsed row carries it.
114
- expect(result?.getText()).not.toContain("2 files");
133
+ expect(shown).not.toContain("2 files");
115
134
  });
116
135
 
117
136
  it("frames single-file output like multi-file (no inline row)", () => {
@@ -156,7 +175,7 @@ describe("registerFindTool", () => {
156
175
  ?.getText() ?? "";
157
176
  // Single result is framed just like multi — one shape, no inline row.
158
177
  expect(out).toContain("─");
159
- expect(out).toContain("src/a.ts");
178
+ expect(strip(out)).toContain("src/a.ts");
160
179
  expect(strip(out)).not.toContain("file");
161
180
  const multi = {
162
181
  content: [{ type: "text", text: "a.ts\nb.ts\nc.ts" }],
package/src/find.ts CHANGED
@@ -34,6 +34,25 @@ export function applyFindDefaults(params: FindParams): FindParams {
34
34
  return params.limit === undefined ? { ...params, limit: DEFAULT_FIND_LIMIT } : params;
35
35
  }
36
36
 
37
+ /**
38
+ * Build a highlight regex from a glob pattern by keeping only its literal runs
39
+ * (the wildcard-free fragments) as case-insensitive alternatives. `**​/*.test.ts`
40
+ * → highlight `.test.ts`; `*.ts` → highlight `.ts`. A pattern with no literal
41
+ * run (e.g. `*`) yields undefined — nothing meaningful to emphasize.
42
+ */
43
+ export function globHighlight(pattern: string): RegExp | undefined {
44
+ const literals = pattern
45
+ .split(/[*?{}[\],/]+/) // split on glob metacharacters + path separators
46
+ .filter((s) => s.length >= 2); // skip single chars/dots — too noisy
47
+ if (literals.length === 0) return undefined;
48
+ const alt = literals.map((s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
49
+ try {
50
+ return new RegExp(alt, "gi");
51
+ } catch {
52
+ return undefined;
53
+ }
54
+ }
55
+
37
56
  export function registerFindTool(
38
57
  pi: PiPrettyApi,
39
58
  createFindTool: ToolFactory<FindToolInput>,
@@ -138,7 +157,7 @@ export function registerFindTool(
138
157
  return text;
139
158
  text.setText(
140
159
  fillToolBackground(
141
- `${theme.fg("toolTitle", theme.bold("find"))} ${theme.fg("accent", pattern)}${path}`,
160
+ `${theme.fg("toolTitle", theme.bold("find"))} ${theme.fg("dim", pattern)}${path}`,
142
161
  ),
143
162
  );
144
163
  return text;
@@ -193,6 +212,7 @@ export function registerFindTool(
193
212
  renderDimPreview(output, theme, {
194
213
  frame: true,
195
214
  paint: (s: string) => theme.fg(renderCtx.isError ? "error" : "success", s),
215
+ highlight: d?._type === "findResult" ? globHighlight(d.pattern) : undefined,
196
216
  }),
197
217
  );
198
218
  return text;