spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

diff: the dialog's walk stops at the first and last file as the built-in's does, where the ring would wrapBrowse files
poteat authored on Sep 13, 2026 parent 78c94ce · commit 17db2e1954fc
2 changed files+26 -8compared with 78c94ce
Mmods/diff/hooks/register.ts
Mmods/diff/hooks/views/dialog-pane/dialog-focus-of.ts
@@ -729,6 +729,10 @@
729729
730730 const focus = isListed ? Views.dialogFocusOf(model, e.element) : null
731731
732+ if (focus === 'stay') {
733+ return {}
734+ }
735+
732736 if (!focus || !host) {
733737 return next(e)
734738 }
@@ -1,3 +1,4 @@
1+import Limits from '../../limits'
12 import type PaneState from '../../pane-state'
23 import Sections from '../sections'
34 import { dialogEntriesOf } from './dialog-entries-of'
@@ -7,26 +8,39 @@
78 * What the focus ring landing on a dialog row makes of the list: that file
89 * selected, the window re-centred, the key of the row drawn where it sits.
910 *
10- * DiffFileList's selection. The engine keeps its ring by position, so the
11- * ring is sent to the row that holds the selected file's place once the
12- * window has moved; null for a key that is none of the listed rows'.
11+ * DiffFileList's selection, which stops at an end where the ring wraps: a
12+ * jump across three or more rows from the first or last file is `stay`.
13+ * The ring goes to the row holding the file's place after the re-centre.
1314 *
1415 * @param model the pane's state
1516 * @param element the key of the element taking the ring
16- * @returns the selected path and the key to land the ring on, or null
17+ * @returns the selection and the key to land on, `stay`, or null for a key
18+ * that is none of the listed rows'
1719 */
1820 export function dialogFocusOf(
1921 model: PaneState.PaneModel,
2022 element: string | undefined,
21-): PaneState.DialogFocus | null {
23+): PaneState.DialogFocus | 'stay' | null {
2224 const entries = dialogEntriesOf(model)
2325 const paths = entries.map(entry => entry.path)
2426 const keys = entries.map(entry => Sections.fileKeyOf(entry))
2527 const picked = keys.indexOf(element ?? '')
28+ const current = Math.max(0, paths.indexOf(model.selectedPath ?? ''))
29+ const before = dialogWindowOf(model, paths)
30+
31+ const lastDrawn =
32+ Math.min(paths.length, before + Limits.MAX_VISIBLE_FILES) - 1
33+
2634 const selectedPath = paths[picked] ?? null
27- const after = dialogWindowOf({ selectedPath }, paths)
28- const landing = keys[dialogWindowOf(model, paths) + picked - after]
35+
36+ const landing =
37+ keys[before + picked - dialogWindowOf({ selectedPath }, paths)]
38+
39+ const isOverStart = current === 0 && picked === lastDrawn
40+ const isOverEnd = current === paths.length - 1 && picked === before
41+ const isFar = lastDrawn - before >= 2
2942 const isRow = selectedPath !== null && landing !== undefined
43+ const isWrap = isFar && (isOverEnd || isOverStart)
3044
31- return isRow ? { selectedPath, landing } : null
45+ return isWrap ? 'stay' : isRow ? { selectedPath, landing } : null
3246 }