@heyhuynhgiabuu/pi-diff 0.5.1 → 0.5.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.
package/README.md CHANGED
@@ -168,19 +168,19 @@ All custom theme colors must be `#rrggbb` hex values.
168
168
 
169
169
  ```ts
170
170
  // Open the read-only review markdown for working-tree changes, including untracked files
171
- review_git_diff({})
171
+ review_git_diff({});
172
172
 
173
173
  // Review branch changes as main...HEAD
174
- review_git_diff({ base: "main" })
174
+ review_git_diff({ base: "main" });
175
175
 
176
176
  // Focus a file from the changed-file list
177
- review_git_diff({ file: "src/index.ts" })
177
+ review_git_diff({ file: "src/index.ts" });
178
178
 
179
179
  // Focus a hunk ID shown by the panel
180
- review_git_diff({ file: "src/index.ts", hunkId: "src/index.ts:10:12" })
180
+ review_git_diff({ file: "src/index.ts", hunkId: "src/index.ts:10:12" });
181
181
 
182
182
  // Return the older full markdown export with raw unified diff included
183
- review_git_diff({ base: "main", includeRawDiff: true })
183
+ review_git_diff({ base: "main", includeRawDiff: true });
184
184
  ```
185
185
 
186
186
  - No `base` means working-tree review, including untracked files.
@@ -228,12 +228,13 @@ New content ──┘ │
228
228
 
229
229
  ### Views
230
230
 
231
- | View | Used by | Description |
232
- |------|---------|-------------|
233
- | **Split** | `edit` tool | Side-by-side with old on left, new on right. Diagonal stripes fill empty slots. Auto-falls back to unified when terminal < 150 cols or > 20% of lines would wrap. |
234
- | **Unified** | `write` tool | Single column with `+`/`-` gutter. Compact, works at any terminal width. |
231
+ | View | Used by | Description |
232
+ | ----------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
233
+ | **Split** | `edit` tool | Side-by-side with old on left, new on right. Diagonal stripes fill empty slots. Auto-falls back to unified when terminal < 150 cols or > 20% of lines would wrap. |
234
+ | **Unified** | `write` tool | Single column with `+`/`-` gutter. Compact, works at any terminal width. |
235
235
 
236
236
  Both views show:
237
+
237
238
  - Colored border bars (`▌`) for changed lines
238
239
  - Line numbers in the gutter
239
240
  - Hunk separators (`··· N unmodified lines ···`)
@@ -252,12 +253,12 @@ pi-diff ships with built-in theme presets optimized for different terminal backg
252
253
  }
253
254
  ```
254
255
 
255
- | Preset | Best for | Description |
256
- |--------|----------|-------------|
257
- | `default` | Dark theme bases (~`#1e1e2e`) | Original pi-diff colors — balanced contrast |
258
- | `midnight` | Pure black (`#000000`) terminals | Subtle tints that don't overwhelm on black |
259
- | `subtle` | Any dark theme | Minimal backgrounds — barely-there tints for a clean look |
260
- | `neon` | Low-contrast displays | Higher contrast backgrounds for better visibility |
256
+ | Preset | Best for | Description |
257
+ | ---------- | -------------------------------- | --------------------------------------------------------- |
258
+ | `default` | Dark theme bases (~`#1e1e2e`) | Original pi-diff colors — balanced contrast |
259
+ | `midnight` | Pure black (`#000000`) terminals | Subtle tints that don't overwhelm on black |
260
+ | `subtle` | Any dark theme | Minimal backgrounds — barely-there tints for a clean look |
261
+ | `neon` | Low-contrast displays | Higher contrast backgrounds for better visibility |
261
262
 
262
263
  ### Per-Color Overrides
263
264
 
@@ -294,6 +295,7 @@ Override individual diff colors in `.pi/settings.json` using hex `#RRGGBB` value
294
295
  When no `diffTheme` or `diffColors` is set, pi-diff **automatically derives** background colors from your pi theme's diff foreground colors and tool-state backgrounds. Added/context surfaces use `toolSuccessBg`; removed surfaces use `toolErrorBg`. This ensures diffs look good with any pi theme and terminal background — no configuration needed.
295
296
 
296
297
  The auto-derive uses different intensity levels:
