Skip to content

Commit 0ddb658

Browse files
authored
Revert "feat: enhance split diff viewer (#40)"
This reverts commit c2b20c1.
1 parent c2b20c1 commit 0ddb658

File tree

2 files changed

+0
-272
lines changed

2 files changed

+0
-272
lines changed

internal/tui/update.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -499,10 +499,6 @@ func (m *Model) updateMainPanel() tea.Cmd {
499499
if content == "" {
500500
content = "Select an item to see details."
501501
}
502-
// Apply adaptive visual styling: split-view for wide terminals, unified for narrow ones
503-
// Calculate right panel width (approximately 65% of total width minus borders)
504-
rightPanelWidth := int(float64(m.width)*(1-leftPanelWidthRatio)) - borderWidth - 2
505-
content = renderAdaptiveDiffView(content, rightPanelWidth, m.theme)
506502
return mainContentUpdatedMsg{content: content}
507503
}
508504
}

internal/tui/view.go

Lines changed: 0 additions & 268 deletions
Original file line numberDiff line numberDiff line change
@@ -19,274 +19,6 @@ func stripAnsi(str string) string {
1919
return ansiRegex.ReplaceAllString(str, "")
2020
}
2121

22-
// diffLineType represents the type of a diff line.
23-
type diffLineType int
24-
25-
const (
26-
lineTypeContext diffLineType = iota
27-
lineTypeAdded
28-
lineTypeRemoved
29-
lineTypeHeader
30-
lineTypeFileHeader
31-
lineTypeHunkHeader
32-
)
33-
34-
// diffRow represents a single row in the structured diff.
35-
type diffRow struct {
36-
lineType diffLineType
37-
oldLine string
38-
newLine string
39-
rawLine string // Original line for fallback
40-
}
41-
42-
// parseDiffStructure transforms a unified diff into structured rows suitable for split-view rendering.
43-
func parseDiffStructure(content string) []diffRow {
44-
lines := strings.Split(content, "\n")
45-
var rows []diffRow
46-
47-
for _, line := range lines {
48-
if len(line) == 0 {
49-
rows = append(rows, diffRow{lineType: lineTypeContext, oldLine: "", newLine: "", rawLine: ""})
50-
continue
51-
}
52-
53-
// Always strip ANSI codes first before any parsing logic
54-
cleanedLine := stripAnsi(line)
55-
56-
if len(cleanedLine) == 0 {
57-
rows = append(rows, diffRow{lineType: lineTypeContext, oldLine: "", newLine: "", rawLine: line})
58-
continue
59-
}
60-
61-
firstChar := cleanedLine[0]
62-
63-
// File headers
64-
if strings.HasPrefix(cleanedLine, "diff --git") ||
65-
strings.HasPrefix(cleanedLine, "index ") {
66-
rows = append(rows, diffRow{lineType: lineTypeFileHeader, rawLine: line})
67-
continue
68-
}
69-
70-
// --- and +++ headers (but not as content)
71-
if strings.HasPrefix(cleanedLine, "---") && len(cleanedLine) > 3 && cleanedLine[3] == ' ' {
72-
rows = append(rows, diffRow{lineType: lineTypeFileHeader, rawLine: line})
73-
continue
74-
}
75-
if strings.HasPrefix(cleanedLine, "+++") && len(cleanedLine) > 3 && cleanedLine[3] == ' ' {
76-
rows = append(rows, diffRow{lineType: lineTypeFileHeader, rawLine: line})
77-
continue
78-
}
79-
80-
// Hunk headers
81-
if strings.HasPrefix(cleanedLine, "@@") {
82-
rows = append(rows, diffRow{lineType: lineTypeHunkHeader, rawLine: line})
83-
continue
84-
}
85-
86-
// Newline marker
87-
if strings.HasPrefix(cleanedLine, "\\ No newline") {
88-
rows = append(rows, diffRow{lineType: lineTypeFileHeader, rawLine: line})
89-
continue
90-
}
91-
92-
// Added lines (but not +++ headers)
93-
if firstChar == '+' {
94-
// Store content without the "+" prefix for rendering
95-
contentWithoutPrefix := cleanedLine[1:]
96-
rows = append(rows, diffRow{lineType: lineTypeAdded, newLine: contentWithoutPrefix, rawLine: line})
97-
continue
98-
}
99-
100-
// Removed lines (but not --- headers)
101-
if firstChar == '-' {
102-
// Store content without the "-" prefix for rendering
103-
contentWithoutPrefix := cleanedLine[1:]
104-
rows = append(rows, diffRow{lineType: lineTypeRemoved, oldLine: contentWithoutPrefix, rawLine: line})
105-
continue
106-
}
107-
108-
// Context lines (start with space)
109-
if firstChar == ' ' {
110-
// Store content without the space prefix
111-
contentWithoutSpace := cleanedLine[1:]
112-
rows = append(rows, diffRow{lineType: lineTypeContext, oldLine: contentWithoutSpace, newLine: contentWithoutSpace, rawLine: line})
113-
continue
114-
}
115-
116-
// Fallback for any other lines
117-
rows = append(rows, diffRow{lineType: lineTypeContext, oldLine: cleanedLine, newLine: cleanedLine, rawLine: line})
118-
}
119-
120-
return rows
121-
}
122-
123-
// renderSplitDiffView renders a GitHub-style split-view diff.
124-
// columnWidth should be roughly half the viewport width minus some padding.
125-
func renderSplitDiffView(rows []diffRow, columnWidth int, theme Theme) string {
126-
if columnWidth < 20 {
127-
// Column too narrow for split view
128-
return ""
129-
}
130-
131-
// Create themed styles
132-
headerStyle := lipgloss.NewStyle().Bold(true)
133-
134-
// Use theme's added/removed colors for backgrounds
135-
addedStyle := theme.GitStaged.
136-
Width(columnWidth).
137-
Padding(0, 1)
138-
139-
removedStyle := theme.GitUnstaged.
140-
Width(columnWidth).
141-
Padding(0, 1)
142-
143-
contextStyle := lipgloss.NewStyle().
144-
Width(columnWidth).
145-
Padding(0, 1)
146-
147-
emptyStyle := lipgloss.NewStyle().
148-
Width(columnWidth).
149-
Padding(0, 1)
150-
151-
var renderedRows []string
152-
153-
for _, row := range rows {
154-
var left, right string
155-
156-
switch row.lineType {
157-
case lineTypeFileHeader:
158-
// File headers span full width
159-
fullLine := headerStyle.Width(columnWidth * 2).Render(row.rawLine)
160-
renderedRows = append(renderedRows, fullLine)
161-
162-
case lineTypeHunkHeader:
163-
// Hunk headers span full width
164-
fullLine := headerStyle.Width(columnWidth * 2).Render(row.rawLine)
165-
renderedRows = append(renderedRows, fullLine)
166-
167-
case lineTypeRemoved:
168-
// Removed line on left (oldLine is already without "-" prefix), empty on right
169-
left = removedStyle.Render(row.oldLine)
170-
right = emptyStyle.Render("")
171-
renderedRows = append(renderedRows, lipgloss.JoinHorizontal(lipgloss.Top, left, right))
172-
173-
case lineTypeAdded:
174-
// Empty on left, added line on right (newLine is already without "+" prefix)
175-
left = emptyStyle.Render("")
176-
right = addedStyle.Render(row.newLine)
177-
renderedRows = append(renderedRows, lipgloss.JoinHorizontal(lipgloss.Top, left, right))
178-
179-
case lineTypeContext:
180-
// Context lines on both sides (oldLine and newLine are already without space prefix and identical)
181-
left = contextStyle.Render(row.oldLine)
182-
right = contextStyle.Render(row.newLine)
183-
renderedRows = append(renderedRows, lipgloss.JoinHorizontal(lipgloss.Top, left, right))
184-
185-
default:
186-
// Fallback: show on both sides
187-
left = contextStyle.Render(row.oldLine)
188-
right = contextStyle.Render(row.newLine)
189-
renderedRows = append(renderedRows, lipgloss.JoinHorizontal(lipgloss.Top, left, right))
190-
}
191-
}
192-
193-
return strings.Join(renderedRows, "\n")
194-
}
195-
196-
// renderAdaptiveDiffView returns the appropriately formatted diff based on viewport width.
197-
// If width >= 80, uses split-view; otherwise falls back to unified diff.
198-
func renderAdaptiveDiffView(content string, width int, theme Theme) string {
199-
// Quick check: if content doesn't look like a diff, return as-is
200-
if !strings.Contains(content, "diff --git") && !strings.Contains(content, "@@") {
201-
return content
202-
}
203-
204-
// Threshold for split-view: 80 chars available
205-
const splitViewThreshold = 80
206-
207-
if width >= splitViewThreshold && width > 60 {
208-
// Use split-view mode
209-
columnWidth := (width - 1) / 2
210-
rows := parseDiffStructure(content)
211-
splitView := renderSplitDiffView(rows, columnWidth, theme)
212-
if splitView != "" {
213-
return splitView
214-
}
215-
}
216-
217-
// Fallback to unified diff styling
218-
return styleDiffContent(content, theme)
219-
}
220-
221-
// styleDiffContent applies visual highlighting to diff lines for better readability.
222-
// It detects and styles:
223-
// - Diff headers (diff --git, index, ---, +++, @@) with bold magenta
224-
// - Added lines (+) with green
225-
// - Removed lines (-) with red
226-
// - Context lines with normal or dimmed styling
227-
// It also adds visual separation before hunk markers for improved scanability.
228-
func styleDiffContent(content string, theme Theme) string {
229-
// Quick check: if content doesn't look like a diff, return as-is
230-
if !strings.Contains(content, "diff --git") && !strings.Contains(content, "@@") {
231-
return content
232-
}
233-
234-
lines := strings.Split(content, "\n")
235-
236-
// Create styles for different diff elements
237-
headerStyle := lipgloss.NewStyle().Bold(true)
238-
239-
// Use theme colors for added/removed lines (aligns with git status colors)
240-
addedStyle := theme.GitStaged // Green
241-
removedStyle := theme.GitUnstaged // Red
242-
243-
var result []string
244-
for i, line := range lines {
245-
if len(line) == 0 {
246-
result = append(result, line)
247-
continue
248-
}
249-
250-
// Strip ANSI codes before checking prefixes
251-
cleanedLine := stripAnsi(line)
252-
253-
if len(cleanedLine) == 0 {
254-
result = append(result, line)
255-
continue
256-
}
257-
258-
firstChar := cleanedLine[0]
259-
260-
// Add spacing before hunk markers (visual separation of hunks)
261-
if strings.HasPrefix(cleanedLine, "@@") && i > 0 && result[len(result)-1] != "" {
262-
result = append(result, "") // Add blank line for visual separation
263-
}
264-
265-
// Handle diff headers
266-
if strings.HasPrefix(cleanedLine, "diff --git") ||
267-
strings.HasPrefix(cleanedLine, "index ") ||
268-
strings.HasPrefix(cleanedLine, "---") ||
269-
strings.HasPrefix(cleanedLine, "+++") ||
270-
strings.HasPrefix(cleanedLine, "@@") {
271-
result = append(result, headerStyle.Render(line))
272-
} else if firstChar == '+' && !strings.HasPrefix(cleanedLine, "+++") {
273-
// Added line: apply green styling
274-
result = append(result, addedStyle.Render(line))
275-
} else if firstChar == '-' && !strings.HasPrefix(cleanedLine, "---") {
276-
// Removed line: apply red styling
277-
result = append(result, removedStyle.Render(line))
278-
} else if firstChar == '\\' {
279-
// "\ No newline at end of file" marker - treat as metadata
280-
result = append(result, headerStyle.Render(line))
281-
} else {
282-
// Context line (starts with space) - keep as-is
283-
result = append(result, line)
284-
}
285-
}
286-
287-
return strings.Join(result, "\n")
288-
}
289-
29022
// View is the main render function for the application.
29123
func (m Model) View() string {
29224

0 commit comments

Comments
 (0)