@tooee/view 0.6.3 → 0.7.1
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/components/diff-file-picker.d.ts +13 -0
- package/dist/components/diff-file-picker.d.ts.map +1 -0
- package/dist/components/diff-file-picker.js +17 -0
- package/dist/components/diff-file-picker.js.map +1 -0
- package/dist/components/subviews/diff-subview.d.ts +15 -0
- package/dist/components/subviews/diff-subview.d.ts.map +1 -0
- package/dist/components/subviews/diff-subview.js +166 -0
- package/dist/components/subviews/diff-subview.js.map +1 -0
- package/dist/components/subviews/index.d.ts +1 -0
- package/dist/components/subviews/index.d.ts.map +1 -1
- package/dist/components/subviews/index.js +1 -0
- package/dist/components/subviews/index.js.map +1 -1
- package/dist/default-provider.d.ts.map +1 -1
- package/dist/default-provider.js +14 -2
- package/dist/default-provider.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +8 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -1
- package/dist/types.js.map +1 -1
- package/dist/view.d.ts.map +1 -1
- package/dist/view.js +9 -2
- package/dist/view.js.map +1 -1
- package/package.json +11 -10
- package/src/components/diff-file-picker.tsx +37 -0
- package/src/components/subviews/diff-subview.tsx +229 -0
- package/src/components/subviews/index.ts +1 -0
- package/src/default-provider.ts +16 -2
- package/src/index.ts +1 -0
- package/src/types.ts +19 -2
- package/src/view.tsx +13 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { HunkDiffFile } from "@tooee/diff";
|
|
3
|
+
export interface DiffFilePickerOverlayProps {
|
|
4
|
+
files: readonly HunkDiffFile[];
|
|
5
|
+
onSelect: (fileIndex: number) => void;
|
|
6
|
+
close: () => void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Fuzzy file picker for a diff. Entries are indexed by position so two files
|
|
10
|
+
* with the same path (a rename pair, say) still resolve to distinct rows.
|
|
11
|
+
*/
|
|
12
|
+
export declare const DiffFilePickerOverlay: ({ files, onSelect, close, }: DiffFilePickerOverlayProps) => ReactNode;
|
|
13
|
+
//# sourceMappingURL=diff-file-picker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-file-picker.d.ts","sourceRoot":"","sources":["../../src/components/diff-file-picker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;IAC/B,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,gCAI/B,0BAA0B,KAAG,SAkB/B,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@opentui/react/jsx-runtime";
|
|
2
|
+
import { CommandPalette } from "@tooee/renderers";
|
|
3
|
+
/**
|
|
4
|
+
* Fuzzy file picker for a diff. Entries are indexed by position so two files
|
|
5
|
+
* with the same path (a rename pair, say) still resolve to distinct rows.
|
|
6
|
+
*/
|
|
7
|
+
export const DiffFilePickerOverlay = function DiffFilePickerOverlay({ files, onSelect, close, }) {
|
|
8
|
+
const entries = files.map((file, index) => ({
|
|
9
|
+
id: String(index),
|
|
10
|
+
title: `${file.previousPath === undefined ? "" : `${file.previousPath} -> `}${file.path ?? file.id} +${file.stats.additions} -${file.stats.deletions}`,
|
|
11
|
+
}));
|
|
12
|
+
return (_jsx(CommandPalette, { commands: entries, onClose: close, onSelect: (id) => {
|
|
13
|
+
onSelect(Number(id));
|
|
14
|
+
close();
|
|
15
|
+
} }));
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=diff-file-picker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-file-picker.js","sourceRoot":"","sources":["../../src/components/diff-file-picker.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AASlD;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,SAAS,qBAAqB,CAAC,EAClE,KAAK,EACL,QAAQ,EACR,KAAK,GACsB;IAC3B,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QAC1C,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC;QACjB,KAAK,EAAE,GAAG,IAAI,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,YAAY,MAAM,GACzE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,EACpB,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;KACtD,CAAC,CAAC,CAAC;IAEJ,OAAO,CACL,KAAC,cAAc,IACb,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,KAAK,EACd,QAAQ,EAAE,CAAC,EAAU,EAAE,EAAE;YACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;YACrB,KAAK,EAAE,CAAC;QACV,CAAC,GACD,CACH,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DiffContent } from "../../types.js";
|
|
2
|
+
import type { SubviewProps } from "./types.js";
|
|
3
|
+
interface DiffSubviewProps extends SubviewProps {
|
|
4
|
+
content: DiffContent;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* The built-in diff viewer: a Hunk-rendered patch inside Tooee's normal chrome.
|
|
8
|
+
*
|
|
9
|
+
* Hunk owns the drawing of each file header and hunk; the row document owns
|
|
10
|
+
* scrolling, the cursor, decorations and mouse routing. The cursor row maps 1:1
|
|
11
|
+
* onto Hunk's `{ fileId, hunkIndex }` selection, so `j`/`k` step hunk by hunk.
|
|
12
|
+
*/
|
|
13
|
+
export declare const DiffSubview: ({ content, decorations, actions, ...screen }: DiffSubviewProps) => React.ReactNode;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=diff-subview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-subview.d.ts","sourceRoot":"","sources":["../../../src/components/subviews/diff-subview.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAIlD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,UAAU,gBAAiB,SAAQ,YAAY;IAC7C,OAAO,EAAE,WAAW,CAAC;CACtB;AAcD;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,iDAKrB,gBAAgB,KAAG,KAAK,CAAC,SAyL3B,CAAC"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@opentui/react/jsx-runtime";
|
|
2
|
+
import { createElement, useCallback, useMemo, useState } from "react";
|
|
3
|
+
import { DiffView, buildDiffModel, diffRowAdapter } from "@tooee/diff";
|
|
4
|
+
import { useCommand } from "@tooee/commands";
|
|
5
|
+
import { useConfig } from "@tooee/config";
|
|
6
|
+
import { useOverlay } from "@tooee/overlays";
|
|
7
|
+
import { useDocumentController } from "@tooee/shell";
|
|
8
|
+
import { useContentCommands } from "../../hooks/use-content-commands.js";
|
|
9
|
+
import { ViewScreen } from "../view-screen.js";
|
|
10
|
+
import { DiffFilePickerOverlay } from "../diff-file-picker.js";
|
|
11
|
+
/** Columns panned per h/l press when a hunk is wider than the viewport. */
|
|
12
|
+
const HSCROLL_STEP = 4;
|
|
13
|
+
const FILE_PICKER_OVERLAY = "diff-file-picker";
|
|
14
|
+
/**
|
|
15
|
+
* Rows are file headers and hunks, so `getText` is the row's patch text and
|
|
16
|
+
* `getSource` its span in the original patch: search, copy and marks all work
|
|
17
|
+
* in real patch coordinates rather than in rendered diff lines.
|
|
18
|
+
*/
|
|
19
|
+
const DIFF_ROW_ADAPTER = diffRowAdapter;
|
|
20
|
+
/**
|
|
21
|
+
* The built-in diff viewer: a Hunk-rendered patch inside Tooee's normal chrome.
|
|
22
|
+
*
|
|
23
|
+
* Hunk owns the drawing of each file header and hunk; the row document owns
|
|
24
|
+
* scrolling, the cursor, decorations and mouse routing. The cursor row maps 1:1
|
|
25
|
+
* onto Hunk's `{ fileId, hunkIndex }` selection, so `j`/`k` step hunk by hunk.
|
|
26
|
+
*/
|
|
27
|
+
export const DiffSubview = function DiffSubview({ content, decorations, actions, ...screen }) {
|
|
28
|
+
const config = useConfig();
|
|
29
|
+
const overlay = useOverlay();
|
|
30
|
+
const textContent = content.patch;
|
|
31
|
+
const model = useMemo(() => buildDiffModel(content.patch), [content.patch]);
|
|
32
|
+
const [layout, setLayout] = useState(content.layout ?? config.view?.diffLayout ?? "stack");
|
|
33
|
+
const [wrapLines, setWrapLines] = useState(config.view?.wrap ?? false);
|
|
34
|
+
const [horizontalOffset, setHorizontalOffset] = useState(0);
|
|
35
|
+
const { showLineNumbers } = useContentCommands({ content, textContent });
|
|
36
|
+
const document = useDocumentController({
|
|
37
|
+
adapter: DIFF_ROW_ADAPTER,
|
|
38
|
+
// The controller projects the screen's actions onto menu entries at open time.
|
|
39
|
+
contextMenu: actions,
|
|
40
|
+
decorations,
|
|
41
|
+
multiSelect: true,
|
|
42
|
+
preserveCursorByKey: true,
|
|
43
|
+
rows: model.rows,
|
|
44
|
+
});
|
|
45
|
+
const { activeIndex } = document;
|
|
46
|
+
// `setCursor` rather than `selectRow`: the latter stands down while a modal
|
|
47
|
+
// overlay is open, which is exactly when the file picker commits its choice.
|
|
48
|
+
const { setCursor } = document.navigation;
|
|
49
|
+
/** Index of the file-header row for `fileIndex`, or `null` when absent. */
|
|
50
|
+
const fileRowIndex = useCallback((fileIndex) => {
|
|
51
|
+
const index = model.rows.findIndex((row) => row.kind === "file" && row.fileIndex === fileIndex);
|
|
52
|
+
return index === -1 ? null : index;
|
|
53
|
+
}, [model.rows]);
|
|
54
|
+
const jumpFile = useCallback((delta) => {
|
|
55
|
+
const current = activeIndex === null ? undefined : model.rows[activeIndex];
|
|
56
|
+
const from = current?.fileIndex ?? 0;
|
|
57
|
+
const target = Math.min(Math.max(from + delta, 0), model.files.length - 1);
|
|
58
|
+
const index = fileRowIndex(target);
|
|
59
|
+
if (index !== null) {
|
|
60
|
+
setCursor(index);
|
|
61
|
+
}
|
|
62
|
+
}, [activeIndex, fileRowIndex, model.files.length, model.rows, setCursor]);
|
|
63
|
+
useCommand({
|
|
64
|
+
handler: () => {
|
|
65
|
+
setLayout((value) => (value === "split" ? "stack" : "split"));
|
|
66
|
+
},
|
|
67
|
+
hotkey: "s",
|
|
68
|
+
id: "diff.toggle-layout",
|
|
69
|
+
modes: ["cursor", "select"],
|
|
70
|
+
title: "Toggle split/unified diff",
|
|
71
|
+
});
|
|
72
|
+
useCommand({
|
|
73
|
+
handler: () => {
|
|
74
|
+
setWrapLines((value) => !value);
|
|
75
|
+
setHorizontalOffset(0);
|
|
76
|
+
},
|
|
77
|
+
hotkey: "w",
|
|
78
|
+
id: "diff.toggle-wrap",
|
|
79
|
+
modes: ["cursor", "select"],
|
|
80
|
+
title: "Toggle diff line wrapping",
|
|
81
|
+
});
|
|
82
|
+
useCommand({
|
|
83
|
+
handler: () => {
|
|
84
|
+
jumpFile(1);
|
|
85
|
+
},
|
|
86
|
+
hotkey: "]",
|
|
87
|
+
id: "diff.next-file",
|
|
88
|
+
modes: ["cursor", "select"],
|
|
89
|
+
title: "Next file",
|
|
90
|
+
});
|
|
91
|
+
useCommand({
|
|
92
|
+
handler: () => {
|
|
93
|
+
jumpFile(-1);
|
|
94
|
+
},
|
|
95
|
+
hotkey: "[",
|
|
96
|
+
id: "diff.prev-file",
|
|
97
|
+
modes: ["cursor", "select"],
|
|
98
|
+
title: "Previous file",
|
|
99
|
+
});
|
|
100
|
+
useCommand({
|
|
101
|
+
handler: () => {
|
|
102
|
+
setHorizontalOffset((value) => Math.max(0, value - HSCROLL_STEP));
|
|
103
|
+
},
|
|
104
|
+
hotkey: "h",
|
|
105
|
+
id: "diff.scroll-left",
|
|
106
|
+
modes: ["cursor"],
|
|
107
|
+
title: "Pan diff left",
|
|
108
|
+
when: () => !wrapLines,
|
|
109
|
+
});
|
|
110
|
+
useCommand({
|
|
111
|
+
handler: () => {
|
|
112
|
+
setHorizontalOffset((value) => value + HSCROLL_STEP);
|
|
113
|
+
},
|
|
114
|
+
hotkey: "l",
|
|
115
|
+
id: "diff.scroll-right",
|
|
116
|
+
modes: ["cursor"],
|
|
117
|
+
title: "Pan diff right",
|
|
118
|
+
when: () => !wrapLines,
|
|
119
|
+
});
|
|
120
|
+
useCommand({
|
|
121
|
+
handler: () => {
|
|
122
|
+
overlay.open(FILE_PICKER_OVERLAY, ({ close }) => createElement(DiffFilePickerOverlay, {
|
|
123
|
+
close: () => {
|
|
124
|
+
close();
|
|
125
|
+
},
|
|
126
|
+
files: model.files,
|
|
127
|
+
onSelect: (fileIndex) => {
|
|
128
|
+
const index = fileRowIndex(fileIndex);
|
|
129
|
+
if (index !== null) {
|
|
130
|
+
setCursor(index);
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
}), null, { ownCommands: true, role: "modal", surfaceMode: "insert" });
|
|
134
|
+
},
|
|
135
|
+
hotkey: "f",
|
|
136
|
+
id: "diff.file-picker",
|
|
137
|
+
modes: ["cursor", "select"],
|
|
138
|
+
title: "Go to file",
|
|
139
|
+
});
|
|
140
|
+
const activeRow = activeIndex === null ? undefined : model.rows[activeIndex];
|
|
141
|
+
const statusItems = useMemo(() => [
|
|
142
|
+
{ label: "Format:", value: content.format },
|
|
143
|
+
{ label: "Files:", value: String(model.files.length) },
|
|
144
|
+
{ label: "Changes:", value: `+${model.stats.additions} -${model.stats.deletions}` },
|
|
145
|
+
{ label: "Layout:", value: layout },
|
|
146
|
+
...(activeRow
|
|
147
|
+
? [
|
|
148
|
+
{
|
|
149
|
+
label: "At:",
|
|
150
|
+
value: activeRow.hunkIndex >= 0
|
|
151
|
+
? `${activeRow.parent.path ?? activeRow.fileId}:${activeRow.hunkIndex + 1}`
|
|
152
|
+
: (activeRow.parent.path ?? activeRow.fileId),
|
|
153
|
+
},
|
|
154
|
+
]
|
|
155
|
+
: []),
|
|
156
|
+
], [
|
|
157
|
+
activeRow,
|
|
158
|
+
content.format,
|
|
159
|
+
layout,
|
|
160
|
+
model.files.length,
|
|
161
|
+
model.stats.additions,
|
|
162
|
+
model.stats.deletions,
|
|
163
|
+
]);
|
|
164
|
+
return (_jsx(ViewScreen, { content: content, controller: document, actions: actions, statusItems: statusItems, ...screen, children: _jsx(DiffView, { rows: model.rows, document: document, activeIndex: activeIndex, showLineNumbers: showLineNumbers, layout: layout, wrapLines: wrapLines, horizontalOffset: horizontalOffset }) }));
|
|
165
|
+
};
|
|
166
|
+
//# sourceMappingURL=diff-subview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-subview.js","sourceRoot":"","sources":["../../../src/components/subviews/diff-subview.tsx"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ export { MarkdownSubview } from "./markdown-subview.js";
|
|
|
2
2
|
export { CodeSubview } from "./code-subview.js";
|
|
3
3
|
export { ImageSubview } from "./image-subview.js";
|
|
4
4
|
export { TableSubview } from "./table-subview.js";
|
|
5
|
+
export { DiffSubview } from "./diff-subview.js";
|
|
5
6
|
export { CustomSubview } from "./custom-subview.js";
|
|
6
7
|
export type { SubviewProps } from "./types.js";
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/subviews/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/subviews/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -2,5 +2,6 @@ export { MarkdownSubview } from "./markdown-subview.js";
|
|
|
2
2
|
export { CodeSubview } from "./code-subview.js";
|
|
3
3
|
export { ImageSubview } from "./image-subview.js";
|
|
4
4
|
export { TableSubview } from "./table-subview.js";
|
|
5
|
+
export { DiffSubview } from "./diff-subview.js";
|
|
5
6
|
export { CustomSubview } from "./custom-subview.js";
|
|
6
7
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/subviews/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/subviews/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default-provider.d.ts","sourceRoot":"","sources":["../src/default-provider.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"default-provider.d.ts","sourceRoot":"","sources":["../src/default-provider.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAW,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE1E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B;AAmGD,eAAO,MAAM,kBAAkB,aACnB,MAAM,YACP,qBAAqB,KAC7B,eAyBF,CAAC;AAEF,eAAO,MAAM,mBAAmB,aACrB,qBAAqB,KAC7B,eAQF,CAAC;AAEF,eAAO,MAAM,uBAAuB,aACxB,MAAM,KACf,eAEF,CAAC;AAEF,eAAO,MAAM,wBAAwB,QAAwC,eAE5E,CAAC"}
|
package/dist/default-provider.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { parseAuto } from "@tooee/renderers";
|
|
3
|
+
import { isDiffPatch } from "@tooee/diff";
|
|
3
4
|
const detectFormat = function detectFormat(filePath) {
|
|
4
5
|
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
5
6
|
if (ext === undefined || ext === "") {
|
|
@@ -13,6 +14,10 @@ const detectFormat = function detectFormat(filePath) {
|
|
|
13
14
|
if (tableExts.has(ext)) {
|
|
14
15
|
return { format: "table" };
|
|
15
16
|
}
|
|
17
|
+
const diffExts = new Set(["diff", "patch"]);
|
|
18
|
+
if (diffExts.has(ext)) {
|
|
19
|
+
return { format: "diff" };
|
|
20
|
+
}
|
|
16
21
|
const markdownExts = new Set(["md", "mdx", "markdown"]);
|
|
17
22
|
if (markdownExts.has(ext)) {
|
|
18
23
|
return { format: "markdown" };
|
|
@@ -58,6 +63,9 @@ const contentFromText = function contentFromText(text, format, title, language)
|
|
|
58
63
|
case "code": {
|
|
59
64
|
return { code: text, format: "code", language, title };
|
|
60
65
|
}
|
|
66
|
+
case "diff": {
|
|
67
|
+
return { format: "diff", patch: text, title };
|
|
68
|
+
}
|
|
61
69
|
case "table": {
|
|
62
70
|
const parsed = parseAuto(text);
|
|
63
71
|
return { columns: parsed.columns, format: "table", rows: parsed.rows, title };
|
|
@@ -84,7 +92,11 @@ export const createFileProvider = function createFileProvider(filePath, options
|
|
|
84
92
|
}
|
|
85
93
|
const file = Bun.file(filePath);
|
|
86
94
|
const text = await file.text();
|
|
87
|
-
|
|
95
|
+
// Patches are routinely written to files with no telling extension.
|
|
96
|
+
const resolved = options.renderer === undefined && detected.format === "text" && isDiffPatch(text)
|
|
97
|
+
? "diff"
|
|
98
|
+
: format;
|
|
99
|
+
const content = contentFromText(text, resolved, title, detected.language);
|
|
88
100
|
if (content.format === "markdown") {
|
|
89
101
|
content.imageBasePath = path.dirname(path.resolve(filePath));
|
|
90
102
|
}
|
|
@@ -96,7 +108,7 @@ export const createStdinProvider = function createStdinProvider(options = {}) {
|
|
|
96
108
|
return {
|
|
97
109
|
async load() {
|
|
98
110
|
const text = await new Response(Bun.stdin.stream()).text();
|
|
99
|
-
const format = options.renderer ?? "markdown";
|
|
111
|
+
const format = options.renderer ?? (isDiffPatch(text) ? "diff" : "markdown");
|
|
100
112
|
return contentFromText(text, format, "stdin");
|
|
101
113
|
},
|
|
102
114
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default-provider.js","sourceRoot":"","sources":["../src/default-provider.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"default-provider.js","sourceRoot":"","sources":["../src/default-provider.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { listDirectoryFiles } from "./directory-provider.js";
|
|
|
8
8
|
export type { DirectoryEntry } from "./directory-provider.js";
|
|
9
9
|
export { createViewCommandContext, useProvideViewCommandContext, } from "./hooks/use-view-command-context.js";
|
|
10
10
|
export type { CreateViewCommandContextOptions, ProvideViewCommandContextOptions, ViewCommandContext, } from "./hooks/use-view-command-context.js";
|
|
11
|
-
export type { AnyContent, Content, ContentChunk, ContentFormat, ContentProvider, ContentRenderer, ContentRendererProps, CustomContent, ImageContent, MarkdownContent, CodeContent, TextContent, TableContent, ViewContent, ViewContentProvider, ColumnDef, TableRow, } from "./types.js";
|
|
11
|
+
export type { AnyContent, Content, ContentChunk, ContentFormat, ContentProvider, ContentRenderer, ContentRendererProps, CustomContent, DiffContent, ImageContent, MarkdownContent, CodeContent, TextContent, TableContent, ViewContent, ViewContentProvider, ColumnDef, TableRow, } from "./types.js";
|
|
12
12
|
export { getTextContent, isBuiltinContent, isCustomContent } from "./types.js";
|
|
13
13
|
export { CodeBlockChrome } from "@tooee/renderers";
|
|
14
14
|
export type { CodeBlockRenderer, CodeBlockRendererProps, CodeBlockHScroll } from "@tooee/renderers";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACtD,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EACL,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EACV,+BAA+B,EAC/B,gCAAgC,EAChC,kBAAkB,GACnB,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EACV,UAAU,EACV,OAAO,EACP,YAAY,EACZ,aAAa,EACb,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,YAAY,EACZ,eAAe,EACf,WAAW,EACX,WAAW,EACX,YAAY,EACZ,WAAW,EACX,mBAAmB,EACnB,SAAS,EACT,QAAQ,GACT,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,YAAY,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACtD,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EACL,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EACV,+BAA+B,EAC/B,gCAAgC,EAChC,kBAAkB,GACnB,MAAM,qCAAqC,CAAC;AAC7C,YAAY,EACV,UAAU,EACV,OAAO,EACP,YAAY,EACZ,aAAa,EACb,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,WAAW,EACX,YAAY,EACZ,eAAe,EACf,WAAW,EACX,WAAW,EACX,YAAY,EACZ,WAAW,EACX,mBAAmB,EACnB,SAAS,EACT,QAAQ,GACT,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,YAAY,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EACL,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EACL,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,qCAAqC,CAAC;AA0B7C,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { ImageFit, ImageRenderProtocol, ImageSource } from "@opentui/core";
|
|
|
3
3
|
import type { ColumnDef, SourceLineRow, TableRow } from "@tooee/renderers";
|
|
4
4
|
import type { DocumentController } from "@tooee/shell";
|
|
5
5
|
import type { MarkSet } from "@tooee/marks";
|
|
6
|
-
export type Content = MarkdownContent | CodeContent | TextContent | ImageContent | TableContent;
|
|
6
|
+
export type Content = MarkdownContent | CodeContent | TextContent | ImageContent | TableContent | DiffContent;
|
|
7
7
|
export type ContentFormat = Content["format"];
|
|
8
8
|
interface BaseContent {
|
|
9
9
|
title?: string;
|
|
@@ -35,6 +35,13 @@ export interface TableContent extends BaseContent {
|
|
|
35
35
|
columns: ColumnDef[];
|
|
36
36
|
rows: TableRow[];
|
|
37
37
|
}
|
|
38
|
+
export interface DiffContent extends BaseContent {
|
|
39
|
+
format: "diff";
|
|
40
|
+
/** Unified patch text, single- or multi-file. */
|
|
41
|
+
patch: string;
|
|
42
|
+
/** Initial layout; defaults to stacked (unified). */
|
|
43
|
+
layout?: "split" | "stack";
|
|
44
|
+
}
|
|
38
45
|
export interface CustomContent<T = unknown> {
|
|
39
46
|
format: string;
|
|
40
47
|
data: T;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,QAAQ,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAI5C,MAAM,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// === Utilities ===
|
|
2
|
-
const BUILTIN_FORMATS = new Set(["markdown", "code", "text", "image", "table"]);
|
|
2
|
+
const BUILTIN_FORMATS = new Set(["markdown", "code", "text", "image", "table", "diff"]);
|
|
3
3
|
export const isBuiltinContent = function isBuiltinContent(content) {
|
|
4
4
|
return BUILTIN_FORMATS.has(content.format);
|
|
5
5
|
};
|
|
@@ -52,6 +52,9 @@ export const getTextContent = function getTextContent(content) {
|
|
|
52
52
|
case "code": {
|
|
53
53
|
return content.code;
|
|
54
54
|
}
|
|
55
|
+
case "diff": {
|
|
56
|
+
return content.patch;
|
|
57
|
+
}
|
|
55
58
|
case "text": {
|
|
56
59
|
return content.text;
|
|
57
60
|
}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/view.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../src/view.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../src/view.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAG/E,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAWnE,UAAU,SAAS;IACjB,eAAe,EAAE,eAAe,CAAC;IACjC,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC5C;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACvD,kEAAkE;IAClE,sBAAsB,CAAC,EAAE,mBAAmB,CAAC;CAC9C;AAED,eAAO,MAAM,IAAI,yFAMd,SAAS,KAAG,KAAK,CAAC,SA4FpB,CAAC"}
|
package/dist/view.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx } from "@opentui/react/jsx-runtime";
|
|
2
2
|
import { useCallback, useMemo, useState } from "react";
|
|
3
3
|
import { useTheme } from "@tooee/themes";
|
|
4
|
+
import { DIFF_CODE_BLOCK_RENDERERS } from "@tooee/diff";
|
|
4
5
|
import { isCustomContent } from "./types.js";
|
|
5
6
|
import { useContentLoader } from "./hooks/use-content-loader.js";
|
|
6
|
-
import { MarkdownSubview, CodeSubview, TableSubview, ImageSubview, CustomSubview, } from "./components/subviews/index.js";
|
|
7
|
+
import { MarkdownSubview, CodeSubview, TableSubview, ImageSubview, DiffSubview, CustomSubview, } from "./components/subviews/index.js";
|
|
7
8
|
export const View = function View({ contentProvider, actions, renderers, codeBlockRenderers, onMarkdownLinkActivate, }) {
|
|
8
9
|
const { theme } = useTheme();
|
|
9
10
|
const { content, streaming, error, providerMarks, reload } = useContentLoader(contentProvider);
|
|
@@ -23,6 +24,9 @@ export const View = function View({ contentProvider, actions, renderers, codeBlo
|
|
|
23
24
|
// Mark sets are decoration layers; the controller composes them with the
|
|
24
25
|
// interaction layers it generates, ordered by each set's own priority.
|
|
25
26
|
const decorations = useMemo(() => [...providerMarks, ...userMarks], [providerMarks, userMarks]);
|
|
27
|
+
// ```diff / ```patch fences render as Hunk diff blocks unless the host
|
|
28
|
+
// registers its own renderer for those types.
|
|
29
|
+
const mergedCodeBlockRenderers = useMemo(() => ({ ...DIFF_CODE_BLOCK_RENDERERS, ...codeBlockRenderers }), [codeBlockRenderers]);
|
|
26
30
|
if ((error?.length ?? 0) > 0) {
|
|
27
31
|
return (_jsx("box", { style: { flexDirection: "column" }, children: _jsx("text", { content: `Error: ${error}`, fg: theme.error }) }));
|
|
28
32
|
}
|
|
@@ -45,7 +49,7 @@ export const View = function View({ contentProvider, actions, renderers, codeBlo
|
|
|
45
49
|
}
|
|
46
50
|
switch (content.format) {
|
|
47
51
|
case "markdown": {
|
|
48
|
-
return (_jsx(MarkdownSubview, { content: content, codeBlockRenderers:
|
|
52
|
+
return (_jsx(MarkdownSubview, { content: content, codeBlockRenderers: mergedCodeBlockRenderers, onLinkActivate: onMarkdownLinkActivate, ...shared }));
|
|
49
53
|
}
|
|
50
54
|
case "code":
|
|
51
55
|
case "text": {
|
|
@@ -57,6 +61,9 @@ export const View = function View({ contentProvider, actions, renderers, codeBlo
|
|
|
57
61
|
case "table": {
|
|
58
62
|
return _jsx(TableSubview, { content: content, ...shared });
|
|
59
63
|
}
|
|
64
|
+
case "diff": {
|
|
65
|
+
return _jsx(DiffSubview, { content: content, ...shared });
|
|
66
|
+
}
|
|
60
67
|
default: {
|
|
61
68
|
return null;
|
|
62
69
|
}
|
package/dist/view.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tooee/view",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "Terminal content viewer for markdown, code, text, images, and tables",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -40,15 +40,16 @@
|
|
|
40
40
|
"typecheck": "tsc --noEmit"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@tooee/commands": "0.
|
|
44
|
-
"@tooee/config": "0.
|
|
45
|
-
"@tooee/
|
|
46
|
-
"@tooee/
|
|
47
|
-
"@tooee/
|
|
48
|
-
"@tooee/
|
|
49
|
-
"@tooee/
|
|
50
|
-
"@tooee/
|
|
51
|
-
"@tooee/
|
|
43
|
+
"@tooee/commands": "0.7.1",
|
|
44
|
+
"@tooee/config": "0.7.1",
|
|
45
|
+
"@tooee/diff": "0.7.1",
|
|
46
|
+
"@tooee/layout": "0.7.1",
|
|
47
|
+
"@tooee/marks": "0.7.1",
|
|
48
|
+
"@tooee/overlays": "0.7.1",
|
|
49
|
+
"@tooee/renderers": "0.7.1",
|
|
50
|
+
"@tooee/search": "0.7.1",
|
|
51
|
+
"@tooee/shell": "0.7.1",
|
|
52
|
+
"@tooee/themes": "0.7.1",
|
|
52
53
|
"@xstate/store": "^4",
|
|
53
54
|
"@xstate/store-react": "^2",
|
|
54
55
|
"marked": "^17.0.4"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { CommandPalette } from "@tooee/renderers";
|
|
3
|
+
import type { HunkDiffFile } from "@tooee/diff";
|
|
4
|
+
|
|
5
|
+
export interface DiffFilePickerOverlayProps {
|
|
6
|
+
files: readonly HunkDiffFile[];
|
|
7
|
+
onSelect: (fileIndex: number) => void;
|
|
8
|
+
close: () => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Fuzzy file picker for a diff. Entries are indexed by position so two files
|
|
13
|
+
* with the same path (a rename pair, say) still resolve to distinct rows.
|
|
14
|
+
*/
|
|
15
|
+
export const DiffFilePickerOverlay = function DiffFilePickerOverlay({
|
|
16
|
+
files,
|
|
17
|
+
onSelect,
|
|
18
|
+
close,
|
|
19
|
+
}: DiffFilePickerOverlayProps): ReactNode {
|
|
20
|
+
const entries = files.map((file, index) => ({
|
|
21
|
+
id: String(index),
|
|
22
|
+
title: `${file.previousPath === undefined ? "" : `${file.previousPath} -> `}${
|
|
23
|
+
file.path ?? file.id
|
|
24
|
+
} +${file.stats.additions} -${file.stats.deletions}`,
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<CommandPalette
|
|
29
|
+
commands={entries}
|
|
30
|
+
onClose={close}
|
|
31
|
+
onSelect={(id: string) => {
|
|
32
|
+
onSelect(Number(id));
|
|
33
|
+
close();
|
|
34
|
+
}}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { createElement, useCallback, useMemo, useState } from "react";
|
|
2
|
+
import { DiffView, buildDiffModel, diffRowAdapter } from "@tooee/diff";
|
|
3
|
+
import type { DiffRow } from "@tooee/diff";
|
|
4
|
+
import { useCommand } from "@tooee/commands";
|
|
5
|
+
import { useConfig } from "@tooee/config";
|
|
6
|
+
import { useOverlay } from "@tooee/overlays";
|
|
7
|
+
import type { OverlayCloseReason } from "@tooee/overlays";
|
|
8
|
+
import { useDocumentController } from "@tooee/shell";
|
|
9
|
+
import type { DocumentRowAdapter } from "@tooee/shell";
|
|
10
|
+
import type { DiffContent } from "../../types.js";
|
|
11
|
+
import { useContentCommands } from "../../hooks/use-content-commands.js";
|
|
12
|
+
import { ViewScreen } from "../view-screen.js";
|
|
13
|
+
import { DiffFilePickerOverlay } from "../diff-file-picker.js";
|
|
14
|
+
import type { SubviewProps } from "./types.js";
|
|
15
|
+
|
|
16
|
+
interface DiffSubviewProps extends SubviewProps {
|
|
17
|
+
content: DiffContent;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Columns panned per h/l press when a hunk is wider than the viewport. */
|
|
21
|
+
const HSCROLL_STEP = 4;
|
|
22
|
+
|
|
23
|
+
const FILE_PICKER_OVERLAY = "diff-file-picker";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Rows are file headers and hunks, so `getText` is the row's patch text and
|
|
27
|
+
* `getSource` its span in the original patch: search, copy and marks all work
|
|
28
|
+
* in real patch coordinates rather than in rendered diff lines.
|
|
29
|
+
*/
|
|
30
|
+
const DIFF_ROW_ADAPTER: DocumentRowAdapter<DiffRow> = diffRowAdapter;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The built-in diff viewer: a Hunk-rendered patch inside Tooee's normal chrome.
|
|
34
|
+
*
|
|
35
|
+
* Hunk owns the drawing of each file header and hunk; the row document owns
|
|
36
|
+
* scrolling, the cursor, decorations and mouse routing. The cursor row maps 1:1
|
|
37
|
+
* onto Hunk's `{ fileId, hunkIndex }` selection, so `j`/`k` step hunk by hunk.
|
|
38
|
+
*/
|
|
39
|
+
export const DiffSubview = function DiffSubview({
|
|
40
|
+
content,
|
|
41
|
+
decorations,
|
|
42
|
+
actions,
|
|
43
|
+
...screen
|
|
44
|
+
}: DiffSubviewProps): React.ReactNode {
|
|
45
|
+
const config = useConfig();
|
|
46
|
+
const overlay = useOverlay();
|
|
47
|
+
const textContent = content.patch;
|
|
48
|
+
const model = useMemo(() => buildDiffModel(content.patch), [content.patch]);
|
|
49
|
+
|
|
50
|
+
const [layout, setLayout] = useState<"split" | "stack">(
|
|
51
|
+
content.layout ?? config.view?.diffLayout ?? "stack",
|
|
52
|
+
);
|
|
53
|
+
const [wrapLines, setWrapLines] = useState(config.view?.wrap ?? false);
|
|
54
|
+
const [horizontalOffset, setHorizontalOffset] = useState(0);
|
|
55
|
+
|
|
56
|
+
const { showLineNumbers } = useContentCommands({ content, textContent });
|
|
57
|
+
|
|
58
|
+
const document = useDocumentController<DiffRow>({
|
|
59
|
+
adapter: DIFF_ROW_ADAPTER,
|
|
60
|
+
// The controller projects the screen's actions onto menu entries at open time.
|
|
61
|
+
contextMenu: actions,
|
|
62
|
+
decorations,
|
|
63
|
+
multiSelect: true,
|
|
64
|
+
preserveCursorByKey: true,
|
|
65
|
+
rows: model.rows,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const { activeIndex } = document;
|
|
69
|
+
// `setCursor` rather than `selectRow`: the latter stands down while a modal
|
|
70
|
+
// overlay is open, which is exactly when the file picker commits its choice.
|
|
71
|
+
const { setCursor } = document.navigation;
|
|
72
|
+
|
|
73
|
+
/** Index of the file-header row for `fileIndex`, or `null` when absent. */
|
|
74
|
+
const fileRowIndex = useCallback(
|
|
75
|
+
(fileIndex: number): number | null => {
|
|
76
|
+
const index = model.rows.findIndex(
|
|
77
|
+
(row) => row.kind === "file" && row.fileIndex === fileIndex,
|
|
78
|
+
);
|
|
79
|
+
return index === -1 ? null : index;
|
|
80
|
+
},
|
|
81
|
+
[model.rows],
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const jumpFile = useCallback(
|
|
85
|
+
(delta: number) => {
|
|
86
|
+
const current = activeIndex === null ? undefined : model.rows[activeIndex];
|
|
87
|
+
const from = current?.fileIndex ?? 0;
|
|
88
|
+
const target = Math.min(Math.max(from + delta, 0), model.files.length - 1);
|
|
89
|
+
const index = fileRowIndex(target);
|
|
90
|
+
if (index !== null) {
|
|
91
|
+
setCursor(index);
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
[activeIndex, fileRowIndex, model.files.length, model.rows, setCursor],
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
useCommand({
|
|
98
|
+
handler: () => {
|
|
99
|
+
setLayout((value) => (value === "split" ? "stack" : "split"));
|
|
100
|
+
},
|
|
101
|
+
hotkey: "s",
|
|
102
|
+
id: "diff.toggle-layout",
|
|
103
|
+
modes: ["cursor", "select"],
|
|
104
|
+
title: "Toggle split/unified diff",
|
|
105
|
+
});
|
|
106
|
+
useCommand({
|
|
107
|
+
handler: () => {
|
|
108
|
+
setWrapLines((value) => !value);
|
|
109
|
+
setHorizontalOffset(0);
|
|
110
|
+
},
|
|
111
|
+
hotkey: "w",
|
|
112
|
+
id: "diff.toggle-wrap",
|
|
113
|
+
modes: ["cursor", "select"],
|
|
114
|
+
title: "Toggle diff line wrapping",
|
|
115
|
+
});
|
|
116
|
+
useCommand({
|
|
117
|
+
handler: () => {
|
|
118
|
+
jumpFile(1);
|
|
119
|
+
},
|
|
120
|
+
hotkey: "]",
|
|
121
|
+
id: "diff.next-file",
|
|
122
|
+
modes: ["cursor", "select"],
|
|
123
|
+
title: "Next file",
|
|
124
|
+
});
|
|
125
|
+
useCommand({
|
|
126
|
+
handler: () => {
|
|
127
|
+
jumpFile(-1);
|
|
128
|
+
},
|
|
129
|
+
hotkey: "[",
|
|
130
|
+
id: "diff.prev-file",
|
|
131
|
+
modes: ["cursor", "select"],
|
|
132
|
+
title: "Previous file",
|
|
133
|
+
});
|
|
134
|
+
useCommand({
|
|
135
|
+
handler: () => {
|
|
136
|
+
setHorizontalOffset((value) => Math.max(0, value - HSCROLL_STEP));
|
|
137
|
+
},
|
|
138
|
+
hotkey: "h",
|
|
139
|
+
id: "diff.scroll-left",
|
|
140
|
+
modes: ["cursor"],
|
|
141
|
+
title: "Pan diff left",
|
|
142
|
+
when: () => !wrapLines,
|
|
143
|
+
});
|
|
144
|
+
useCommand({
|
|
145
|
+
handler: () => {
|
|
146
|
+
setHorizontalOffset((value) => value + HSCROLL_STEP);
|
|
147
|
+
},
|
|
148
|
+
hotkey: "l",
|
|
149
|
+
id: "diff.scroll-right",
|
|
150
|
+
modes: ["cursor"],
|
|
151
|
+
title: "Pan diff right",
|
|
152
|
+
when: () => !wrapLines,
|
|
153
|
+
});
|
|
154
|
+
useCommand({
|
|
155
|
+
handler: () => {
|
|
156
|
+
overlay.open(
|
|
157
|
+
FILE_PICKER_OVERLAY,
|
|
158
|
+
({ close }: { close: (reason?: OverlayCloseReason) => void }) =>
|
|
159
|
+
createElement(DiffFilePickerOverlay, {
|
|
160
|
+
close: () => {
|
|
161
|
+
close();
|
|
162
|
+
},
|
|
163
|
+
files: model.files,
|
|
164
|
+
onSelect: (fileIndex: number) => {
|
|
165
|
+
const index = fileRowIndex(fileIndex);
|
|
166
|
+
if (index !== null) {
|
|
167
|
+
setCursor(index);
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
}),
|
|
171
|
+
null,
|
|
172
|
+
{ ownCommands: true, role: "modal", surfaceMode: "insert" },
|
|
173
|
+
);
|
|
174
|
+
},
|
|
175
|
+
hotkey: "f",
|
|
176
|
+
id: "diff.file-picker",
|
|
177
|
+
modes: ["cursor", "select"],
|
|
178
|
+
title: "Go to file",
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
const activeRow = activeIndex === null ? undefined : model.rows[activeIndex];
|
|
182
|
+
const statusItems = useMemo(
|
|
183
|
+
() => [
|
|
184
|
+
{ label: "Format:", value: content.format },
|
|
185
|
+
{ label: "Files:", value: String(model.files.length) },
|
|
186
|
+
{ label: "Changes:", value: `+${model.stats.additions} -${model.stats.deletions}` },
|
|
187
|
+
{ label: "Layout:", value: layout },
|
|
188
|
+
...(activeRow
|
|
189
|
+
? [
|
|
190
|
+
{
|
|
191
|
+
label: "At:",
|
|
192
|
+
value:
|
|
193
|
+
activeRow.hunkIndex >= 0
|
|
194
|
+
? `${activeRow.parent.path ?? activeRow.fileId}:${activeRow.hunkIndex + 1}`
|
|
195
|
+
: (activeRow.parent.path ?? activeRow.fileId),
|
|
196
|
+
},
|
|
197
|
+
]
|
|
198
|
+
: []),
|
|
199
|
+
],
|
|
200
|
+
[
|
|
201
|
+
activeRow,
|
|
202
|
+
content.format,
|
|
203
|
+
layout,
|
|
204
|
+
model.files.length,
|
|
205
|
+
model.stats.additions,
|
|
206
|
+
model.stats.deletions,
|
|
207
|
+
],
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
return (
|
|
211
|
+
<ViewScreen
|
|
212
|
+
content={content}
|
|
213
|
+
controller={document}
|
|
214
|
+
actions={actions}
|
|
215
|
+
statusItems={statusItems}
|
|
216
|
+
{...screen}
|
|
217
|
+
>
|
|
218
|
+
<DiffView
|
|
219
|
+
rows={model.rows}
|
|
220
|
+
document={document}
|
|
221
|
+
activeIndex={activeIndex}
|
|
222
|
+
showLineNumbers={showLineNumbers}
|
|
223
|
+
layout={layout}
|
|
224
|
+
wrapLines={wrapLines}
|
|
225
|
+
horizontalOffset={horizontalOffset}
|
|
226
|
+
/>
|
|
227
|
+
</ViewScreen>
|
|
228
|
+
);
|
|
229
|
+
};
|
|
@@ -2,5 +2,6 @@ export { MarkdownSubview } from "./markdown-subview.js";
|
|
|
2
2
|
export { CodeSubview } from "./code-subview.js";
|
|
3
3
|
export { ImageSubview } from "./image-subview.js";
|
|
4
4
|
export { TableSubview } from "./table-subview.js";
|
|
5
|
+
export { DiffSubview } from "./diff-subview.js";
|
|
5
6
|
export { CustomSubview } from "./custom-subview.js";
|
|
6
7
|
export type { SubviewProps } from "./types.js";
|
package/src/default-provider.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { parseAuto } from "@tooee/renderers";
|
|
3
|
+
import { isDiffPatch } from "@tooee/diff";
|
|
3
4
|
import type { Content, ContentFormat, ContentProvider } from "./types.js";
|
|
4
5
|
|
|
5
6
|
export interface CreateProviderOptions {
|
|
@@ -25,6 +26,11 @@ const detectFormat = function detectFormat(filePath: string): {
|
|
|
25
26
|
return { format: "table" };
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
const diffExts = new Set(["diff", "patch"]);
|
|
30
|
+
if (diffExts.has(ext)) {
|
|
31
|
+
return { format: "diff" };
|
|
32
|
+
}
|
|
33
|
+
|
|
28
34
|
const markdownExts = new Set(["md", "mdx", "markdown"]);
|
|
29
35
|
if (markdownExts.has(ext)) {
|
|
30
36
|
return { format: "markdown" };
|
|
@@ -79,6 +85,9 @@ const contentFromText = function contentFromText(
|
|
|
79
85
|
case "code": {
|
|
80
86
|
return { code: text, format: "code", language, title };
|
|
81
87
|
}
|
|
88
|
+
case "diff": {
|
|
89
|
+
return { format: "diff", patch: text, title };
|
|
90
|
+
}
|
|
82
91
|
case "table": {
|
|
83
92
|
const parsed = parseAuto(text);
|
|
84
93
|
return { columns: parsed.columns, format: "table", rows: parsed.rows, title };
|
|
@@ -111,7 +120,12 @@ export const createFileProvider = function createFileProvider(
|
|
|
111
120
|
|
|
112
121
|
const file = Bun.file(filePath);
|
|
113
122
|
const text = await file.text();
|
|
114
|
-
|
|
123
|
+
// Patches are routinely written to files with no telling extension.
|
|
124
|
+
const resolved =
|
|
125
|
+
options.renderer === undefined && detected.format === "text" && isDiffPatch(text)
|
|
126
|
+
? "diff"
|
|
127
|
+
: format;
|
|
128
|
+
const content = contentFromText(text, resolved, title, detected.language);
|
|
115
129
|
if (content.format === "markdown") {
|
|
116
130
|
content.imageBasePath = path.dirname(path.resolve(filePath));
|
|
117
131
|
}
|
|
@@ -126,7 +140,7 @@ export const createStdinProvider = function createStdinProvider(
|
|
|
126
140
|
return {
|
|
127
141
|
async load(): Promise<Content> {
|
|
128
142
|
const text = await new Response(Bun.stdin.stream()).text();
|
|
129
|
-
const format = options.renderer ?? "markdown";
|
|
143
|
+
const format = options.renderer ?? (isDiffPatch(text) ? "diff" : "markdown");
|
|
130
144
|
return contentFromText(text, format, "stdin");
|
|
131
145
|
},
|
|
132
146
|
};
|
package/src/index.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -6,7 +6,13 @@ import type { MarkSet } from "@tooee/marks";
|
|
|
6
6
|
|
|
7
7
|
// === Built-in content types ===
|
|
8
8
|
|
|
9
|
-
export type Content =
|
|
9
|
+
export type Content =
|
|
10
|
+
| MarkdownContent
|
|
11
|
+
| CodeContent
|
|
12
|
+
| TextContent
|
|
13
|
+
| ImageContent
|
|
14
|
+
| TableContent
|
|
15
|
+
| DiffContent;
|
|
10
16
|
|
|
11
17
|
export type ContentFormat = Content["format"];
|
|
12
18
|
|
|
@@ -46,6 +52,14 @@ export interface TableContent extends BaseContent {
|
|
|
46
52
|
rows: TableRow[];
|
|
47
53
|
}
|
|
48
54
|
|
|
55
|
+
export interface DiffContent extends BaseContent {
|
|
56
|
+
format: "diff";
|
|
57
|
+
/** Unified patch text, single- or multi-file. */
|
|
58
|
+
patch: string;
|
|
59
|
+
/** Initial layout; defaults to stacked (unified). */
|
|
60
|
+
layout?: "split" | "stack";
|
|
61
|
+
}
|
|
62
|
+
|
|
49
63
|
// === Custom content ===
|
|
50
64
|
|
|
51
65
|
export interface CustomContent<T = unknown> {
|
|
@@ -122,7 +136,7 @@ export type { ColumnDef, TableRow } from "@tooee/renderers";
|
|
|
122
136
|
|
|
123
137
|
// === Utilities ===
|
|
124
138
|
|
|
125
|
-
const BUILTIN_FORMATS = new Set<string>(["markdown", "code", "text", "image", "table"]);
|
|
139
|
+
const BUILTIN_FORMATS = new Set<string>(["markdown", "code", "text", "image", "table", "diff"]);
|
|
126
140
|
|
|
127
141
|
export const isBuiltinContent = function isBuiltinContent(content: AnyContent): content is Content {
|
|
128
142
|
return BUILTIN_FORMATS.has(content.format);
|
|
@@ -184,6 +198,9 @@ export const getTextContent = function getTextContent(content: AnyContent): stri
|
|
|
184
198
|
case "code": {
|
|
185
199
|
return content.code;
|
|
186
200
|
}
|
|
201
|
+
case "diff": {
|
|
202
|
+
return content.patch;
|
|
203
|
+
}
|
|
187
204
|
case "text": {
|
|
188
205
|
return content.text;
|
|
189
206
|
}
|
package/src/view.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import { useTheme } from "@tooee/themes";
|
|
|
3
3
|
import type { ActionDefinition } from "@tooee/commands";
|
|
4
4
|
import type { MarkSet } from "@tooee/marks";
|
|
5
5
|
import type { CodeBlockRenderer, MarkdownLinkHandler } from "@tooee/renderers";
|
|
6
|
+
import { DIFF_CODE_BLOCK_RENDERERS } from "@tooee/diff";
|
|
6
7
|
import { isCustomContent } from "./types.js";
|
|
7
8
|
import type { ContentProvider, ContentRenderer } from "./types.js";
|
|
8
9
|
import { useContentLoader } from "./hooks/use-content-loader.js";
|
|
@@ -11,6 +12,7 @@ import {
|
|
|
11
12
|
CodeSubview,
|
|
12
13
|
TableSubview,
|
|
13
14
|
ImageSubview,
|
|
15
|
+
DiffSubview,
|
|
14
16
|
CustomSubview,
|
|
15
17
|
} from "./components/subviews/index.js";
|
|
16
18
|
|
|
@@ -58,6 +60,13 @@ export const View = function View({
|
|
|
58
60
|
// interaction layers it generates, ordered by each set's own priority.
|
|
59
61
|
const decorations = useMemo(() => [...providerMarks, ...userMarks], [providerMarks, userMarks]);
|
|
60
62
|
|
|
63
|
+
// ```diff / ```patch fences render as Hunk diff blocks unless the host
|
|
64
|
+
// registers its own renderer for those types.
|
|
65
|
+
const mergedCodeBlockRenderers = useMemo(
|
|
66
|
+
() => ({ ...DIFF_CODE_BLOCK_RENDERERS, ...codeBlockRenderers }),
|
|
67
|
+
[codeBlockRenderers],
|
|
68
|
+
);
|
|
69
|
+
|
|
61
70
|
if ((error?.length ?? 0) > 0) {
|
|
62
71
|
return (
|
|
63
72
|
<box style={{ flexDirection: "column" }}>
|
|
@@ -95,7 +104,7 @@ export const View = function View({
|
|
|
95
104
|
return (
|
|
96
105
|
<MarkdownSubview
|
|
97
106
|
content={content}
|
|
98
|
-
codeBlockRenderers={
|
|
107
|
+
codeBlockRenderers={mergedCodeBlockRenderers}
|
|
99
108
|
onLinkActivate={onMarkdownLinkActivate}
|
|
100
109
|
{...shared}
|
|
101
110
|
/>
|
|
@@ -111,6 +120,9 @@ export const View = function View({
|
|
|
111
120
|
case "table": {
|
|
112
121
|
return <TableSubview content={content} {...shared} />;
|
|
113
122
|
}
|
|
123
|
+
case "diff": {
|
|
124
|
+
return <DiffSubview content={content} {...shared} />;
|
|
125
|
+
}
|
|
114
126
|
default: {
|
|
115
127
|
return null;
|
|
116
128
|
}
|