dsh-diff-approval 0.14.1 → 0.15.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.
- package/lib/client.js +739 -273
- package/lib/index.js +23 -1
- package/lib/types/client/PendingPanel.d.ts +12 -0
- package/lib/types/client/locales.d.ts +10 -2
- package/lib/types/client/settings.d.ts +13 -0
- package/lib/types/client/split-diff.d.ts +7 -4
- package/lib/types/client/whole-file-diff.d.ts +58 -0
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -424,6 +424,11 @@ function defaultOpenPath(path, action) {
|
|
|
424
424
|
/** Cap on one VCS command's runtime; scans (git status, svn status) can be slow
|
|
425
425
|
* on large trees but must not hang the import. */
|
|
426
426
|
const VCS_COMMAND_TIMEOUT_MS = 6e4;
|
|
427
|
+
/** Blobs up to this size are read straight off the executor's buffered stdout
|
|
428
|
+
* (the small-blob path, no temp file); larger blobs go through the checkout-index
|
|
429
|
+
* temp-file path because the executor cap truncates its stdout. Kept below the
|
|
430
|
+
* cap so the small path never truncates. */
|
|
431
|
+
const GIT_BLOB_STDOUT_SAFE = 6e4;
|
|
427
432
|
/** Quote one argument for a POSIX-ish shell, so paths with spaces or special
|
|
428
433
|
* characters survive interpolation into VCS command lines. */
|
|
429
434
|
function shq(value) {
|
|
@@ -528,7 +533,24 @@ async function gitChanges(input) {
|
|
|
528
533
|
if (worktree !== "M" && worktree !== "D") continue;
|
|
529
534
|
let oldText = "";
|
|
530
535
|
try {
|
|
531
|
-
|
|
536
|
+
let size = 0;
|
|
537
|
+
try {
|
|
538
|
+
size = Number.parseInt((await runShell(shell, `git cat-file -s :0:${shq(rel)}`, root, signal)).trim(), 10);
|
|
539
|
+
} catch {
|
|
540
|
+
size = 0;
|
|
541
|
+
}
|
|
542
|
+
if (Number.isFinite(size) && size > 0 && size <= GIT_BLOB_STDOUT_SAFE) oldText = await runShell(shell, `git show :0:${shq(rel)}`, root, signal);
|
|
543
|
+
else {
|
|
544
|
+
const tempRel = (await runShell(shell, `git checkout-index --temp --force -- ${shq(rel)}`, root, signal)).trim().split(/\s+/)[0] ?? "";
|
|
545
|
+
if (tempRel !== "") {
|
|
546
|
+
const tempFile = resolve(root, tempRel);
|
|
547
|
+
try {
|
|
548
|
+
oldText = await readText(tempFile) ?? "";
|
|
549
|
+
} finally {
|
|
550
|
+
await rm(tempFile, { force: true }).catch(() => {});
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
532
554
|
} catch {
|
|
533
555
|
oldText = "";
|
|
534
556
|
}
|
|
@@ -5,6 +5,7 @@ import type { DiffApprovalBlockRange, PendingFileDiff } from '../types.ts';
|
|
|
5
5
|
import type { PendingPanelFace } from './slots.ts';
|
|
6
6
|
import type { DiffApprovalKey } from './locales.ts';
|
|
7
7
|
import { computeWholeFileDiff } from './whole-file-diff.ts';
|
|
8
|
+
import type { IntraRun } from './whole-file-diff.ts';
|
|
8
9
|
import { highlightLines } from './highlight.ts';
|
|
9
10
|
/** The dsh shell's sidebar auto-collapse breakpoint (ui-layout columns.ts):
|
|
10
11
|
* below it the sidebar auto-collapses, and the file list floats on the same
|
|
@@ -30,6 +31,8 @@ interface RowModel {
|
|
|
30
31
|
diff: ReturnType<typeof computeWholeFileDiff>;
|
|
31
32
|
/** Maximal runs of changed rows (inclusive row indices); one per modification. */
|
|
32
33
|
blocks: ChangeBlock[];
|
|
34
|
+
/** Intra-line runs keyed by row index, present only for annotated del/add rows. */
|
|
35
|
+
intra: Map<number, IntraRun[]>;
|
|
33
36
|
}
|
|
34
37
|
/** One file's deferred syntax-highlight runs, one entry per side. */
|
|
35
38
|
interface HighlightRuns {
|
|
@@ -65,9 +68,18 @@ export declare const SplitDiff: import("react").ForwardRefExoticComponent<{
|
|
|
65
68
|
busy: boolean;
|
|
66
69
|
t: Translator;
|
|
67
70
|
selection: RowRange | undefined;
|
|
71
|
+
leadRows: number;
|
|
68
72
|
onBlockKeep: (sessionId: SessionId, id: string, block: DiffApprovalBlockRange) => Promise<void>;
|
|
69
73
|
onBlockRevert: (sessionId: SessionId, id: string, block: DiffApprovalBlockRange) => Promise<void>;
|
|
70
74
|
} & import("react").RefAttributes<SplitDiffHandle>>;
|
|
75
|
+
/**
|
|
76
|
+
* Reconstruct the plain text of the current selection so auto-wrap's visual
|
|
77
|
+
* line breaks never leak into the clipboard. A wrapped row renders its code as
|
|
78
|
+
* several `.subline` block elements, and the browser's default copy inserts a
|
|
79
|
+
* newline between them; those segments form one logical line, so they are joined
|
|
80
|
+
* without a newline while the real newline between diff rows is kept.
|
|
81
|
+
*/
|
|
82
|
+
export declare function selectedPlainText(): string | undefined;
|
|
71
83
|
/** Render the pending-edit review panel and its unified footer action. */
|
|
72
84
|
export declare function PendingPanel({ wide, useSessions, usePending, onRefresh, onKeep, onRevert, onBlockKeep, onBlockRevert, onOpen, onPasteReference, onUndo, onRedo, onImportVcs, onAckRedoCleared, onAckJustResolved, collapseSidebar, t, }: PendingPanelProps): import("react").JSX.Element;
|
|
73
85
|
export {};
|
|
@@ -17,7 +17,6 @@ export declare const zh: {
|
|
|
17
17
|
'panel.missingHint': string;
|
|
18
18
|
'panel.externalChanged': string;
|
|
19
19
|
'panel.dismiss': string;
|
|
20
|
-
'panel.createHint': string;
|
|
21
20
|
'panel.pasteOnCopy': string;
|
|
22
21
|
'panel.pasteOnCopyDesc': string;
|
|
23
22
|
'panel.importUntracked': string;
|
|
@@ -26,6 +25,8 @@ export declare const zh: {
|
|
|
26
25
|
'panel.tabWidthDesc': string;
|
|
27
26
|
'panel.splitMode': string;
|
|
28
27
|
'panel.splitModeDesc': string;
|
|
28
|
+
'panel.navLeadRows': string;
|
|
29
|
+
'panel.navLeadRowsDesc': string;
|
|
29
30
|
'panel.quickSummon': string;
|
|
30
31
|
'panel.quickSummonDesc': string;
|
|
31
32
|
'panel.recordShortcut': string;
|
|
@@ -37,6 +38,7 @@ export declare const zh: {
|
|
|
37
38
|
'row.removed': string;
|
|
38
39
|
'action.keep': string;
|
|
39
40
|
'action.revert': string;
|
|
41
|
+
'action.delete': string;
|
|
40
42
|
'action.keepAll': string;
|
|
41
43
|
'action.revertAll': string;
|
|
42
44
|
'action.openFile': string;
|
|
@@ -54,6 +56,8 @@ export declare const zh: {
|
|
|
54
56
|
'action.wrap': string;
|
|
55
57
|
'action.toggleOn': string;
|
|
56
58
|
'action.toggleOff': string;
|
|
59
|
+
'action.decrease': string;
|
|
60
|
+
'action.increase': string;
|
|
57
61
|
'action.importVcs': string;
|
|
58
62
|
'action.importVcsBusy': string;
|
|
59
63
|
'panel.importNone': string;
|
|
@@ -96,7 +100,6 @@ export declare const en: {
|
|
|
96
100
|
'panel.missingHint': string;
|
|
97
101
|
'panel.externalChanged': string;
|
|
98
102
|
'panel.dismiss': string;
|
|
99
|
-
'panel.createHint': string;
|
|
100
103
|
'panel.pasteOnCopy': string;
|
|
101
104
|
'panel.pasteOnCopyDesc': string;
|
|
102
105
|
'panel.importUntracked': string;
|
|
@@ -105,6 +108,8 @@ export declare const en: {
|
|
|
105
108
|
'panel.tabWidthDesc': string;
|
|
106
109
|
'panel.splitMode': string;
|
|
107
110
|
'panel.splitModeDesc': string;
|
|
111
|
+
'panel.navLeadRows': string;
|
|
112
|
+
'panel.navLeadRowsDesc': string;
|
|
108
113
|
'panel.quickSummon': string;
|
|
109
114
|
'panel.quickSummonDesc': string;
|
|
110
115
|
'panel.recordShortcut': string;
|
|
@@ -116,6 +121,7 @@ export declare const en: {
|
|
|
116
121
|
'row.removed': string;
|
|
117
122
|
'action.keep': string;
|
|
118
123
|
'action.revert': string;
|
|
124
|
+
'action.delete': string;
|
|
119
125
|
'action.keepAll': string;
|
|
120
126
|
'action.revertAll': string;
|
|
121
127
|
'action.openFile': string;
|
|
@@ -133,6 +139,8 @@ export declare const en: {
|
|
|
133
139
|
'action.wrap': string;
|
|
134
140
|
'action.toggleOn': string;
|
|
135
141
|
'action.toggleOff': string;
|
|
142
|
+
'action.decrease': string;
|
|
143
|
+
'action.increase': string;
|
|
136
144
|
'action.importVcs': string;
|
|
137
145
|
'action.importVcsBusy': string;
|
|
138
146
|
'panel.importNone': string;
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
/** Client preferences for the review panel, persisted in localStorage. */
|
|
2
|
+
/** Default lead rows above a jumped-to diff block (kept small and bounded). */
|
|
3
|
+
export declare const NAV_LEAD_ROWS_DEFAULT = 2;
|
|
4
|
+
export declare const NAV_LEAD_ROWS_MIN = 0;
|
|
5
|
+
export declare const NAV_LEAD_ROWS_MAX = 10;
|
|
2
6
|
/**
|
|
3
7
|
* Whether copying a reference should also paste it into the chat input and
|
|
4
8
|
* focus it. Defaults to on; only an explicit `'0'` disables it.
|
|
@@ -45,6 +49,15 @@ export declare function setTabWidth(value: number): void;
|
|
|
45
49
|
export declare function splitMode(): boolean;
|
|
46
50
|
/** Persist the split-view preference. */
|
|
47
51
|
export declare function setSplitMode(value: boolean): void;
|
|
52
|
+
/**
|
|
53
|
+
* How many rows of lead the diff block jump leaves above the jumped-to block,
|
|
54
|
+
* and how far the anchored navigation scans. Defaults to 2; an out-of-range or
|
|
55
|
+
* non-integer value falls back to the default.
|
|
56
|
+
* @returns the lead row count.
|
|
57
|
+
*/
|
|
58
|
+
export declare function navLeadRows(): number;
|
|
59
|
+
/** Persist the block-jump lead row count. */
|
|
60
|
+
export declare function setNavLeadRows(value: number): void;
|
|
48
61
|
/** Default quick-summon chord (toggle the review panel open/closed). */
|
|
49
62
|
export declare const DEFAULT_QUICK_SUMMON = "Ctrl+D";
|
|
50
63
|
/**
|
|
@@ -32,13 +32,16 @@ export interface SplitDiff {
|
|
|
32
32
|
pairOfRow: ReadonlyMap<number, number>;
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
|
-
* Regroup the whole-file rows into aligned split pairs,
|
|
36
|
-
*
|
|
37
|
-
*
|
|
35
|
+
* Regroup the whole-file rows into aligned split pairs. By order, a deletion
|
|
36
|
+
* run pairs line-by-line with a following addition run; with similarity
|
|
37
|
+
* alignment, each deletion pairs with its most-similar addition (order
|
|
38
|
+
* preserved, threshold-bounded) so a mixed insert/delete block does not force a
|
|
39
|
+
* wrong line together. A stray deletion or addition stays a one-sided pair.
|
|
38
40
|
* @param rows - the whole-file diff rows.
|
|
41
|
+
* @param alignBySimilarity - align a change block by similarity instead of order.
|
|
39
42
|
* @returns the split pairs plus the row→pair index map.
|
|
40
43
|
*/
|
|
41
|
-
export declare function computeSideBySideDiff(rows: readonly WholeFileDiffRow[]): SplitDiff;
|
|
44
|
+
export declare function computeSideBySideDiff(rows: readonly WholeFileDiffRow[], alignBySimilarity?: boolean): SplitDiff;
|
|
42
45
|
/**
|
|
43
46
|
* Pair indices whose left or right text contains the query (case-insensitive).
|
|
44
47
|
* A pair counts once however many times the query appears, so split search
|
|
@@ -47,3 +47,61 @@ export interface WholeFileDiff {
|
|
|
47
47
|
*/
|
|
48
48
|
export declare function contentKey(text: string): string;
|
|
49
49
|
export declare function computeWholeFileDiff(oldText: string, newText: string): WholeFileDiff;
|
|
50
|
+
/**
|
|
51
|
+
* One intra-line segment of a changed line, used to highlight which characters
|
|
52
|
+
* within a paired del/add line differ. A run is either unmarked context
|
|
53
|
+
* (`same`) or the characters that were removed (`del`) /
|
|
54
|
+
* added (`add`). Reassembling the runs of a del row in order yields the old
|
|
55
|
+
* line's text; the runs of the paired add row yield the new line's text.
|
|
56
|
+
*/
|
|
57
|
+
export interface IntraRun {
|
|
58
|
+
text: string;
|
|
59
|
+
kind: 'same' | 'del' | 'add';
|
|
60
|
+
}
|
|
61
|
+
/** One matched del→add row pair within a change block. */
|
|
62
|
+
interface BlockPair {
|
|
63
|
+
delIndex: number;
|
|
64
|
+
addIndex: number;
|
|
65
|
+
}
|
|
66
|
+
/** The alignment of one del/add change block: matched pairs and excess sides. */
|
|
67
|
+
export interface BlockAlignment {
|
|
68
|
+
/** Matched del→add pairs, in file order. */
|
|
69
|
+
pairs: BlockPair[];
|
|
70
|
+
/** Row indices of unmatched deletions (shown as del-only in the split view). */
|
|
71
|
+
delOnly: number[];
|
|
72
|
+
/** Row indices of unmatched additions (shown as add-only in the split view). */
|
|
73
|
+
addOnly: number[];
|
|
74
|
+
/** True when similarity matching actually ran. False for a by-order block or a
|
|
75
|
+
* block too large to match — the caller then skips the intra-line highlight so
|
|
76
|
+
* alignment and highlighting are all-or-nothing (either both or neither). */
|
|
77
|
+
usedSimilarity: boolean;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Align a del run with the following add run. By order (the baseline) pairs
|
|
81
|
+
* `del[i]`↔`add[i]`. With similarity alignment, an order-preserving best match
|
|
82
|
+
* pairs each del with the add that maximises total similarity, keeping a pair
|
|
83
|
+
* only when it clears the similarity threshold — so a lone insert or delete in
|
|
84
|
+
* a mixed block stays unaligned instead of being forced onto a wrong line.
|
|
85
|
+
* @param delRows - the run's del rows (index + text).
|
|
86
|
+
* @param addRows - the run's add rows (index + text).
|
|
87
|
+
* @param alignBySimilarity - whether to use the similarity-based matching.
|
|
88
|
+
* @returns the aligned pairs and the unmatched sides.
|
|
89
|
+
*/
|
|
90
|
+
export declare function alignChangedBlock(delRows: readonly {
|
|
91
|
+
index: number;
|
|
92
|
+
text: string;
|
|
93
|
+
}[], addRows: readonly {
|
|
94
|
+
index: number;
|
|
95
|
+
text: string;
|
|
96
|
+
}[], alignBySimilarity: boolean): BlockAlignment;
|
|
97
|
+
/**
|
|
98
|
+
* Derive intra-line runs for a whole-file row list. Each del/add block is
|
|
99
|
+
* aligned (by order, or by similarity when `alignBySimilarity`), and each
|
|
100
|
+
* matched pair is compared by `intraRunsOf`. Returns a map keyed by the row's
|
|
101
|
+
* index in `rows`, present only for rows that carry a highlight.
|
|
102
|
+
* @param rows - the unified `WholeFileDiff` row list.
|
|
103
|
+
* @param alignBySimilarity - align blocks by similarity instead of by order.
|
|
104
|
+
* @returns per-row-index intra-line runs for annotated del/add rows.
|
|
105
|
+
*/
|
|
106
|
+
export declare function computeIntraLineDiff(rows: readonly WholeFileDiffRow[], alignBySimilarity?: boolean): Map<number, IntraRun[]>;
|
|
107
|
+
export {};
|
package/package.json
CHANGED