From 26dcab23aeb635012f68c3e07becf460ca6d8c83 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Fri, 19 Jun 2026 17:54:55 +0200 Subject: [PATCH] =?UTF-8?q?Session=20notes:=20(B)=20`d`=20discard=20a=20hu?= =?UTF-8?q?nk=20done=20(=C2=A721.26)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- focused-main-view-notes.md | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/focused-main-view-notes.md b/focused-main-view-notes.md index 5eadd5f7c..3e32080cf 100644 --- a/focused-main-view-notes.md +++ b/focused-main-view-notes.md @@ -3063,3 +3063,50 @@ reflog would return the same `FocusedMainViewActions` + implement the marker). **NEXT: (B) `d` (discard a hunk)** — different backend per panel (working-tree discard vs patch-building variant); the (A) handler accommodates it (add `DiscardSelection` to `FocusedMainViewActions`). Then (C) `ctrl+o` copy, (D) the pager fallback. + +### 21.26 Session 19 (cont.): (B) `d` — discard a hunk — DONE + +`d` in the focused main view now discards the selection, mirroring each explorer. Committed (most recent +last): + +``` +3719a0412 amend! Generalize FilesController.stageDiffLines to applyDiffLines (prep — folds into 2414f3eab) +19d4b8f66 Discard the selected diff line(s) from the focused main view (B + 2 e2e tests) +``` + +**Prep — `applyDiffLines` generalized.** `stageDiffLines` used one `reverse` flag for *both* "which diff +to read" (it's the `cached` arg of `WorktreeFileDiff`) and "reverse the apply"; that only works because +those coincide for stage/unstage. Working-tree discard breaks it: read the **unstaged** diff (the side +shown), but apply a **reverse, not-cached** patch. So split them — `applyDiffLines(file, infos, +sourceCached, ApplyPatchOpts)`. Found via the failing staging-discard e2e (no lines matched, because it +was reading the empty staged diff). The prep commit as first written had the wrong signature; corrected +in place with an `amend!` so the prep introduces the final shape (per [[clean-history-no-back-and-forth]]). + +**(B) — `DiscardSelection` + disabled reason on `FocusedMainViewActions`** (user picked full +explorer-parity disabled-reason UX over silent-no-op/handler-error). The dispatcher binds `Universal.Remove` +and forwards to the panel beneath; per panel: +- **files** → working-tree discard, mirroring the staging view's `d`: reverse-apply **not cached** on the + unstaged side (destructive → confirm unless `SkipDiscardChangeWarning`), reverse-apply **cached** on the + staged side (= unstage). Always available (zero-context = inline error, like the staging view), so its + `DiscardSelectionDisabledReason` is nil. +- **commit panels** (commitFiles + the whole-commit diff of localCommits/subCommits/stash) → remove the + selected lines from the commit via rebase, mirroring the patch builder's "discard lines from commit": + reset any active patch, build a one-off patch from the selection (reusing `togglePatchLines`), then + `DeletePatchesFromCommit`. Shared free functions `discardSelectionFromCommit` + `discardFromCommitDisabledReason` + in `patch_building_from_main_view.go`, paralleling the toggle. Only rebaseable on a **local branch**, so + the disabled reason greys `d` on stash + other-branch sub-commits (never rebaseable) and mid-rebase — + treated all the same (user OK'd; the "never applicable ⇒ hide entirely" hair isn't worth it). + +**Tests:** `staging/discard_from_main_view` (discard one hunk of a two-hunk working-tree file from the +files main view; the other hunk stays) and `patch_building/discard_lines_from_commit_main_view` (discard +one line from a local commit straight from the commits main view → rebase → commit keeps the other lines). +`build` + `unit` + `lint` + **`e2e-all` all green**. + +**Needs interactive sign-off / carry-forward:** the commit-discard's post-rebase re-render isn't given a +special reveal (the SYNC refresh re-renders; selection lands wherever it falls) — fine for a destructive +op, revisit if it feels off. Files-discard reveals same-pane by ordinal; the rare staged-side-collapse +case (discard-on-staged = unstage, secondary pane empties) isn't special-cased. Reflog `d` no-ops (nil +actions), like its `space`. + +**NEXT: (C) `ctrl+o` (copy parts of a diff to the clipboard)** — supported by every diff panel; add +`CopySelection` to `FocusedMainViewActions`. Then (D) the pager fallback.