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

mods/diff: each decision a hook makes names its test, and a value used once is written where it is usedBrowse files
poteat authored on Sep 11, 2026 parent a9d339b · commit 46ea2a528de7
14 changed files+97 -76compared with a9d339b
Mmods/diff/hooks/git/probes/untracked-files/untracked-files.ts
Mmods/diff/hooks/git/tiers/with-untracked/with-untracked.ts
Mmods/diff/hooks/pane-toggle/pane-toggle-of.ts
Mmods/diff/hooks/register.ts
Mmods/diff/hooks/views/current-pane/current-pane.tsx
Amods/diff/hooks/views/current-pane/message-pane-of/foot-rows/foot-rows.ts
Amods/diff/hooks/views/current-pane/message-pane-of/foot-rows/index.ts
Mmods/diff/hooks/views/current-pane/message-pane-of/index.ts
Amods/diff/hooks/views/current-pane/message-pane-of/message-pane/index.ts
Amods/diff/hooks/views/current-pane/message-pane-of/message-pane/message-pane.ts
Mmods/diff/hooks/views/current-pane/message-pane-of/message-pane-of.tsx
Mmods/diff/hooks/views/layout/wrapped-lines/wrapped-lines.ts
Mmods/diff/hooks/views/sections/controls-view.tsx
Mmods/diff/hooks/views/sections/header-view.tsx
@@ -30,11 +30,11 @@
3030 '--full-name',
3131 ])
3232
33- if (!Parse.isWholeAnswer(listing)) {
34- return null
35- }
36-
37- const paths = listing.stdout.split('\0').filter(path => path !== '')
38-
39- return untrackedRowsOf(context, paths, place)
33+ return Parse.isWholeAnswer(listing)
34+ ? untrackedRowsOf(
35+ context,
36+ listing.stdout.split('\0').filter(path => path !== ''),
37+ place,
38+ )
39+ : null
4040 }
@@ -22,15 +22,13 @@
2222 result: Types.NumstatResult,
2323 scope: Types.UntrackedScope,
2424 ): Promise<Types.MergedResult> {
25- if (isPastDetails(result)) {
26- return mergedResultOf(result, { isUntrackedWithheld: false })
27- }
28-
29- return mergedWithUntracked(
30- result,
31- await Probes.untrackedFiles(context, {
32- slots: Limits.MAX_FILES - result.files.length,
33- scope,
34- }),
35- )
25+ return isPastDetails(result)
26+ ? mergedResultOf(result, { isUntrackedWithheld: false })
27+ : mergedWithUntracked(
28+ result,
29+ await Probes.untrackedFiles(context, {
30+ slots: Limits.MAX_FILES - result.files.length,
31+ scope,
32+ }),
33+ )
3634 }
@@ -12,11 +12,12 @@
1212 * @param pane the plugin's belief, the probe's answer and the width
1313 * @returns `close`, `open` or `too-narrow`
1414 */
15-export const paneToggleOf = (
15+export function paneToggleOf(
1616 pane: PaneBelief,
17-): 'open' | 'close' | 'too-narrow' =>
18- pane.isBelievedOpen && pane.wasDrawnWhenProbed
19- ? 'close'
20- : pane.columns !== null && pane.columns < Limits.OPEN_MIN_COLUMNS
21- ? 'too-narrow'
22- : 'open'
17+): 'open' | 'close' | 'too-narrow' {
18+ const isClosing = pane.isBelievedOpen && pane.wasDrawnWhenProbed
19+ const isTooNarrow =
20+ pane.columns !== null && pane.columns < Limits.OPEN_MIN_COLUMNS
21+
22+ return isClosing ? 'close' : isTooNarrow ? 'too-narrow' : 'open'
23+}
@@ -595,10 +595,10 @@
595595 }
596596
597597 const context = e.context ?? []
598- const used = context.reduce((sum, entry) => sum + entry.length, 0)
599598 const text = Ask.fittedAskTextOf(
600599 asked.text,
601- Limits.PROMPT_CONTEXT_MAX_CHARS - used,
600+ Limits.PROMPT_CONTEXT_MAX_CHARS -
601+ context.reduce((sum, entry) => sum + entry.length, 0),
602602 )
603603
604604 if (text === undefined) {
@@ -89,10 +89,10 @@
8989 })
9090 : null
9191 const earlierFiles = model.isPreSessionShown ? partition.preSession : []
92- const earlierRows =
93- earlierFiles.length === 0
94- ? []
95- : [<Box height={1} />, ...earlierFiles.map(rowOf)]
92+ const isEarlierListed = earlierFiles.length > 0
93+ const earlierRows = isEarlierListed
94+ ? [<Box height={1} />, ...earlierFiles.map(rowOf)]
95+ : []
9696 const isUntrackedNoted = data?.isUntrackedWithheld === true && !empty
9797 const listed = listBodyOf(kit, { data, partition, totals, empty })
9898 const notes = listed.filter(line => typeof line === 'string')
@@ -125,8 +125,10 @@
125125 ]
126126 : []
127127
128- if (message.length > 0) {
129- return messagePaneOf(kit, {
128+ const isMessageShown = message.length > 0
129+
130+ return isMessageShown ? (
131+ messagePaneOf(kit, {
130132 top: Sections.present([
131133 header,
132134 noteOf(baseLabel),
@@ -140,9 +142,7 @@
140142 earlier: earlierToggle,
141143 rest: [...earlierRows, ...detail],
142144 })
143- }
144-
145- return (
145+ ) : (
146146 <Box flexDirection="column">
147147 {Sections.present([
148148 header,
@@ -1,0 +1,5 @@
1+/**
2+ * The rows the pre-session line takes at the pane's foot: a blank row, the
3+ * line, and a blank row under it.
4+ */
5+export const FOOT_ROWS = 3
@@ -1,0 +1,3 @@
1+export * from './foot-rows.js'
2+
3+export * as default from '.'
@@ -1,3 +1,5 @@
1+export * from './foot-rows'
2+export * from './message-pane'
13 export * from './message-pane-of.jsx'
24
35 export * as default from '.'
@@ -1,0 +1,3 @@
1+export type * from './message-pane.js'
2+
3+export * as default from '.'
@@ -1,0 +1,13 @@
1+import type { RenderElement } from 'claude-code'
2+
3+/**
4+ * What stands around a message in the pane: the header block, the message,
5+ * the pickers, the pre-session line, and what is listed under it.
6+ */
7+export type MessagePane = {
8+ top: readonly RenderElement[]
9+ message: readonly string[]
10+ controls: RenderElement | null
11+ earlier: RenderElement | null
12+ rest: readonly RenderElement[]
13+}
@@ -5,6 +5,8 @@
55
66 import type { Kit } from '../../kit'
77 import Layout from '../../layout'
8+import { FOOT_ROWS } from './foot-rows'
9+import type { MessagePane } from './message-pane'
810
911 /**
1012 * The pane while a message stands in for the list (ReplDiffSidebar's
@@ -19,16 +21,7 @@
1921 * pre-session line, and what is listed under it
2022 * @returns the pane's tree
2123 */
22-export function messagePaneOf(
23- kit: Kit,
24- pane: {
25- top: readonly RenderElement[]
26- message: readonly string[]
27- controls: RenderElement | null
28- earlier: RenderElement | null
29- rest: readonly RenderElement[]
30- },
31-): RenderElement {
24+export function messagePaneOf(kit: Kit, pane: MessagePane): RenderElement {
3225 const { Box, Text } = kit.ui
3326 const { top, controls, earlier, rest } = pane
3427 const lines = pane.message.flatMap(text =>
@@ -37,11 +30,13 @@
3730 const drawn = lines.map(line => <Text dimColor>{line}</Text>)
3831 const controlRows = controls === null ? [] : [controls]
3932 const earlierRows = earlier === null ? [] : [earlier]
40- const aboveEarlier =
33+ const isControlsAboveEarlier =
4134 controlRows.length > 0 || earlierRows.length === 0
42- ? controlRows
43- : [<Box height={1} />]
44- const middleRows = kit.rows - top.length - 1 - (earlier === null ? 0 : 3)
35+ const aboveEarlier = isControlsAboveEarlier
36+ ? controlRows
37+ : [<Box height={1} />]
38+ const footRows = earlier === null ? 0 : FOOT_ROWS
39+ const middleRows = kit.rows - top.length - 1 - footRows
4540 const above = Math.floor((middleRows - lines.length) / 2)
4641 const isCentered =
4742 rest.length === 0 && middleRows - above - lines.length >= controlRows.length
@@ -33,9 +33,8 @@
3333 if (wordWidth > width) {
3434 const breaksHere =
3535 1 + Math.floor((wordWidth - (width - rowWidth) - 1) / width)
36- const breaksNext = Math.floor((wordWidth - 1) / width)
3736
38- if (breaksNext < breaksHere) {
37+ if (Math.floor((wordWidth - 1) / width) < breaksHere) {
3938 rows.push('')
4039 }
4140
@@ -46,23 +46,23 @@
4646 ) : null
4747 const isCurrent = source.kind === 'current'
4848 const fetchedSource = model.data?.source
49- const base =
50- fetchedSource?.kind === 'working-tree'
51- ? fetchedSource.base
52- : model.words.base
49+ const isWorkingTree = fetchedSource?.kind === 'working-tree'
50+ const base = isWorkingTree ? fetchedSource.base : model.words.base
5351 const basePicker = isCurrent ? (
5452 <Select
5553 key="base"
5654 label="base"
57- options={model.baseModes.map(mode => ({
58- value: mode,
59- label:
60- mode === 'uncommitted'
61- ? `uncommitted (vs ${base})`
62- : mode === 'session'
63- ? 'this session'
64- : mode,
65- }))}
55+ options={model.baseModes.map(mode => {
56+ const isUncommitted = mode === 'uncommitted'
57+ const isSession = mode === 'session'
58+ const label = isUncommitted
59+ ? `uncommitted (vs ${base})`
60+ : isSession
61+ ? 'this session'
62+ : mode
63+
64+ return { value: mode, label }
65+ })}
6666 value={model.requestedMode}
6767 onSelect={value => kit.actions.chooseBase(value)}
6868 />
@@ -24,20 +24,22 @@
2424 totals: PaneState.HeaderTotals | null,
2525 ): RenderElement {
2626 const { Box, Text } = kit.ui
27- const counts =
28- totals === null
29- ? []
30- : [
31- <Text wrap="truncate-end">
32- <Text bold>{Layout.plural(totals.filesCount, 'file')}</Text>
33- {' changed '}
34- {diffStat(kit, totals.linesAdded, totals.linesRemoved)}
35- </Text>,
36- ]
3727
3828 return (
3929 <Box flexDirection="row">
40- {[...counts, <Box flexGrow={1} />, closeButton(kit)]}
30+ {[
31+ ...(totals
32+ ? [
33+ <Text wrap="truncate-end">
34+ <Text bold>{Layout.plural(totals.filesCount, 'file')}</Text>
35+ {' changed '}
36+ {diffStat(kit, totals.linesAdded, totals.linesRemoved)}
37+ </Text>,
38+ ]
39+ : []),
40+ <Box flexGrow={1} />,
41+ closeButton(kit),
42+ ]}
4143 </Box>
4244 )
4345 }