298
+
297
299
  - **Line backgrounds**: 8–10% of the theme's diff fg color mixed into the matching tool-state background (subtle tint)
298
300
  - **Word highlights**: 20–22% (more visible for changed characters)
299
301
  - **Gutters**: 5–6% (subtler than line backgrounds)
@@ -314,31 +316,31 @@ All settings are also controllable via environment variables. Add them to your s
314
316
 
315
317
  ### Theme
316
318
 
317
- | Variable | Default | Description |
318
- |----------|---------|-------------|
319
+ | Variable | Default | Description |
320
+ | ------------ | ------------- | ---------------------------------------------------------------------- |
319
321
  | `DIFF_THEME` | `github-dark` | Shiki theme name (e.g., `dracula`, `one-dark-pro`, `catppuccin-mocha`) |
320
322
 
321
323
  ### Colors
322
324
 
323
325
  Override any diff color with hex `#RRGGBB` format:
324
326
 
325
- | Variable | Default | Description |
326
- |----------|---------|-------------|
327
- | `DIFF_BG_ADD` | `#162620` | Background for added lines |
328
- | `DIFF_BG_DEL` | `#2d1919` | Background for removed lines |
329
- | `DIFF_BG_ADD_HL` | `#234b32` | Word-level emphasis on added text |
330
- | `DIFF_BG_DEL_HL` | `#502323` | Word-level emphasis on removed text |
331
- | `DIFF_BG_GUTTER_ADD` | `#12201a` | Gutter background for added lines |
332
- | `DIFF_BG_GUTTER_DEL` | `#261616` | Gutter background for removed lines |
333
- | `DIFF_FG_ADD` | `#64b478` | Foreground for `+` signs and add indicators |
334
- | `DIFF_FG_DEL` | `#c86464` | Foreground for `-` signs and del indicators |
327
+ | Variable | Default | Description |
328
+ | -------------------- | --------- | ------------------------------------------- |
329
+ | `DIFF_BG_ADD` | `#162620` | Background for added lines |
330
+ | `DIFF_BG_DEL` | `#2d1919` | Background for removed lines |
331
+ | `DIFF_BG_ADD_HL` | `#234b32` | Word-level emphasis on added text |
332
+ | `DIFF_BG_DEL_HL` | `#502323` | Word-level emphasis on removed text |
333
+ | `DIFF_BG_GUTTER_ADD` | `#12201a` | Gutter background for added lines |
334
+ | `DIFF_BG_GUTTER_DEL` | `#261616` | Gutter background for removed lines |
335
+ | `DIFF_FG_ADD` | `#64b478` | Foreground for `+` signs and add indicators |
336
+ | `DIFF_FG_DEL` | `#c86464` | Foreground for `-` signs and del indicators |
335
337
 
336
338
  ### Layout
337
339
 
338
- | Variable | Default | Description |
339
- |----------|---------|-------------|
340
- | `DIFF_SPLIT_MIN_WIDTH` | `150` | Minimum terminal columns to use split view |
341
- | `DIFF_SPLIT_MIN_CODE_WIDTH` | `60` | Minimum code columns per side in split view |
340
+ | Variable | Default | Description |
341
+ | --------------------------- | ------- | ------------------------------------------- |
342
+ | `DIFF_SPLIT_MIN_WIDTH` | `150` | Minimum terminal columns to use split view |
343
+ | `DIFF_SPLIT_MIN_CODE_WIDTH` | `60` | Minimum code columns per side in split view |
342
344
 
343
345
  ### Example `.envrc`
344
346
 
@@ -363,26 +365,26 @@ src/
363
365
 
364
366
  ### Key internals
365
367
 
