@cardinal4/opencode-fold-diffs 0.3.5 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -7
- package/package.json +1 -1
- package/tui.js +19 -2
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# opencode-fold-diffs
|
|
2
2
|
|
|
3
3
|
> [!NOTE]
|
|
4
|
-
> **Unofficial OpenCode V2 port of [Tanner Bruhn](https://github.com/tannerbruhn)'s [`opencode-fold-diffs`](https://github.com/tannerbruhn/opencode-fold-diffs) (npm: `opencode-fold-diffs`) — the OpenCode V1 plugin.** This fork — [`cardin/opencode-fold-diffs`](https://github.com/cardin/opencode-fold-diffs), published as [`@cardinal4/opencode-fold-diffs`](https://www.npmjs.com/package/@cardinal4/opencode-fold-diffs) — ports it to **OpenCode V2** (`@opencode/cli` 2.x, `opencode
|
|
4
|
+
> **Unofficial OpenCode V2 port of [Tanner Bruhn](https://github.com/tannerbruhn)'s [`opencode-fold-diffs`](https://github.com/tannerbruhn/opencode-fold-diffs) (npm: `opencode-fold-diffs`) — the OpenCode V1 plugin.** This fork — [`cardin/opencode-fold-diffs`](https://github.com/cardin/opencode-fold-diffs), published as [`@cardinal4/opencode-fold-diffs`](https://www.npmjs.com/package/@cardinal4/opencode-fold-diffs) — ports it to **OpenCode V2** (`@opencode/cli` 2.x, tested with `opencode 2.2.0`). Install this fork on V2, upstream on V1. Tanner has not reviewed or endorsed it; report bugs here, not upstream.
|
|
5
5
|
|
|
6
6
|
**Every `write`, `edit` and `apply_patch` dumps the whole file or the whole diff into your transcript, and stays there.** This plugin folds those blocks down to their header line — `# Wrote 40 lines · click to expand src/app.ts` — and opens them again on click, or with a fold/unfold-all key if you configure one.
|
|
7
7
|
|
|
@@ -33,7 +33,9 @@ Click the row to open it. If you set the `key` option, that binding folds or unf
|
|
|
33
33
|
opencode plugin add @cardinal4/opencode-fold-diffs
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
That installs the package and adds it to the global `opencode.json`. The package ships a server entry (`index.js`, a no-op that gives the plugin an id) and a TUI entry (`tui.js`); the TUI part loads automatically with the server entry, so no second configuration is needed.
|
|
37
|
+
|
|
38
|
+
If the terminal connects to a **remote server**, list the package in `~/.config/opencode/cli.json` (or `$XDG_CONFIG_HOME/opencode/cli.json`) instead so the local TUI loads the TUI part. Do not list it in both files:
|
|
37
39
|
|
|
38
40
|
```json
|
|
39
41
|
{
|
|
@@ -42,9 +44,7 @@ Then list it in your CLI config so the terminal loads the TUI entrypoint. Add it
|
|
|
42
44
|
}
|
|
43
45
|
```
|
|
44
46
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
With options:
|
|
47
|
+
Options go on the plugin entry in either file:
|
|
48
48
|
|
|
49
49
|
```json
|
|
50
50
|
{
|
|
@@ -115,7 +115,7 @@ Blocks are re-scanned on V2's `session.message.content.updated`, `session.tool.s
|
|
|
115
115
|
|
|
116
116
|
## Status
|
|
117
117
|
|
|
118
|
-
Written against **opencode v2.0.24
|
|
118
|
+
Written against **opencode v2.0.24**, re-checked against **v2.0.27** and **v2.2.0**; the `session.*` events it listens to exist from v2.0.10 on, so an older V2 install gets the fix without upgrading. The tree-walking, block matching, fold/unfold and toggle logic run green against a mock renderer tree shaped like V2's (`node --test`), and the fold was checked against a real transcript: `visible = false` (Yoga `display: none`) is what actually hides a body, not `maxHeight`.
|
|
119
119
|
|
|
120
120
|
To confirm it loaded, restart (`opencode service restart`) and check `/plugins` lists `opencode-fold-diffs` and `Ctrl+P` → **Fold / unfold file diffs** is in the palette. If nothing folds, run **Fold diffs: diagnose** — the toast reports what the plugin can see:
|
|
121
121
|
|
|
@@ -126,6 +126,8 @@ To confirm it loaded, restart (`opencode service restart`) and check `/plugins`
|
|
|
126
126
|
| `transcript: yes · blocks: N · folded: N` | Detection and folding ran; if the blocks still look expanded, the fold did not take on the renderables. |
|
|
127
127
|
| `stats: off` | Folding works but the header could not be restated (Solid owns the label node). |
|
|
128
128
|
|
|
129
|
+
The diagnose dump includes up to 80 characters of text from each renderable, so it can contain prompts or tool output. Redact it before sharing; set `dump: false` to skip writing it.
|
|
130
|
+
|
|
129
131
|
Edits with fewer than `min_lines` changed lines (default 6) are left expanded on purpose — a one-line change is already its own summary. Set `min_lines: 0` to fold every file block.
|
|
130
132
|
|
|
131
133
|
## V2 port notes
|
|
@@ -136,7 +138,7 @@ The port follows V2's new plugin API and render tree, so the V1 code could not b
|
|
|
136
138
|
- `api.renderer` → `context.renderer`, `api.route.current.name` → `context.ui.router.current().type`, `api.event.on` → `context.data.on`, `api.ui.toast` → `context.ui.toast.show`, `api.keymap.registerLayer` → `context.keymap.layer` (called straight from `setup` on 2.0.23+, from an `app`-slot component before that).
|
|
137
139
|
- Event names are V2's `session.*` events; `message.updated` / `message.part.updated` are legacy schemas that never fire.
|
|
138
140
|
- Tool headers are a label node plus a path node, so detection and the stats suffix target the label.
|
|
139
|
-
- `bash` defaults to `false` because V2 trims long commands itself, and config moves from `tui.json` to `cli.json
|
|
141
|
+
- `bash` defaults to `false` because V2 trims long commands itself, and config moves from `tui.json` to `opencode.json` (or `cli.json` for a remote TUI).
|
|
140
142
|
|
|
141
143
|
## License
|
|
142
144
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cardinal4/opencode-fold-diffs",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"description": "Unofficial OpenCode V2 fork of opencode-fold-diffs: write, edit and apply_patch blocks render folded to their header line, click to expand.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
package/tui.js
CHANGED
|
@@ -221,7 +221,8 @@ function summarise(nodes) {
|
|
|
221
221
|
}
|
|
222
222
|
continue;
|
|
223
223
|
}
|
|
224
|
-
|
|
224
|
+
const content = node.content.endsWith("\n") ? node.content.slice(0, -1) : node.content;
|
|
225
|
+
lines += content === "" ? 0 : content.split("\n").length;
|
|
225
226
|
}
|
|
226
227
|
if (diffs) return { size: added + removed, label: `+${added} −${removed}` };
|
|
227
228
|
return { size: lines, label: `${lines} ${lines === 1 ? "line" : "lines"}` };
|
|
@@ -271,6 +272,10 @@ export default {
|
|
|
271
272
|
// Folded blocks, by their block renderable. WeakMap so a session switch,
|
|
272
273
|
// which destroys the renderables, drops the state with them.
|
|
273
274
|
const known = new WeakMap();
|
|
275
|
+
// WeakMap has no iterator, so keep a strong set of adopted blocks only for
|
|
276
|
+
// cleanup. Destroyed blocks are pruned on the sweep to avoid retaining a
|
|
277
|
+
// closed session's renderables.
|
|
278
|
+
const adopted = new Set();
|
|
274
279
|
// The mode new blocks adopt. ctrl+o flips it, so "expand everything" also
|
|
275
280
|
// means "and stop folding what arrives next", the way a verbose toggle works.
|
|
276
281
|
let folding = opts.folded !== false;
|
|
@@ -356,6 +361,7 @@ export default {
|
|
|
356
361
|
folded: false,
|
|
357
362
|
};
|
|
358
363
|
known.set(block, state);
|
|
364
|
+
adopted.add(block);
|
|
359
365
|
|
|
360
366
|
block.onMouseUp = () => {
|
|
361
367
|
// Copy-on-select is a drag ending on the block; that is not a click.
|
|
@@ -382,6 +388,7 @@ export default {
|
|
|
382
388
|
folded: false,
|
|
383
389
|
};
|
|
384
390
|
known.set(block, state);
|
|
391
|
+
adopted.add(block);
|
|
385
392
|
|
|
386
393
|
// The block's own onMouseUp belongs to the host here -- it is what expands
|
|
387
394
|
// the collapsed command/output -- and opentui declares the handler as a
|
|
@@ -404,6 +411,7 @@ export default {
|
|
|
404
411
|
}
|
|
405
412
|
|
|
406
413
|
function sweep() {
|
|
414
|
+
for (const block of adopted) if (block.isDestroyed) adopted.delete(block);
|
|
407
415
|
if (context.ui.router.current().type !== "session") return;
|
|
408
416
|
const box = transcript();
|
|
409
417
|
if (!box) return;
|
|
@@ -515,8 +523,10 @@ export default {
|
|
|
515
523
|
if (target) {
|
|
516
524
|
const lines = [];
|
|
517
525
|
dumpNode(box ?? context.renderer.root, 0, lines, 600);
|
|
518
|
-
dump = target;
|
|
519
526
|
writeFileSync(target, summary.concat("", lines).join("\n"));
|
|
527
|
+
// Only advertise the path once the write succeeded; the
|
|
528
|
+
// catch below keeps a failed write from taking down diagnose.
|
|
529
|
+
dump = target;
|
|
520
530
|
}
|
|
521
531
|
} catch {}
|
|
522
532
|
context.ui.toast.show({
|
|
@@ -550,6 +560,13 @@ export default {
|
|
|
550
560
|
clearInterval(timer);
|
|
551
561
|
if (pending) clearTimeout(pending);
|
|
552
562
|
for (const off of offs) if (typeof off === "function") off();
|
|
563
|
+
// The host owns these renderables and keeps them after the plugin is
|
|
564
|
+
// disabled, so undo our folds instead of leaving the transcript collapsed.
|
|
565
|
+
for (const block of adopted) {
|
|
566
|
+
const state = known.get(block);
|
|
567
|
+
if (state?.folded) apply(state, false);
|
|
568
|
+
}
|
|
569
|
+
adopted.clear();
|
|
553
570
|
};
|
|
554
571
|
},
|
|
555
572
|
};
|