@chances-ai/tui 13.0.0 → 15.0.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/dist/api-key-prompt.d.ts +8 -15
- package/dist/api-key-prompt.d.ts.map +1 -1
- package/dist/api-key-prompt.js +21 -31
- package/dist/api-key-prompt.js.map +1 -1
- package/dist/app.d.ts +15 -21
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +180 -151
- package/dist/app.js.map +1 -1
- package/dist/code-view.d.ts +9 -0
- package/dist/code-view.d.ts.map +1 -0
- package/dist/code-view.js +28 -0
- package/dist/code-view.js.map +1 -0
- package/dist/diff-model.d.ts +64 -0
- package/dist/diff-model.d.ts.map +1 -0
- package/dist/diff-model.js +156 -0
- package/dist/diff-model.js.map +1 -0
- package/dist/diff-view.d.ts +13 -0
- package/dist/diff-view.d.ts.map +1 -0
- package/dist/diff-view.js +60 -0
- package/dist/diff-view.js.map +1 -0
- package/dist/highlight-to-segments.d.ts +18 -0
- package/dist/highlight-to-segments.d.ts.map +1 -0
- package/dist/highlight-to-segments.js +224 -0
- package/dist/highlight-to-segments.js.map +1 -0
- package/dist/index.d.ts +15 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -2
- package/dist/index.js.map +1 -1
- package/dist/markdown.d.ts +5 -0
- package/dist/markdown.d.ts.map +1 -0
- package/dist/markdown.js +117 -0
- package/dist/markdown.js.map +1 -0
- package/dist/modal.d.ts +3 -2
- package/dist/modal.d.ts.map +1 -1
- package/dist/modal.js +3 -2
- package/dist/modal.js.map +1 -1
- package/dist/model-picker.d.ts +7 -39
- package/dist/model-picker.d.ts.map +1 -1
- package/dist/model-picker.js +14 -65
- package/dist/model-picker.js.map +1 -1
- package/dist/progress.d.ts +41 -0
- package/dist/progress.d.ts.map +1 -0
- package/dist/progress.js +122 -0
- package/dist/progress.js.map +1 -0
- package/dist/select.d.ts +59 -0
- package/dist/select.d.ts.map +1 -0
- package/dist/select.js +114 -0
- package/dist/select.js.map +1 -0
- package/dist/session-picker.d.ts +7 -15
- package/dist/session-picker.d.ts.map +1 -1
- package/dist/session-picker.js +14 -40
- package/dist/session-picker.js.map +1 -1
- package/dist/slash-typeahead.d.ts +34 -0
- package/dist/slash-typeahead.d.ts.map +1 -0
- package/dist/slash-typeahead.js +78 -0
- package/dist/slash-typeahead.js.map +1 -0
- package/dist/theme-context.d.ts +25 -0
- package/dist/theme-context.d.ts.map +1 -0
- package/dist/theme-context.js +24 -0
- package/dist/theme-context.js.map +1 -0
- package/dist/theme.d.ts +106 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +116 -0
- package/dist/theme.js.map +1 -0
- package/dist/tool-line.d.ts +33 -0
- package/dist/tool-line.d.ts.map +1 -0
- package/dist/tool-line.js +168 -0
- package/dist/tool-line.js.map +1 -0
- package/dist/tool-message.d.ts +18 -0
- package/dist/tool-message.d.ts.map +1 -0
- package/dist/tool-message.js +37 -0
- package/dist/tool-message.js.map +1 -0
- package/dist/view-model.d.ts +46 -1
- package/dist/view-model.d.ts.map +1 -1
- package/dist/view-model.js +109 -16
- package/dist/view-model.js.map +1 -1
- package/package.json +9 -4
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { JSX } from "react";
|
|
2
|
+
export interface CodeViewProps {
|
|
3
|
+
code: string;
|
|
4
|
+
lang?: string;
|
|
5
|
+
/** Left indent (columns). Default 2 (the claude-code code gutter). */
|
|
6
|
+
indent?: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function CodeView({ code, lang, indent }: CodeViewProps): JSX.Element;
|
|
9
|
+
//# sourceMappingURL=code-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-view.d.ts","sourceRoot":"","sources":["../src/code-view.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAIjC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAU,EAAE,EAAE,aAAa,GAAG,GAAG,CAAC,OAAO,CAkC/E"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* (5.9 / v14) Fenced code block: indented, no border/background (claude-code
|
|
4
|
+
* does not box code). Syntax-highlit per `config.tui.syntaxHighlight` via the
|
|
5
|
+
* pure `highlightToSegments`; unknown language / disabled / `NO_COLOR` →
|
|
6
|
+
* plain. The highlighter never throws (it self-degrades to a plain segment).
|
|
7
|
+
*/
|
|
8
|
+
import { Box, Text } from "ink";
|
|
9
|
+
import { highlightToSegments, SCOPE_TO_THEME } from "./highlight-to-segments.js";
|
|
10
|
+
import { useTheme } from "./theme-context.js";
|
|
11
|
+
export function CodeView({ code, lang, indent = 2 }) {
|
|
12
|
+
const { theme, syntaxHighlight } = useTheme();
|
|
13
|
+
// Trailing newline would render an extra blank line; drop exactly one.
|
|
14
|
+
const body = code.endsWith("\n") ? code.slice(0, -1) : code;
|
|
15
|
+
const lines = body.split("\n");
|
|
16
|
+
return (_jsx(Box, { flexDirection: "column", paddingLeft: indent, children: lines.map((line, i) => {
|
|
17
|
+
if (!syntaxHighlight) {
|
|
18
|
+
return (_jsx(Text, { dimColor: true, children: line === "" ? " " : line }, i));
|
|
19
|
+
}
|
|
20
|
+
const segs = highlightToSegments(line, lang);
|
|
21
|
+
return (_jsxs(Text, { children: [line === "" ? " " : null, segs.map((seg, j) => {
|
|
22
|
+
const role = SCOPE_TO_THEME[seg.scope];
|
|
23
|
+
const color = role ? theme[role] : undefined;
|
|
24
|
+
return (_jsx(Text, { color: color, children: seg.text }, j));
|
|
25
|
+
})] }, i));
|
|
26
|
+
}) }));
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=code-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-view.js","sourceRoot":"","sources":["../src/code-view.tsx"],"names":[],"mappings":";AAAA;;;;;GAKG;AACH,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAS9C,MAAM,UAAU,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,EAAiB;IAChE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC9C,uEAAuE;IACvE,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE/B,OAAO,CACL,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,WAAW,EAAE,MAAM,YAC5C,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;YACrB,IAAI,CAAC,eAAe,EAAE,CAAC;gBACrB,OAAO,CACL,KAAC,IAAI,IAAS,QAAQ,kBACnB,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IADhB,CAAC,CAEL,CACR,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,GAAG,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC7C,OAAO,CACL,MAAC,IAAI,eACF,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EACxB,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;wBACnB,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;wBACvC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;wBAC7C,OAAO,CACL,KAAC,IAAI,IAAS,KAAK,EAAE,KAAK,YACvB,GAAG,CAAC,IAAI,IADA,CAAC,CAEL,CACR,CAAC;oBACJ,CAAC,CAAC,KAVO,CAAC,CAWL,CACR,CAAC;QACJ,CAAC,CAAC,GACE,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* (5.9 / v14) Pure parser that turns the `linesDiff` text block (carried in a
|
|
3
|
+
* write/edit `tool:permission` summary — see `view-model.ts`) into structured,
|
|
4
|
+
* renderable rows. NO React/Ink here — this is the correctness core, fully
|
|
5
|
+
* unit-tested in isolation.
|
|
6
|
+
*
|
|
7
|
+
* `linesDiff` (`packages/tools/src/diff.ts`) emits, in order:
|
|
8
|
+
* `@@ -start,rem +start,add @@`
|
|
9
|
+
* `- <removed line>` × rem
|
|
10
|
+
* `+ <added line>` × add
|
|
11
|
+
* — i.e. ALL removes then ALL adds, NO context lines; with a `… (N lines
|
|
12
|
+
* elided)` marker injected in the middle when the block exceeds its 14-body-row
|
|
13
|
+
* cap (so a full block is up to 15 lines incl. the header — codex R1 SHOULD-5).
|
|
14
|
+
*
|
|
15
|
+
* Line numbers (codex R1 MUST-1): `write` diffs are whole-file-anchored
|
|
16
|
+
* (`linesDiff(before, content)`), so `@@ -start` is the real file line — render
|
|
17
|
+
* the gutter. `edit` diffs are `find`↔`replace` snippets, so `@@ -1` is
|
|
18
|
+
* snippet-relative — the caller passes `anchored: false` and no gutter is shown.
|
|
19
|
+
*/
|
|
20
|
+
/** Threshold above which a remove/add pair renders as whole-line (not word-level).
|
|
21
|
+
* Matches claude-code `StructuredDiff/Fallback.tsx` `CHANGE_THRESHOLD`. */
|
|
22
|
+
export declare const CHANGE_THRESHOLD = 0.4;
|
|
23
|
+
export interface WordSeg {
|
|
24
|
+
text: string;
|
|
25
|
+
/** True ⇒ this word was added (on an add row) or removed (on a remove row). */
|
|
26
|
+
changed: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface DiffRow {
|
|
29
|
+
kind: "add" | "remove" | "elision";
|
|
30
|
+
/** Code content with the `+`/`-`/space sigil stripped (the raw elision text
|
|
31
|
+
* for `kind:"elision"`). */
|
|
32
|
+
text: string;
|
|
33
|
+
/** Assigned line number, or null when unanchored (edit) or an elision row. */
|
|
34
|
+
lineNo: number | null;
|
|
35
|
+
/** Word-level segments when this row is part of a sub-threshold pair; null ⇒
|
|
36
|
+
* render the whole line with the line background. */
|
|
37
|
+
words: WordSeg[] | null;
|
|
38
|
+
}
|
|
39
|
+
export interface ParsedDiff {
|
|
40
|
+
rows: DiffRow[];
|
|
41
|
+
/** The hunk's old start line (1-based) parsed from the `@@` header, or null. */
|
|
42
|
+
startLine: number | null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Detect whether a text block is a renderable diff (the non-diff guard, 5.9 §3):
|
|
46
|
+
* true only when it contains a `@@ -d +d @@` hunk header.
|
|
47
|
+
*/
|
|
48
|
+
export declare function looksLikeDiff(text: string): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Parse a `linesDiff` block. `anchored` (write=true, edit=false) controls
|
|
51
|
+
* whether line numbers are assigned. Returns rows in source order with
|
|
52
|
+
* word-level segments computed for sub-threshold remove/add pairs.
|
|
53
|
+
*/
|
|
54
|
+
export declare function parseDiff(text: string, opts: {
|
|
55
|
+
anchored: boolean;
|
|
56
|
+
}): ParsedDiff;
|
|
57
|
+
/**
|
|
58
|
+
* Word-level segments for one side of a pair. `side:"remove"` keeps common +
|
|
59
|
+
* removed words; `side:"add"` keeps common + added words. Returns null when the
|
|
60
|
+
* pair changed more than {@link CHANGE_THRESHOLD} of its total length (render
|
|
61
|
+
* whole-line instead).
|
|
62
|
+
*/
|
|
63
|
+
export declare function wordSegs(removeText: string, addText: string, side: "add" | "remove"): WordSeg[] | null;
|
|
64
|
+
//# sourceMappingURL=diff-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-model.d.ts","sourceRoot":"","sources":["../src/diff-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH;4EAC4E;AAC5E,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;IACnC;iCAC6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;0DACsD;IACtD,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,gFAAgF;IAChF,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAQD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAOD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,GAAG,UAAU,CAuB/E;AAqED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,OAAO,EAAE,GAAG,IAAI,CAiBtG"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* (5.9 / v14) Pure parser that turns the `linesDiff` text block (carried in a
|
|
3
|
+
* write/edit `tool:permission` summary — see `view-model.ts`) into structured,
|
|
4
|
+
* renderable rows. NO React/Ink here — this is the correctness core, fully
|
|
5
|
+
* unit-tested in isolation.
|
|
6
|
+
*
|
|
7
|
+
* `linesDiff` (`packages/tools/src/diff.ts`) emits, in order:
|
|
8
|
+
* `@@ -start,rem +start,add @@`
|
|
9
|
+
* `- <removed line>` × rem
|
|
10
|
+
* `+ <added line>` × add
|
|
11
|
+
* — i.e. ALL removes then ALL adds, NO context lines; with a `… (N lines
|
|
12
|
+
* elided)` marker injected in the middle when the block exceeds its 14-body-row
|
|
13
|
+
* cap (so a full block is up to 15 lines incl. the header — codex R1 SHOULD-5).
|
|
14
|
+
*
|
|
15
|
+
* Line numbers (codex R1 MUST-1): `write` diffs are whole-file-anchored
|
|
16
|
+
* (`linesDiff(before, content)`), so `@@ -start` is the real file line — render
|
|
17
|
+
* the gutter. `edit` diffs are `find`↔`replace` snippets, so `@@ -1` is
|
|
18
|
+
* snippet-relative — the caller passes `anchored: false` and no gutter is shown.
|
|
19
|
+
*/
|
|
20
|
+
import { diffWordsWithSpace } from "diff";
|
|
21
|
+
/** Threshold above which a remove/add pair renders as whole-line (not word-level).
|
|
22
|
+
* Matches claude-code `StructuredDiff/Fallback.tsx` `CHANGE_THRESHOLD`. */
|
|
23
|
+
export const CHANGE_THRESHOLD = 0.4;
|
|
24
|
+
const HUNK_RE = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
|
|
25
|
+
// Anchored + exact: `linesDiff` emits the marker as `… (N lines elided)`. A
|
|
26
|
+
// loose `lines elided)` alternative (codex R2 SHOULD-4) would misclassify a
|
|
27
|
+
// real source line that merely contains that phrase.
|
|
28
|
+
const ELISION_RE = /^… \(\d+ lines elided\)$/;
|
|
29
|
+
/**
|
|
30
|
+
* Detect whether a text block is a renderable diff (the non-diff guard, 5.9 §3):
|
|
31
|
+
* true only when it contains a `@@ -d +d @@` hunk header.
|
|
32
|
+
*/
|
|
33
|
+
export function looksLikeDiff(text) {
|
|
34
|
+
return text.split("\n").some((l) => HUNK_RE.test(l));
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Parse a `linesDiff` block. `anchored` (write=true, edit=false) controls
|
|
38
|
+
* whether line numbers are assigned. Returns rows in source order with
|
|
39
|
+
* word-level segments computed for sub-threshold remove/add pairs.
|
|
40
|
+
*/
|
|
41
|
+
export function parseDiff(text, opts) {
|
|
42
|
+
const lines = text.split("\n");
|
|
43
|
+
let startLine = null;
|
|
44
|
+
const raw = [];
|
|
45
|
+
for (const line of lines) {
|
|
46
|
+
const hunk = HUNK_RE.exec(line);
|
|
47
|
+
if (hunk) {
|
|
48
|
+
if (startLine === null)
|
|
49
|
+
startLine = Number(hunk[1]);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (ELISION_RE.test(line)) {
|
|
53
|
+
raw.push({ kind: "elision", text: line });
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (line.startsWith("- "))
|
|
57
|
+
raw.push({ kind: "remove", text: line.slice(2) });
|
|
58
|
+
else if (line.startsWith("+ "))
|
|
59
|
+
raw.push({ kind: "add", text: line.slice(2) });
|
|
60
|
+
else if (line === "-" || line === "+")
|
|
61
|
+
raw.push({ kind: line === "+" ? "add" : "remove", text: "" });
|
|
62
|
+
// Anything else (stray context / blank) is ignored: linesDiff never emits it.
|
|
63
|
+
}
|
|
64
|
+
const rows = numberAndPair(raw, startLine ?? 1, opts.anchored);
|
|
65
|
+
return { rows, startLine };
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Assign line numbers (anchored only) and compute word-level pairing. Mirrors
|
|
69
|
+
* claude-code's `numberDiffLines` + `processAdjacentLines`: a run of removes
|
|
70
|
+
* followed by a run of adds pairs index-wise; the line counter rewinds by the
|
|
71
|
+
* number of removes so the matching add reuses the same displayed number.
|
|
72
|
+
*/
|
|
73
|
+
function numberAndPair(raw, startLine, anchored) {
|
|
74
|
+
const out = [];
|
|
75
|
+
let i = 0;
|
|
76
|
+
let lineNo = startLine;
|
|
77
|
+
while (i < raw.length) {
|
|
78
|
+
const cur = raw[i];
|
|
79
|
+
if (cur.kind === "elision") {
|
|
80
|
+
out.push({ kind: "elision", text: cur.text, lineNo: null, words: null });
|
|
81
|
+
i++;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (cur.kind === "remove") {
|
|
85
|
+
// Collect the remove run, then the following add run.
|
|
86
|
+
const removes = [];
|
|
87
|
+
while (i < raw.length && raw[i].kind === "remove")
|
|
88
|
+
removes.push(raw[i++]);
|
|
89
|
+
const adds = [];
|
|
90
|
+
while (i < raw.length && raw[i].kind === "add")
|
|
91
|
+
adds.push(raw[i++]);
|
|
92
|
+
const removeBase = lineNo;
|
|
93
|
+
removes.forEach((r, k) => {
|
|
94
|
+
const paired = adds[k];
|
|
95
|
+
out.push({
|
|
96
|
+
kind: "remove",
|
|
97
|
+
text: r.text,
|
|
98
|
+
lineNo: anchored ? removeBase + k : null,
|
|
99
|
+
words: paired ? wordSegs(r.text, paired.text, "remove") : null,
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
// Rewind: removed lines don't exist in the new file — adds reuse the numbers.
|
|
103
|
+
adds.forEach((a, k) => {
|
|
104
|
+
const paired = removes[k];
|
|
105
|
+
out.push({
|
|
106
|
+
kind: "add",
|
|
107
|
+
text: a.text,
|
|
108
|
+
lineNo: anchored ? removeBase + k : null,
|
|
109
|
+
// wordSegs always takes (removeText, addText); here the add's pair is
|
|
110
|
+
// the remove at the same index.
|
|
111
|
+
words: paired ? wordSegs(paired.text, a.text, "add") : null,
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
lineNo = removeBase + Math.max(removes.length, adds.length);
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
// A lone add run (pure insertion, no preceding removes).
|
|
118
|
+
if (cur.kind === "add") {
|
|
119
|
+
while (i < raw.length && raw[i].kind === "add") {
|
|
120
|
+
const a = raw[i++];
|
|
121
|
+
out.push({ kind: "add", text: a.text, lineNo: anchored ? lineNo++ : null, words: null });
|
|
122
|
+
}
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
i++;
|
|
126
|
+
}
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Word-level segments for one side of a pair. `side:"remove"` keeps common +
|
|
131
|
+
* removed words; `side:"add"` keeps common + added words. Returns null when the
|
|
132
|
+
* pair changed more than {@link CHANGE_THRESHOLD} of its total length (render
|
|
133
|
+
* whole-line instead).
|
|
134
|
+
*/
|
|
135
|
+
export function wordSegs(removeText, addText, side) {
|
|
136
|
+
const parts = diffWordsWithSpace(removeText, addText);
|
|
137
|
+
const total = removeText.length + addText.length;
|
|
138
|
+
const changedLen = parts.reduce((sum, p) => (p.added || p.removed ? sum + p.value.length : sum), 0);
|
|
139
|
+
if (total === 0 || changedLen / total > CHANGE_THRESHOLD)
|
|
140
|
+
return null;
|
|
141
|
+
const segs = [];
|
|
142
|
+
for (const p of parts) {
|
|
143
|
+
if (side === "remove") {
|
|
144
|
+
if (p.added)
|
|
145
|
+
continue;
|
|
146
|
+
segs.push({ text: p.value, changed: !!p.removed });
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
if (p.removed)
|
|
150
|
+
continue;
|
|
151
|
+
segs.push({ text: p.value, changed: !!p.added });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return segs;
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=diff-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-model.js","sourceRoot":"","sources":["../src/diff-model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { JSX } from "react";
|
|
2
|
+
export interface DiffViewProps {
|
|
3
|
+
/** The raw `linesDiff` text (from the stashed `tool:permission` summary). */
|
|
4
|
+
diff: string;
|
|
5
|
+
/** True for `write` (whole-file-anchored line numbers); false for `edit`
|
|
6
|
+
* (snippet-relative — no gutter, codex R1 MUST-1). */
|
|
7
|
+
anchored: boolean;
|
|
8
|
+
/** Render width for full-line background padding. Defaults to the terminal
|
|
9
|
+
* columns (or 80). */
|
|
10
|
+
width?: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function DiffView({ diff, anchored, width }: DiffViewProps): JSX.Element;
|
|
13
|
+
//# sourceMappingURL=diff-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-view.d.ts","sourceRoot":"","sources":["../src/diff-view.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAKjC,MAAM,WAAW,aAAa;IAC5B,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,EAAE,OAAO,CAAC;IAClB;2BACuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAOD,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,aAAa,GAAG,GAAG,CAAC,OAAO,CAgB9E"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* (5.9 / v14) Render a `linesDiff` block as claude-code's structured diff:
|
|
4
|
+
* per-row `<lineNo> <sigil> <code>` with a full-line background, word-level
|
|
5
|
+
* emphasis on sub-threshold pairs. Pure parsing lives in `diff-model.ts`; this
|
|
6
|
+
* file is the Ink view only.
|
|
7
|
+
*
|
|
8
|
+
* Notes:
|
|
9
|
+
* - `linesDiff` emits no context lines, so every row is add/remove — there is
|
|
10
|
+
* no context-line syntax highlighting to do here (a lever if context is ever
|
|
11
|
+
* added). Readability comes from the +/- background + word emphasis.
|
|
12
|
+
* - Each text run carries an EXPLICIT backgroundColor (word-bg for changed
|
|
13
|
+
* words, else the line-bg) so Ink leaves no un-painted gaps between runs.
|
|
14
|
+
* - Under `NO_COLOR` every theme bg is undefined ⇒ no background; the `+`/`-`
|
|
15
|
+
* sigils alone carry the add/remove meaning.
|
|
16
|
+
*/
|
|
17
|
+
import { Box, Text } from "ink";
|
|
18
|
+
import stringWidth from "string-width";
|
|
19
|
+
import { parseDiff } from "./diff-model.js";
|
|
20
|
+
import { useTheme } from "./theme-context.js";
|
|
21
|
+
function defaultWidth() {
|
|
22
|
+
const cols = process.stdout?.columns;
|
|
23
|
+
return typeof cols === "number" && cols > 0 ? cols : 80;
|
|
24
|
+
}
|
|
25
|
+
export function DiffView({ diff, anchored, width }) {
|
|
26
|
+
const { theme } = useTheme();
|
|
27
|
+
const { rows } = parseDiff(diff, { anchored });
|
|
28
|
+
const totalWidth = width ?? defaultWidth();
|
|
29
|
+
const gutterWidth = anchored
|
|
30
|
+
? Math.max(0, ...rows.map((r) => (r.lineNo === null ? 0 : String(r.lineNo).length)))
|
|
31
|
+
: 0;
|
|
32
|
+
return (_jsx(Box, { flexDirection: "column", children: rows.map((row, i) => (_jsx(DiffLine, { row: row, gutterWidth: gutterWidth, width: totalWidth, theme: theme }, i))) }));
|
|
33
|
+
}
|
|
34
|
+
function DiffLine({ row, gutterWidth, width, theme, }) {
|
|
35
|
+
if (row.kind === "elision") {
|
|
36
|
+
return (_jsxs(Text, { dimColor: true, children: [" ", row.text] }));
|
|
37
|
+
}
|
|
38
|
+
const isAdd = row.kind === "add";
|
|
39
|
+
const lineBg = isAdd ? theme.diffAddedBg : theme.diffRemovedBg;
|
|
40
|
+
const wordBg = isAdd ? theme.diffAddedWordBg : theme.diffRemovedWordBg;
|
|
41
|
+
const sigil = isAdd ? "+" : "-";
|
|
42
|
+
const gutter = gutterWidth > 0 ? `${row.lineNo === null ? "" : String(row.lineNo)}`.padStart(gutterWidth) : "";
|
|
43
|
+
const prefix = gutterWidth > 0 ? `${gutter} ${sigil} ` : `${sigil} `;
|
|
44
|
+
// Build the content runs (word-level or whole-line), each with explicit bg.
|
|
45
|
+
const runs = [];
|
|
46
|
+
let consumed = stringWidth(prefix);
|
|
47
|
+
if (row.words) {
|
|
48
|
+
row.words.forEach((w, i) => {
|
|
49
|
+
runs.push(_jsx(Text, { backgroundColor: w.changed ? wordBg : lineBg, children: w.text }, i));
|
|
50
|
+
consumed += stringWidth(w.text);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
runs.push(_jsx(Text, { backgroundColor: lineBg, children: row.text }, "c"));
|
|
55
|
+
consumed += stringWidth(row.text);
|
|
56
|
+
}
|
|
57
|
+
const pad = Math.max(0, width - consumed);
|
|
58
|
+
return (_jsxs(Text, { backgroundColor: lineBg, children: [_jsx(Text, { dimColor: true, children: prefix }), runs, pad > 0 ? " ".repeat(pad) : ""] }));
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=diff-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-view.js","sourceRoot":"","sources":["../src/diff-view.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Theme } from "./theme.js";
|
|
2
|
+
/** Stable highlight scopes we color. Everything else → `"plain"` (no color). */
|
|
3
|
+
export type HlScope = "plain" | "keyword" | "string" | "comment" | "number" | "function" | "type" | "literal" | "attr";
|
|
4
|
+
export interface Segment {
|
|
5
|
+
text: string;
|
|
6
|
+
scope: HlScope;
|
|
7
|
+
}
|
|
8
|
+
/** scope → theme color role (used by views to pick the `<Text color>`). */
|
|
9
|
+
export declare const SCOPE_TO_THEME: Record<HlScope, keyof Theme | undefined>;
|
|
10
|
+
/** Resolve a user-supplied language label to a registered grammar, or null. */
|
|
11
|
+
export declare function resolveLanguage(lang: string | undefined): string | null;
|
|
12
|
+
/**
|
|
13
|
+
* Highlight `code` as `lang` into themed segments. Unknown/absent language or
|
|
14
|
+
* any highlighter error → a single `"plain"` segment with the original code
|
|
15
|
+
* (callers render it as plain text).
|
|
16
|
+
*/
|
|
17
|
+
export declare function highlightToSegments(code: string, lang: string | undefined): Segment[];
|
|
18
|
+
//# sourceMappingURL=highlight-to-segments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"highlight-to-segments.d.ts","sourceRoot":"","sources":["../src/highlight-to-segments.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AA4ExC,gFAAgF;AAChF,MAAM,MAAM,OAAO,GACf,OAAO,GACP,SAAS,GACT,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,UAAU,GACV,MAAM,GACN,SAAS,GACT,MAAM,CAAC;AAEX,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB;AA6CD,2EAA2E;AAC3E,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,KAAK,GAAG,SAAS,CAUnE,CAAC;AAgBF,+EAA+E;AAC/E,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAMvE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,EAAE,CAWrF"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* (5.9 / v14) Terminal syntax highlighting, pi-style: drive highlight.js
|
|
3
|
+
* directly (NOT `cli-highlight`, which drags in `parse5` + `yargs` — codex R1
|
|
4
|
+
* UNVERIFIABLE-2), then map its `<span class="hljs-…">` HTML to flat, themed
|
|
5
|
+
* segments with a tiny stack scanner. Pure `(code, lang) → Segment[]`, so it is
|
|
6
|
+
* fully unit-testable without Ink and degrades to a single plain segment on
|
|
7
|
+
* unknown language / highlighter throw.
|
|
8
|
+
*
|
|
9
|
+
* Only a curated language set is registered (via `highlight.js/lib/core`) to
|
|
10
|
+
* keep the `bun build --compile` binary small.
|
|
11
|
+
*/
|
|
12
|
+
import hljs from "highlight.js/lib/core";
|
|
13
|
+
// -- curated language registration ------------------------------------------
|
|
14
|
+
import bash from "highlight.js/lib/languages/bash";
|
|
15
|
+
import c from "highlight.js/lib/languages/c";
|
|
16
|
+
import cpp from "highlight.js/lib/languages/cpp";
|
|
17
|
+
import css from "highlight.js/lib/languages/css";
|
|
18
|
+
import diff from "highlight.js/lib/languages/diff";
|
|
19
|
+
import dockerfile from "highlight.js/lib/languages/dockerfile";
|
|
20
|
+
import go from "highlight.js/lib/languages/go";
|
|
21
|
+
import java from "highlight.js/lib/languages/java";
|
|
22
|
+
import javascript from "highlight.js/lib/languages/javascript";
|
|
23
|
+
import json from "highlight.js/lib/languages/json";
|
|
24
|
+
import markdown from "highlight.js/lib/languages/markdown";
|
|
25
|
+
import python from "highlight.js/lib/languages/python";
|
|
26
|
+
import ruby from "highlight.js/lib/languages/ruby";
|
|
27
|
+
import rust from "highlight.js/lib/languages/rust";
|
|
28
|
+
import sql from "highlight.js/lib/languages/sql";
|
|
29
|
+
import toml from "highlight.js/lib/languages/ini";
|
|
30
|
+
import typescript from "highlight.js/lib/languages/typescript";
|
|
31
|
+
import xml from "highlight.js/lib/languages/xml";
|
|
32
|
+
import yaml from "highlight.js/lib/languages/yaml";
|
|
33
|
+
let registered = false;
|
|
34
|
+
function ensureRegistered() {
|
|
35
|
+
if (registered)
|
|
36
|
+
return;
|
|
37
|
+
registered = true;
|
|
38
|
+
const langs = {
|
|
39
|
+
bash,
|
|
40
|
+
c,
|
|
41
|
+
cpp,
|
|
42
|
+
css,
|
|
43
|
+
diff,
|
|
44
|
+
dockerfile,
|
|
45
|
+
go,
|
|
46
|
+
java,
|
|
47
|
+
javascript,
|
|
48
|
+
json,
|
|
49
|
+
markdown,
|
|
50
|
+
python,
|
|
51
|
+
ruby,
|
|
52
|
+
rust,
|
|
53
|
+
sql,
|
|
54
|
+
toml,
|
|
55
|
+
typescript,
|
|
56
|
+
xml,
|
|
57
|
+
yaml,
|
|
58
|
+
};
|
|
59
|
+
for (const [name, def] of Object.entries(langs))
|
|
60
|
+
hljs.registerLanguage(name, def);
|
|
61
|
+
}
|
|
62
|
+
/** Common aliases highlight.js's curated set doesn't auto-register for us. */
|
|
63
|
+
const ALIASES = {
|
|
64
|
+
ts: "typescript",
|
|
65
|
+
tsx: "typescript",
|
|
66
|
+
js: "javascript",
|
|
67
|
+
jsx: "javascript",
|
|
68
|
+
mjs: "javascript",
|
|
69
|
+
cjs: "javascript",
|
|
70
|
+
py: "python",
|
|
71
|
+
rb: "ruby",
|
|
72
|
+
rs: "rust",
|
|
73
|
+
sh: "bash",
|
|
74
|
+
shell: "bash",
|
|
75
|
+
zsh: "bash",
|
|
76
|
+
yml: "yaml",
|
|
77
|
+
html: "xml",
|
|
78
|
+
htm: "xml",
|
|
79
|
+
svg: "xml",
|
|
80
|
+
golang: "go",
|
|
81
|
+
"c++": "cpp",
|
|
82
|
+
ini: "toml",
|
|
83
|
+
dockerfile: "dockerfile",
|
|
84
|
+
md: "markdown",
|
|
85
|
+
};
|
|
86
|
+
/** hljs class (without the `hljs-` prefix) → our scope. Unmapped → "plain". */
|
|
87
|
+
function classToScope(cls) {
|
|
88
|
+
// A span class may be multi-token, e.g. "hljs-title function_"; check each.
|
|
89
|
+
const tokens = cls.split(/\s+/);
|
|
90
|
+
for (const raw of tokens) {
|
|
91
|
+
const t = raw.replace(/^hljs-/, "");
|
|
92
|
+
switch (t) {
|
|
93
|
+
case "keyword":
|
|
94
|
+
return "keyword";
|
|
95
|
+
case "string":
|
|
96
|
+
case "regexp":
|
|
97
|
+
case "char":
|
|
98
|
+
case "char.escape":
|
|
99
|
+
case "subst":
|
|
100
|
+
return "string";
|
|
101
|
+
case "comment":
|
|
102
|
+
case "quote":
|
|
103
|
+
return "comment";
|
|
104
|
+
case "number":
|
|
105
|
+
return "number";
|
|
106
|
+
case "title":
|
|
107
|
+
case "built_in":
|
|
108
|
+
return "function";
|
|
109
|
+
case "type":
|
|
110
|
+
case "class":
|
|
111
|
+
case "title.class":
|
|
112
|
+
return "type";
|
|
113
|
+
case "literal":
|
|
114
|
+
return "literal";
|
|
115
|
+
case "attr":
|
|
116
|
+
case "attribute":
|
|
117
|
+
case "property":
|
|
118
|
+
case "selector-tag":
|
|
119
|
+
case "selector-class":
|
|
120
|
+
case "name":
|
|
121
|
+
return "attr";
|
|
122
|
+
default:
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return "plain";
|
|
127
|
+
}
|
|
128
|
+
/** scope → theme color role (used by views to pick the `<Text color>`). */
|
|
129
|
+
export const SCOPE_TO_THEME = {
|
|
130
|
+
plain: undefined,
|
|
131
|
+
keyword: "synKeyword",
|
|
132
|
+
string: "synString",
|
|
133
|
+
comment: "synComment",
|
|
134
|
+
number: "synNumber",
|
|
135
|
+
function: "synFunction",
|
|
136
|
+
type: "synType",
|
|
137
|
+
literal: "synLiteral",
|
|
138
|
+
attr: "synAttr",
|
|
139
|
+
};
|
|
140
|
+
const ENTITIES = {
|
|
141
|
+
"&": "&",
|
|
142
|
+
"<": "<",
|
|
143
|
+
">": ">",
|
|
144
|
+
""": '"',
|
|
145
|
+
"'": "'",
|
|
146
|
+
"'": "'",
|
|
147
|
+
"'": "'",
|
|
148
|
+
};
|
|
149
|
+
function decodeEntities(s) {
|
|
150
|
+
return s.replace(/&(?:amp|lt|gt|quot|apos|#x27|#39);/g, (m) => ENTITIES[m] ?? m);
|
|
151
|
+
}
|
|
152
|
+
/** Resolve a user-supplied language label to a registered grammar, or null. */
|
|
153
|
+
export function resolveLanguage(lang) {
|
|
154
|
+
if (!lang)
|
|
155
|
+
return null;
|
|
156
|
+
ensureRegistered();
|
|
157
|
+
const norm = lang.trim().toLowerCase();
|
|
158
|
+
const aliased = ALIASES[norm] ?? norm;
|
|
159
|
+
return hljs.getLanguage(aliased) ? aliased : null;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Highlight `code` as `lang` into themed segments. Unknown/absent language or
|
|
163
|
+
* any highlighter error → a single `"plain"` segment with the original code
|
|
164
|
+
* (callers render it as plain text).
|
|
165
|
+
*/
|
|
166
|
+
export function highlightToSegments(code, lang) {
|
|
167
|
+
const resolved = resolveLanguage(lang);
|
|
168
|
+
if (!resolved)
|
|
169
|
+
return [{ text: code, scope: "plain" }];
|
|
170
|
+
let html;
|
|
171
|
+
try {
|
|
172
|
+
html = hljs.highlight(code, { language: resolved, ignoreIllegals: true }).value;
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
return [{ text: code, scope: "plain" }];
|
|
176
|
+
}
|
|
177
|
+
return scanHtml(html);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Flatten highlight.js HTML into segments. Maintains a scope stack; the
|
|
181
|
+
* innermost open span wins for the text between tags. Closing more spans than
|
|
182
|
+
* are open (defensive) is ignored.
|
|
183
|
+
*/
|
|
184
|
+
function scanHtml(html) {
|
|
185
|
+
const segs = [];
|
|
186
|
+
const stack = [];
|
|
187
|
+
// The final `(<)` alternative captures a stray `<` that starts neither a
|
|
188
|
+
// recognized span open/close — emitted as literal text so no source char is
|
|
189
|
+
// silently dropped if highlight.js ever produces unexpected markup (codex R2
|
|
190
|
+
// SHOULD-5). highlight.js escapes real `<` in source to `<`, so this only
|
|
191
|
+
// fires defensively.
|
|
192
|
+
const re = /<span class="([^"]*)">|<\/span>|([^<]+)|(<)/g;
|
|
193
|
+
const push = (raw) => {
|
|
194
|
+
const text = decodeEntities(raw);
|
|
195
|
+
if (text.length > 0)
|
|
196
|
+
segs.push({ text, scope: stack[stack.length - 1] ?? "plain" });
|
|
197
|
+
};
|
|
198
|
+
let m = re.exec(html);
|
|
199
|
+
while (m !== null) {
|
|
200
|
+
if (m[1] !== undefined)
|
|
201
|
+
stack.push(classToScope(m[1]));
|
|
202
|
+
else if (m[2] !== undefined)
|
|
203
|
+
push(m[2]);
|
|
204
|
+
else if (m[3] !== undefined)
|
|
205
|
+
push(m[3]); // stray "<"
|
|
206
|
+
else
|
|
207
|
+
stack.pop();
|
|
208
|
+
m = re.exec(html);
|
|
209
|
+
}
|
|
210
|
+
return coalesce(segs);
|
|
211
|
+
}
|
|
212
|
+
/** Merge adjacent same-scope segments so the renderer emits fewer `<Text>`. */
|
|
213
|
+
function coalesce(segs) {
|
|
214
|
+
const out = [];
|
|
215
|
+
for (const s of segs) {
|
|
216
|
+
const last = out[out.length - 1];
|
|
217
|
+
if (last && last.scope === s.scope)
|
|
218
|
+
last.text += s.text;
|
|
219
|
+
else
|
|
220
|
+
out.push({ ...s });
|
|
221
|
+
}
|
|
222
|
+
return out;
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=highlight-to-segments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"highlight-to-segments.js","sourceRoot":"","sources":["../src/highlight-to-segments.ts"],"names":[],"mappings":"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"}
|