366
- | Component | Purpose |
367
- |-----------|---------|
368
- | `parseDiff()` | Converts old/new content to structured `DiffLine[]` using `diff.structuredPatch` |
369
- | `hlBlock()` | Shiki ANSI highlighting with LRU cache (192 entries) |
370
- | `injectBg()` | Composites diff backgrounds into Shiki ANSI output (fg + bg layering) |
371
- | `wordDiffAnalysis()` | Single-pass word diff → similarity score + character ranges |
372
- | `renderSplit()` | Side-by-side renderer with diagonal stripe fillers |
373
- | `renderUnified()` | Stacked single-column renderer |
374
- | `wrapAnsi()` | ANSI-aware line wrapping with state carry-forward |
375
- | `shouldUseSplit()` | Heuristic: split vs unified based on terminal width and wrap ratio |
368
+ | Component | Purpose |
369
+ | -------------------- | -------------------------------------------------------------------------------- |
370
+ | `parseDiff()` | Converts old/new content to structured `DiffLine[]` using `diff.structuredPatch` |
371
+ | `hlBlock()` | Shiki ANSI highlighting with LRU cache (192 entries) |
372
+ | `injectBg()` | Composites diff backgrounds into Shiki ANSI output (fg + bg layering) |
373
+ | `wordDiffAnalysis()` | Single-pass word diff → similarity score + character ranges |
374
+ | `renderSplit()` | Side-by-side renderer with diagonal stripe fillers |
375
+ | `renderUnified()` | Stacked single-column renderer |
376
+ | `wrapAnsi()` | ANSI-aware line wrapping with state carry-forward |
377
+ | `shouldUseSplit()` | Heuristic: split vs unified based on terminal width and wrap ratio |
376
378
 
377
379
  ### Rendering constants
378
380
 
379
- | Constant | Value | Description |
380
- |----------|-------|-------------|
381
- | `MAX_PREVIEW_LINES` | 60 | Max lines in edit preview (split view) |
382
- | `MAX_RENDER_LINES` | 150 | Max lines in write result (unified view) |
383
- | `MAX_HL_CHARS` | 80,000 | Skip syntax highlighting above this |
384
- | `CACHE_LIMIT` | 192 | LRU cache entries for highlighted blocks |
385
- | `WORD_DIFF_MIN_SIM` | 0.15 | Minimum similarity for word-level emphasis |
381
+ | Constant | Value | Description |
382
+ | ------------------- | ------ | ------------------------------------------ |
383
+ | `MAX_PREVIEW_LINES` | 60 | Max lines in edit preview (split view) |
384
+ | `MAX_RENDER_LINES` | 150 | Max lines in write result (unified view) |
385
+ | `MAX_HL_CHARS` | 80,000 | Skip syntax highlighting above this |
386
+ | `CACHE_LIMIT` | 192 | LRU cache entries for highlighted blocks |
387
+ | `WORD_DIFF_MIN_SIM` | 0.15 | Minimum similarity for word-level emphasis |
386
388
 
387
389
  ## Exports
388
390
 
@@ -391,7 +393,8 @@ The extension exports a `__testing` object for unit testing:
391
393
  ```typescript
392
394
  import { __testing } from "@heyhuynhgiabuu/pi-diff";
393
395
 
394
- const { parseDiff, renderSplit, renderUnified, normalizeShikiContrast } = __testing;
396
+ const { parseDiff, renderSplit, renderUnified, normalizeShikiContrast } =
397
+ __testing;
395
398
  ```
396
399
 
397
400
  ## Development
