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

claude-code / mods / diff / hooks / views / body / draw-window.tsx
104 lines · 2.9 KBRaw
1/* @jsxRuntime classic */
2/* @jsx h */
3/* @jsxFrag Fragment */
4import type { RenderElement } from 'claude-code'
5
6import Limits from '../../limits'
7import Detail from '../detail'
8import type { Kit } from '../kit'
9import Layout from '../layout'
10import Sections from '../sections'
11import Plan from './plan'
12import type { BodyLayout, HunkSegment, Segment, WindowCut } from './types'
13
14/**
15 * The rows of the docked body its window shows from a row down: each
16 * segment drawn from the row the window cuts it at, until the window fills.
17 *
18 * A hunk draws only its lines in view, and past MAX_BODY_CHARS of hunk
19 * text the rest waits for a scroll (the tree's cap); rows past the foot
20 * are the pane's to clip, so SCROLL_MARGIN_ROWS more are drawn than fit.
21 *
22 * @param kit the elements, the handlers, the width
23 * @param layout the body laid out
24 * @param top the body row wanted at the window's top; clamped to the body
25 * @returns the elements, top to bottom
26 */
27export function drawWindow(
28 kit: Kit,
29 layout: BodyLayout,
30 top: number,
31): RenderElement[] {
32 const { Box, Text, Code } = kit.ui
33 const drawn: RenderElement[] = []
34 const wanted = layout.visibleRows + Limits.SCROLL_MARGIN_ROWS
35 const at = Math.max(0, Math.min(top, layout.maxTop))
36 const onPress = kit.actions.togglePreSession
37
38 let start = 0
39 let filled = 0
40 let chars = 0
41
42 function codeOf(segment: HunkSegment, cut: WindowCut): RenderElement {
43 const source = Detail.hunkSourceOf(Plan.hunkWindowOf(segment, cut))
44 const path = Layout.sanitizeName(segment.path)
45 chars += source.length
46
47 const isOver = chars > Detail.MAX_BODY_CHARS
48
49 return isOver ? (
50 <Text dimColor italic>
51 …
52 </Text>
53 ) : (
54 <Code source={source} format="diff" path={path} />
55 )
56 }
57
58 function elementOf(segment: Segment, cut: WindowCut): RenderElement {
59 switch (segment.kind) {
60 case 'rule':
61 return Sections.divider(kit)
62 case 'blank':
63 return <Box height={1} />
64 case 'name':
65 return Sections.nameRow(kit, segment.name)
66 case 'hunk':
67 return codeOf(segment, cut)
68 case 'note':
69 return (
70 <Text dimColor italic wrap="wrap">
71 {segment.text}
72 </Text>
73 )
74 case 'footer':
75 return (
76 <Text dimColor italic>
77 … diff truncated (exceeded 400 line limit)
78 </Text>
79 )
80 case 'text':
81 return Sections.dimNote(kit, segment.text)
82 case 'toggle':
83 return Sections.toggleRow(kit, 'presession', { ...segment, onPress })
84 case 'legend':
85 return Sections.legendRow(kit, segment.entry)
86 }
87 }
88
89 for (const segment of layout.segments) {
90 const rows = Plan.segmentRowsOf(segment)
91 const isShown = start + rows > at && filled < wanted
92
93 if (isShown) {
94 const skip = Math.max(0, at - start)
95
96 drawn.push(elementOf(segment, { skip, take: wanted - filled }))
97 filled += rows - skip
98 }
99
100 start += rows
101 }
102
103 return drawn
104}