@@ -437,7 +440,8 @@ export default function piDiffExtension(pi: any): void {
437
440
  ```
438
441
 
439
442
  Extensions can:
440
- - **Register tools** — `pi.registerTool(definition)`
443
+
444
+ - **Register tools** — `pi.registerTool(definition)`
441
445
  - **Listen to events** — `pi.on("session_start" | "input" | "before_tool_call" | ...)`
442
446
  - **Register commands** — `pi.registerCommand("/name", handler)`
443
447
  - **Register providers** — `pi.registerProvider("name", config)`
@@ -1,8 +1,19 @@
1
+ /** Hunk metadata attached to separator DiffLines. */
2
+ export interface HunkMeta {
3
+ oldStart: number;
4
+ oldLines: number;
5
+ newStart: number;
6
+ newLines: number;
7
+ /** Function context from hunk header, e.g. "function foo() {" */
8
+ context?: string;
9
+ }
1
10
  export interface DiffLine {
2
11
  type: "add" | "del" | "ctx" | "sep";
3
12
  oldNum: number | null;
4
13
  newNum: number | null;
5
14
  content: string;
15
+ /** Hunk metadata — present on first sep and between-hunk seps if available. */
16
+ hunkMeta?: HunkMeta;
6
17
  }
7
18
  export interface ParsedDiff {
8
19
  lines: DiffLine[];
@@ -10,5 +21,44 @@ export interface ParsedDiff {
10
21
  removed: number;
11
22
  chars: number;
12
23
  }
24
+ /**
25
+ * Parse a unified diff/patch string into one or more ParsedDiff.
26
+ * Each file in the patch gets its own entry.
27
+ */
28
+ export declare function parsePatchFiles(patch: string): ParsedDiff[];
29
+ /** Style for rendering hunk separators between change blocks. */
30
+ export type HunkSeparatorStyle = "auto" | "simple" | "gap" | "context" | "metadata";
31
+ /**
32
+ * Resolve hunk separator style from env var PI_DIFF_SEP_STYLE.
33
+ * Call once during extension init, or with force=true to re-read.
34
+ */
35
+ export declare function resolveSepStyle(): HunkSeparatorStyle;
36
+ /**
37
+ * Get the current separator style (resolved once via resolveSepStyle()).
38
+ */
39
+ export declare function getSepStyle(): HunkSeparatorStyle;
40
+ /**
41
+ * Generate a hunk separator label for the unified view.
42
+ * Returns the full label including spacing, or "···" for empty/default.
43
+ * If `content` is non-empty, it is used directly (e.g. "───── Edit 2 ─────").
44
+ */
45
+ export declare function sepLabelUnified(style: HunkSeparatorStyle, hunkMeta: HunkMeta | undefined, gap: number | null, content?: string): string;
46
+ /**
47
+ * Generate a hunk separator label for the split view.
48
+ * Wraps the content in "··· ... ···".
49
+ * If `content` is non-empty, it is used directly (e.g. "───── Edit 2 ─────").
50
+ */
51
+ export declare function sepLabelSplit(style: HunkSeparatorStyle, hunkMeta: HunkMeta | undefined, gap: number | null, content?: string): string;
52
+ /** A paired block of deletions and additions within a hunk. */
53
+ export interface HunkBlock {
54
+ deletions: DiffLine[];
55
+ additions: DiffLine[];
56
+ }
57
+ /**
58
+ * Walk a ParsedDiff and extract hunk blocks.
59
+ * Each block is a group of consecutive deletes followed by consecutive adds.
60
+ * Context and separator lines are skipped.
61
+ */
62
+ export declare function computeHunkBlocks(diff: ParsedDiff): HunkBlock[];
13
63
  export declare function parseDiff(oldContent: string, newContent: string, ctx?: number): ParsedDiff;
14
64
  //# sourceMappingURL=diff.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/core/diff.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,QAAQ;IACxB,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;IACpC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IAC1B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,SAAI,GAAG,UAAU,CA+BrF"}
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/core/diff.ts"],"names":[],"mappings":"AAMA,qDAAqD;AACrD,MAAM,WAAW,QAAQ;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACxB,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;IACpC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IAC1B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACd;AAeD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,CAyB3D;AA+FD,iEAAiE;AACjE,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,GAAG,UAAU,CAAC;AAIpF;;;GAGG;AACH,wBAAgB,eAAe,IAAI,kBAAkB,CAQpD;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,kBAAkB,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC9B,KAAK,EAAE,kBAAkB,EACzB,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAC9B,GAAG,EAAE,MAAM,GAAG,IAAI,EAClB,OAAO,CAAC,EAAE,MAAM,GACd,MAAM,CA2BR;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC5B,KAAK,EAAE,kBAAkB,EACzB,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAC9B,GAAG,EAAE,MAAM,GAAG,IAAI,EAClB,OAAO,CAAC,EAAE,MAAM,GACd,MAAM,CA4BR;AASD,+DAA+D;AAC/D,MAAM,WAAW,SAAS;IACzB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,SAAS,EAAE,QAAQ,EAAE,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,EAAE,CA8B/D;AAED,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,SAAI,GAAG,UAAU,CA2CrF"}
package/dist/core/diff.js CHANGED
@@ -1,16 +1,287 @@
1
1
  import * as Diff from "diff";
2
+ // ---------------------------------------------------------------------------
3
+ // Unified diff patch parsing
4
+ //
5
+ // Parses git/unified diff strings (output of `git diff`, `Diff.formatPatch`,
6
+ // or similar) into our internal ParsedDiff representation. Preserves hunk
7
+ // function context from hunk headers.
8
+ //
9
+ // Handles these formats:
10
+ // diff --git a/file.ts b/file.ts \n --- a/file.ts \n +++ b/file.ts
11
+ // --- a/file.ts \n +++ b/file.ts (no diff --git prefix)
12
+ // @@ -start,count +start,count @@ func_name (with or without func context)
13
+ // ---------------------------------------------------------------------------
14
+ /**
15
+ * Parse a unified diff/patch string into one or more ParsedDiff.
16
+ * Each file in the patch gets its own entry.
17
+ */
18
+ export function parsePatchFiles(patch) {
19
+ if (!patch || !patch.trim())
20
+ return [];
21
+ // Split into file sections
22
+ const lines = patch.split("\n");
23
+ const sections = [];
24
+ let cur = [];
25
+ // Split by "+++ " or "diff --git " (start of a new file)
26
+ for (let i = 0; i < lines.length; i++) {
27
+ const l = lines[i];
28
+ if (l.startsWith("diff --git ") || (l.startsWith("--- ") && cur.length > 0 && cur[0]?.startsWith("+++"))) {
29
+ if (cur.length > 0)
30
+ sections.push(cur);
31
+ cur = [];
32
+ }
33
+ cur.push(l);
34
+ }
35
+ if (cur.length > 0)
36
+ sections.push(cur);
37
+ const result = [];
38
+ for (const sec of sections) {
39
+ const parsed = parseOneFile(sec);
40
+ if (parsed)
41
+ result.push(parsed);
42
+ }
43
+ return result.length > 0 ? result : [parseOneFile(lines) ?? emptyDiff()];
44
+ }
45
+ /** Parse a single file section into a ParsedDiff. */
46
+ function parseOneFile(lines) {
47
+ const all = [];
48
+ let added = 0, removed = 0;
49
+ let i = 0;
50
+ while (i < lines.length) {
51
+ const raw = lines[i];
52
+ const hdr = parseHunkHeader(raw);
53
+ if (!hdr) {
54
+ i++;
55
+ continue;
56
+ }
57
+ // Emit sep for this hunk's metadata (synthetic at position 0 for first)
58
+ if (all.length === 0 || all.filter((l) => l.type !== "sep").length > 0) {
59
+ // After some non-sep content, push a sep for the next hunk
60
+ all.push({ type: "sep", oldNum: null, newNum: null, content: "", hunkMeta: hdr });
61
+ }
62
+ else {
63
+ // Already have only seps (first hunk) — update the last sep's metadata
64
+ all[all.length - 1] = { type: "sep", oldNum: null, newNum: null, content: "", hunkMeta: hdr };
65
+ }
66
+ let oL = hdr.oldStart;
67
+ let nL = hdr.newStart;
68
+ // Advance past the hunk header
69
+ i++;
70
+ // Process hunk content lines (until next hunk header or end)
71
+ while (i < lines.length) {
72
+ const line = lines[i];
73
+ if (line.startsWith("@@"))
74
+ break; // next hunk header — outer loop handles it
75
+ if (line.startsWith("\\ ")) {
76
+ i++;
77
+ continue; // "\"
78
+ }
79
+ if (/^(---|\+\+\+|diff --git|index |new file|old mode|new mode|deleted|rename|similarity|copy)/.test(line)) {
80
+ i++;
81
+ continue; // skip headers/metadata
82
+ }
83
+ if (line.length === 0 || line[0] === " ") {
84
+ all.push({ type: "ctx", oldNum: oL++, newNum: nL++, content: line.slice(1) });
85
+ }
86
+ else if (line[0] === "+") {
87
+ all.push({ type: "add", oldNum: null, newNum: nL++, content: line.slice(1) });
88
+ added++;
89
+ }
90
+ else if (line[0] === "-") {
91
+ all.push({ type: "del", oldNum: oL++, newNum: null, content: line.slice(1) });
92
+ removed++;
93
+ }
94
+ i++;
95
+ }
96
+ }
97
+ if (all.length === 0)
98
+ return null;
99
+ // Compute chars from content lines only (not seps)
100
+ let chars = 0;
101
+ for (const l of all) {
102
+ if (l.type !== "sep")
103
+ chars += l.content.length;
104
+ }
105
+ return { lines: all, added, removed, chars };
106
+ }
107
+ /**
108
+ * Parse a hunk header line like:
109
+ * @@ -oldStart,oldCount +newStart,newCount @@ optional func context
110
+ */
111
+ function parseHunkHeader(line) {
112
+ const m = line.match(/^@@\s+-(\d+)(?:,(\d+))?\s+\+(\d+)(?:,(\d+))?\s+@@(?:\s+(.*))?$/);
113
+ if (!m)
114
+ return null;
115
+ const oldStart = Number(m[1]);
116
+ const oldLines = m[2] ? Number(m[2]) : 1;
117
+ const newStart = Number(m[3]);
118
+ const newLines = m[4] ? Number(m[4]) : 1;
119
+ const context = m[5]?.trim() || undefined;
120
+ return { oldStart, oldLines, newStart, newLines, context };
121
+ }
122
+ function emptyDiff() {
123
+ return { lines: [], added: 0, removed: 0, chars: 0 };
124
+ }
125
+ let _sepStyle = "auto";
126
+ /**
127
+ * Resolve hunk separator style from env var PI_DIFF_SEP_STYLE.
128
+ * Call once during extension init, or with force=true to re-read.
129
+ */
130
+ export function resolveSepStyle() {
131
+ const fromEnv = process.env.PI_DIFF_SEP_STYLE;
132
+ if (fromEnv && ["auto", "simple", "gap", "context", "metadata"].includes(fromEnv)) {
133
+ _sepStyle = fromEnv;
134
+ }
135
+ else {
136
+ _sepStyle = "auto";
137
+ }
138
+ return _sepStyle;
139
+ }
140
+ /**
141
+ * Get the current separator style (resolved once via resolveSepStyle()).
142
+ */
143
+ export function getSepStyle() {
144
+ return _sepStyle;
145
+ }
146
+ /**
147
+ * Generate a hunk separator label for the unified view.
148
+ * Returns the full label including spacing, or "···" for empty/default.
149
+ * If `content` is non-empty, it is used directly (e.g. "───── Edit 2 ─────").
150
+ */
151
+ export function sepLabelUnified(style, hunkMeta, gap, content) {
152
+ // Custom content (e.g. multi-edit separators) takes precedence
153
+ if (content)
154
+ return ` ${content} `;
155
+ const ctx = hunkMeta?.context;
156
+ switch (style) {
157
+ case "simple":
158
+ return "···";
159
+ case "gap":
160
+ if (gap && gap > 0)
161
+ return ` ${gap} unmodified lines `;
162
+ return "···";
163
+ case "context":
164
+ if (ctx)
165
+ return ` ${ctx} `;
166
+ if (gap && gap > 0)
167
+ return ` ${gap} unmodified lines `;
168
+ return "···";
169
+ case "metadata": {
170
+ if (!hunkMeta)
171
+ return "···";
172
+ const hdr = `@@ -${hunkMeta.oldStart},${hunkMeta.oldLines} +${hunkMeta.newStart},${hunkMeta.newLines} @@`;
173
+ const label = ctx ? `${hdr} ${ctx}` : hdr;
174
+ return ` ${label} `;
175
+ }
176
+ case "auto":
177
+ default:
178
+ if (ctx && gap && gap > 0)
179
+ return ` ${ctx} — +${gap} lines `;
180
+ if (ctx)
181
+ return ` ${ctx} `;
182
+ if (gap && gap > 0)
183
+ return ` +${gap} lines `;
184
+ return "···";
185
+ }
186
+ }
187
+ /**
188
+ * Generate a hunk separator label for the split view.
189
+ * Wraps the content in "··· ... ···".
190
+ * If `content` is non-empty, it is used directly (e.g. "───── Edit 2 ─────").
191
+ */
192
+ export function sepLabelSplit(style, hunkMeta, gap, content) {
193
+ // Custom content (e.g. multi-edit separators) takes precedence
194
+ if (content)
195
+ return `${content}`;
196
+ const ctx = hunkMeta?.context;
197
+ switch (style) {
198
+ case "simple":
199
+ return "···";
200
+ case "gap":
201
+ if (gap && gap > 0)
202
+ return `··· ${gap} lines ···`;
203
+ return "···";
204
+ case "context":
205
+ if (ctx && gap && gap > 0)
206
+ return `··· ${ctx} — ${gap} lines ···`;
207
+ if (ctx)
208
+ return `··· ${ctx} ···`;
209
+ if (gap && gap > 0)
210
+ return `··· ${gap} lines ···`;
211
+ return "···";
212
+ case "metadata": {
213
+ if (!hunkMeta)
214
+ return "···";
215
+ const hdr = `@@ -${hunkMeta.oldStart},${hunkMeta.oldLines} +${hunkMeta.newStart},${hunkMeta.newLines} @@`;
216
+ const content = ctx ? `${hdr} ${ctx}` : hdr;
217
+ return `··· ${content} ···`;
218
+ }
219
+ case "auto":
220
+ default:
221
+ if (ctx && gap && gap > 0)
222
+ return `··· ${ctx} — +${gap} lines ···`;
223
+ if (ctx)
224
+ return `··· ${ctx} ···`;
225
+ if (gap && gap > 0)
226
+ return `··· +${gap} lines ···`;
227
+ return "···";
228
+ }
229
+ }
230
+ /**
231
+ * Walk a ParsedDiff and extract hunk blocks.
232
+ * Each block is a group of consecutive deletes followed by consecutive adds.
233
+ * Context and separator lines are skipped.
234
+ */
235
+ export function computeHunkBlocks(diff) {
236
+ const blocks = [];
237
+ let i = 0;
238
+ const lines = diff.lines;
239
+ while (i < lines.length) {
240
+ if (lines[i].type === "sep" || lines[i].type === "ctx") {
241
+ i++;
242
+ continue;
243
+ }
244
+ // Collect consecutive deletions
245
+ const deletions = [];
246
+ while (i < lines.length && lines[i].type === "del") {
247
+ deletions.push(lines[i]);
248
+ i++;
249
+ }
250
+ // Collect consecutive additions
251
+ const additions = [];
252
+ while (i < lines.length && lines[i].type === "add") {
253
+ additions.push(lines[i]);
254
+ i++;
255
+ }
256
+ if (deletions.length === 0 && additions.length === 0)
257
+ continue;
258
+ blocks.push({ deletions, additions });
259
+ }
260
+ return blocks;
261
+ }
2
262
  export function parseDiff(oldContent, newContent, ctx = 3) {
3
263
  const patch = Diff.structuredPatch("", "", oldContent, newContent, "", "", { context: ctx });
4
264
  const lines = [];
5
265
  let added = 0;
6
266
  let removed = 0;
7
267
  for (let hi = 0; hi < patch.hunks.length; hi++) {
268
+ const h = patch.hunks[hi];
269
+ const meta = {
270
+ oldStart: h.oldStart,
271
+ oldLines: h.oldLines,
272
+ newStart: h.newStart,
273
+ newLines: h.newLines,
274
+ };
275
+ // Emit hunk metadata as a synthetic sep (position 0 for first hunk,
276
+ // between-hunk sep for subsequent). This ensures every hunk has metadata.
8
277
  if (hi > 0) {
9
278
  const prev = patch.hunks[hi - 1];
10
- const gap = patch.hunks[hi].oldStart - (prev.oldStart + prev.oldLines);
11
- lines.push({ type: "sep", oldNum: null, newNum: gap > 0 ? gap : null, content: "" });
279
+ const gap = h.oldStart - (prev.oldStart + prev.oldLines);
280
+ lines.push({ type: "sep", oldNum: null, newNum: gap > 0 ? gap : null, content: "", hunkMeta: meta });
281
+ }
282
+ else {
283
+ lines.push({ type: "sep", oldNum: null, newNum: null, content: "", hunkMeta: meta });
12
284
  }
13
- const h = patch.hunks[hi];
14
285
  let oL = h.oldStart;
15
286
  let nL = h.newStart;
16
287
  for (const raw of h.lines) {
@@ -1 +1 @@
1
- {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/core/diff.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAgB7B,MAAM,UAAU,SAAS,CAAC,UAAkB,EAAE,UAAkB,EAAE,GAAG,GAAG,CAAC;IACxE,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7F,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;QAChD,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACjC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,QAAQ,GAAG,CAAC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1B,IAAI,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC;QACpB,IAAI,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC;QACpB,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;YAC3B,IAAI,GAAG,KAAK,8BAA8B;gBAAE,SAAS;YACrD,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YAClB,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC1B,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;gBAChB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvE,KAAK,EAAE,CAAC;YACT,CAAC;iBAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;gBACvB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvE,OAAO,EAAE,CAAC;YACX,CAAC;iBAAM,CAAC;gBACP,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACxE,CAAC;QACF,CAAC;IACF,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC;AAChF,CAAC"}
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/core/diff.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -21,7 +21,7 @@
21
21
  * • Async rendering with invalidate() for non-blocking preview
22
22
  */
23
23
  import type { BundledLanguage } from "shiki";
24
- import { type ParsedDiff, parseDiff } from "./core/diff.js";
24
+ import { computeHunkBlocks, type ParsedDiff, getSepStyle, parseDiff, parsePatchFiles, resolveSepStyle } from "./core/diff.js";
25
25
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
26
26
  /** Resolved ANSI colors for diff rendering — theme overrides hardcoded defaults. */
27
27
  interface DiffColors {
@@ -33,8 +33,12 @@ declare function normalizeShikiContrast(ansi: string): string;
33
33
  declare function renderUnified(diff: ParsedDiff, language: BundledLanguage | undefined, max?: number, dc?: DiffColors): Promise<string>;
34
34
  declare function renderSplit(diff: ParsedDiff, language: BundledLanguage | undefined, max?: number, dc?: DiffColors): Promise<string>;
35
35
  export declare const __testing: {
36
+ computeHunkBlocks: typeof computeHunkBlocks;
36
37
  normalizeShikiContrast: typeof normalizeShikiContrast;
38
+ getSepStyle: typeof getSepStyle;
37
39
  parseDiff: typeof parseDiff;
40
+ parsePatchFiles: typeof parsePatchFiles;
41
+ resolveSepStyle: typeof resolveSepStyle;
38
42
  renderSplit: typeof renderSplit;
39
43
  renderUnified: typeof renderUnified;
40
44
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAOH,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,OAAO,CAAC;AAG3D,OAAO,EAAiB,KAAK,UAAU,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AA2cpE,oFAAoF;AACpF,UAAU,UAAU;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACd;AAuKD,iBAAS,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIpD;AAuVD,iBAAe,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,eAAe,GAAG,SAAS,EACrC,GAAG,SAAmB,EACtB,EAAE,GAAE,UAAgC,GAClC,OAAO,CAAC,MAAM,CAAC,CA8HjB;AAMD,iBAAe,WAAW,CACzB,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,eAAe,GAAG,SAAS,EACrC,GAAG,SAAoB,EACvB,EAAE,GAAE,UAAgC,GAClC,OAAO,CAAC,MAAM,CAAC,CA6JjB;AAMD,eAAO,MAAM,SAAS;;;;;CAKrB,CAAC;AAmCF,wBAA8B,qBAAqB,CAAC,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA0dnF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAOH,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,OAAO,CAAC;AAG3D,OAAO,EAAE,iBAAiB,EAAiB,KAAK,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,eAAe,EAAE,eAAe,EAAkC,MAAM,gBAAgB,CAAC;AAC7K,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AA2cpE,oFAAoF;AACpF,UAAU,UAAU;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACd;AAuKD,iBAAS,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIpD;AAuVD,iBAAe,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,eAAe,GAAG,SAAS,EACrC,GAAG,SAAmB,EACtB,EAAE,GAAE,UAAgC,GAClC,OAAO,CAAC,MAAM,CAAC,CA6HjB;AAMD,iBAAe,WAAW,CACzB,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,eAAe,GAAG,SAAS,EACrC,GAAG,SAAoB,EACvB,EAAE,GAAE,UAAgC,GAClC,OAAO,CAAC,MAAM,CAAC,CAkKjB;AAMD,eAAO,MAAM,SAAS;;;;;;;;;CASrB,CAAC;AAIF,wBAA8B,qBAAqB,CAAC,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA4gBnF"}