fix segment diff and add new theme

Kujtim Hoxha created

Change summary

internal/diff/diff.go | 523 +++++++++++++++++++++++++++++---------------
1 file changed, 348 insertions(+), 175 deletions(-)

Detailed changes

internal/diff/diff.go 🔗

@@ -22,89 +22,95 @@ import (
 	"github.com/sergi/go-diff/diffmatchpatch"
 )
 
+// -------------------------------------------------------------------------
+// Core Types
+// -------------------------------------------------------------------------
+
 // LineType represents the kind of line in a diff.
 type LineType int
 
 const (
-	// LineContext represents a line that exists in both the old and new file.
-	LineContext LineType = iota
-	// LineAdded represents a line added in the new file.
-	LineAdded
-	// LineRemoved represents a line removed from the old file.
-	LineRemoved
+	LineContext LineType = iota // Line exists in both files
+	LineAdded                   // Line added in the new file
+	LineRemoved                 // Line removed from the old file
 )
 
-// DiffLine represents a single line in a diff, either from the old file,
-// the new file, or a context line.
+// Segment represents a portion of a line for intra-line highlighting
+type Segment struct {
+	Start int
+	End   int
+	Type  LineType
+	Text  string
+}
+
+// DiffLine represents a single line in a diff
 type DiffLine struct {
-	OldLineNo int      // Line number in the old file (0 for added lines)
-	NewLineNo int      // Line number in the new file (0 for removed lines)
-	Kind      LineType // Type of line (added, removed, context)
-	Content   string   // Content of the line
+	OldLineNo int       // Line number in old file (0 for added lines)
+	NewLineNo int       // Line number in new file (0 for removed lines)
+	Kind      LineType  // Type of line (added, removed, context)
+	Content   string    // Content of the line
+	Segments  []Segment // Segments for intraline highlighting
 }
 
-// Hunk represents a section of changes in a diff.
+// Hunk represents a section of changes in a diff
 type Hunk struct {
 	Header string
 	Lines  []DiffLine
 }
 
-// DiffResult contains the parsed result of a diff.
+// DiffResult contains the parsed result of a diff
 type DiffResult struct {
 	OldFile string
 	NewFile string
 	Hunks   []Hunk
 }
 
-// HunkDelta represents the change statistics for a hunk.
-type HunkDelta struct {
-	StartLine1 int
-	LineCount1 int
-	StartLine2 int
-	LineCount2 int
-}
-
-// linePair represents a pair of lines to be displayed side by side.
+// linePair represents a pair of lines for side-by-side display
 type linePair struct {
 	left  *DiffLine
 	right *DiffLine
 }
 
 // -------------------------------------------------------------------------
-// Style Configuration with Option Pattern
+// Style Configuration
 // -------------------------------------------------------------------------
 
-// StyleConfig defines styling for diff rendering.
+// StyleConfig defines styling for diff rendering
 type StyleConfig struct {
+	// Background colors
 	RemovedLineBg       lipgloss.Color
 	AddedLineBg         lipgloss.Color
 	ContextLineBg       lipgloss.Color
 	HunkLineBg          lipgloss.Color
-	HunkLineFg          lipgloss.Color
-	RemovedFg           lipgloss.Color
-	AddedFg             lipgloss.Color
-	LineNumberFg        lipgloss.Color
-	HighlightStyle      string
-	RemovedHighlightBg  lipgloss.Color
-	AddedHighlightBg    lipgloss.Color
 	RemovedLineNumberBg lipgloss.Color
 	AddedLineNamerBg    lipgloss.Color
-	RemovedHighlightFg  lipgloss.Color
-	AddedHighlightFg    lipgloss.Color
+
+	// Foreground colors
+	HunkLineFg         lipgloss.Color
+	RemovedFg          lipgloss.Color
+	AddedFg            lipgloss.Color
+	LineNumberFg       lipgloss.Color
+	RemovedHighlightFg lipgloss.Color
+	AddedHighlightFg   lipgloss.Color
+
+	// Highlight settings
+	HighlightStyle     string
+	RemovedHighlightBg lipgloss.Color
+	AddedHighlightBg   lipgloss.Color
 }
 
-// StyleOption defines a function that modifies a StyleConfig.
+// StyleOption is a function that modifies a StyleConfig
 type StyleOption func(*StyleConfig)
 
-// NewStyleConfig creates a StyleConfig with default values and applies any provided options.
+// NewStyleConfig creates a StyleConfig with default values
 func NewStyleConfig(opts ...StyleOption) StyleConfig {
-	// Set default values
+	// Default color scheme
 	config := StyleConfig{
 		RemovedLineBg:       lipgloss.Color("#3A3030"),
 		AddedLineBg:         lipgloss.Color("#303A30"),
 		ContextLineBg:       lipgloss.Color("#212121"),
-		HunkLineBg:          lipgloss.Color("#2A2822"),
-		HunkLineFg:          lipgloss.Color("#D4AF37"),
+		HunkLineBg:          lipgloss.Color("#23252D"),
+		HunkLineFg:          lipgloss.Color("#8CA3B4"),
 		RemovedFg:           lipgloss.Color("#7C4444"),
 		AddedFg:             lipgloss.Color("#478247"),
 		LineNumberFg:        lipgloss.Color("#888888"),
@@ -125,56 +131,35 @@ func NewStyleConfig(opts ...StyleOption) StyleConfig {
 	return config
 }
 
-// WithRemovedLineBg sets the background color for removed lines.
+// Style option functions
 func WithRemovedLineBg(color lipgloss.Color) StyleOption {
-	return func(s *StyleConfig) {
-		s.RemovedLineBg = color
-	}
+	return func(s *StyleConfig) { s.RemovedLineBg = color }
 }
 
-// WithAddedLineBg sets the background color for added lines.
 func WithAddedLineBg(color lipgloss.Color) StyleOption {
-	return func(s *StyleConfig) {
-		s.AddedLineBg = color
-	}
+	return func(s *StyleConfig) { s.AddedLineBg = color }
 }
 
-// WithContextLineBg sets the background color for context lines.
 func WithContextLineBg(color lipgloss.Color) StyleOption {
-	return func(s *StyleConfig) {
-		s.ContextLineBg = color
-	}
+	return func(s *StyleConfig) { s.ContextLineBg = color }
 }
 
-// WithRemovedFg sets the foreground color for removed line markers.
 func WithRemovedFg(color lipgloss.Color) StyleOption {
-	return func(s *StyleConfig) {
-		s.RemovedFg = color
-	}
+	return func(s *StyleConfig) { s.RemovedFg = color }
 }
 
-// WithAddedFg sets the foreground color for added line markers.
 func WithAddedFg(color lipgloss.Color) StyleOption {
-	return func(s *StyleConfig) {
-		s.AddedFg = color
-	}
+	return func(s *StyleConfig) { s.AddedFg = color }
 }
 
-// WithLineNumberFg sets the foreground color for line numbers.
 func WithLineNumberFg(color lipgloss.Color) StyleOption {
-	return func(s *StyleConfig) {
-		s.LineNumberFg = color
-	}
+	return func(s *StyleConfig) { s.LineNumberFg = color }
 }
 
-// WithHighlightStyle sets the syntax highlighting style.
 func WithHighlightStyle(style string) StyleOption {
-	return func(s *StyleConfig) {
-		s.HighlightStyle = style
-	}
+	return func(s *StyleConfig) { s.HighlightStyle = style }
 }
 
-// WithRemovedHighlightColors sets the colors for highlighted parts in removed text.
 func WithRemovedHighlightColors(bg, fg lipgloss.Color) StyleOption {
 	return func(s *StyleConfig) {
 		s.RemovedHighlightBg = bg
@@ -182,7 +167,6 @@ func WithRemovedHighlightColors(bg, fg lipgloss.Color) StyleOption {
 	}
 }
 
-// WithAddedHighlightColors sets the colors for highlighted parts in added text.
 func WithAddedHighlightColors(bg, fg lipgloss.Color) StyleOption {
 	return func(s *StyleConfig) {
 		s.AddedHighlightBg = bg
@@ -190,45 +174,35 @@ func WithAddedHighlightColors(bg, fg lipgloss.Color) StyleOption {
 	}
 }
 
-// WithRemovedLineNumberBg sets the background color for removed line numbers.
 func WithRemovedLineNumberBg(color lipgloss.Color) StyleOption {
-	return func(s *StyleConfig) {
-		s.RemovedLineNumberBg = color
-	}
+	return func(s *StyleConfig) { s.RemovedLineNumberBg = color }
 }
 
-// WithAddedLineNumberBg sets the background color for added line numbers.
 func WithAddedLineNumberBg(color lipgloss.Color) StyleOption {
-	return func(s *StyleConfig) {
-		s.AddedLineNamerBg = color
-	}
+	return func(s *StyleConfig) { s.AddedLineNamerBg = color }
 }
 
 func WithHunkLineBg(color lipgloss.Color) StyleOption {
-	return func(s *StyleConfig) {
-		s.HunkLineBg = color
-	}
+	return func(s *StyleConfig) { s.HunkLineBg = color }
 }
 
 func WithHunkLineFg(color lipgloss.Color) StyleOption {
-	return func(s *StyleConfig) {
-		s.HunkLineFg = color
-	}
+	return func(s *StyleConfig) { s.HunkLineFg = color }
 }
 
 // -------------------------------------------------------------------------
-// Parse Options with Option Pattern
+// Parse Configuration
 // -------------------------------------------------------------------------
 
-// ParseConfig configures the behavior of diff parsing.
+// ParseConfig configures the behavior of diff parsing
 type ParseConfig struct {
 	ContextSize int // Number of context lines to include
 }
 
-// ParseOption defines a function that modifies a ParseConfig.
+// ParseOption modifies a ParseConfig
 type ParseOption func(*ParseConfig)
 
-// WithContextSize sets the number of context lines to include.
+// WithContextSize sets the number of context lines to include
 func WithContextSize(size int) ParseOption {
 	return func(p *ParseConfig) {
 		if size >= 0 {
@@ -238,27 +212,25 @@ func WithContextSize(size int) ParseOption {
 }
 
 // -------------------------------------------------------------------------
-// Side-by-Side Options with Option Pattern
+// Side-by-Side Configuration
 // -------------------------------------------------------------------------
 
-// SideBySideConfig configures the rendering of side-by-side diffs.
+// SideBySideConfig configures the rendering of side-by-side diffs
 type SideBySideConfig struct {
 	TotalWidth int
 	Style      StyleConfig
 }
 
-// SideBySideOption defines a function that modifies a SideBySideConfig.
+// SideBySideOption modifies a SideBySideConfig
 type SideBySideOption func(*SideBySideConfig)
 
-// NewSideBySideConfig creates a SideBySideConfig with default values and applies any provided options.
+// NewSideBySideConfig creates a SideBySideConfig with default values
 func NewSideBySideConfig(opts ...SideBySideOption) SideBySideConfig {
-	// Set default values
 	config := SideBySideConfig{
 		TotalWidth: 160, // Default width for side-by-side view
 		Style:      NewStyleConfig(),
 	}
 
-	// Apply all provided options
 	for _, opt := range opts {
 		opt(&config)
 	}
@@ -266,7 +238,7 @@ func NewSideBySideConfig(opts ...SideBySideOption) SideBySideConfig {
 	return config
 }
 
-// WithTotalWidth sets the total width for side-by-side view.
+// WithTotalWidth sets the total width for side-by-side view
 func WithTotalWidth(width int) SideBySideOption {
 	return func(s *SideBySideConfig) {
 		if width > 0 {
@@ -275,14 +247,14 @@ func WithTotalWidth(width int) SideBySideOption {
 	}
 }
 
-// WithStyle sets the styling configuration.
+// WithStyle sets the styling configuration
 func WithStyle(style StyleConfig) SideBySideOption {
 	return func(s *SideBySideConfig) {
 		s.Style = style
 	}
 }
 
-// WithStyleOptions applies the specified style options.
+// WithStyleOptions applies the specified style options
 func WithStyleOptions(opts ...StyleOption) SideBySideOption {
 	return func(s *SideBySideConfig) {
 		s.Style = NewStyleConfig(opts...)
@@ -290,10 +262,10 @@ func WithStyleOptions(opts ...StyleOption) SideBySideOption {
 }
 
 // -------------------------------------------------------------------------
-// Diff Parsing and Generation
+// Diff Parsing
 // -------------------------------------------------------------------------
 
-// ParseUnifiedDiff parses a unified diff format string into structured data.
+// ParseUnifiedDiff parses a unified diff format string into structured data
 func ParseUnifiedDiff(diff string) (DiffResult, error) {
 	var result DiffResult
 	var currentHunk *Hunk
@@ -305,7 +277,7 @@ func ParseUnifiedDiff(diff string) (DiffResult, error) {
 	inFileHeader := true
 
 	for _, line := range lines {
-		// Parse the file headers
+		// Parse file headers
 		if inFileHeader {
 			if strings.HasPrefix(line, "--- a/") {
 				result.OldFile = strings.TrimPrefix(line, "--- a/")
@@ -332,27 +304,27 @@ func ParseUnifiedDiff(diff string) (DiffResult, error) {
 			newStart, _ := strconv.Atoi(matches[3])
 			oldLine = oldStart
 			newLine = newStart
-
 			continue
 		}
 
-		// ignore the \\ No newline at end of file
+		// Ignore "No newline at end of file" markers
 		if strings.HasPrefix(line, "\\ No newline at end of file") {
 			continue
 		}
+
 		if currentHunk == nil {
 			continue
 		}
 
+		// Process the line based on its prefix
 		if len(line) > 0 {
-			// Process the line based on its prefix
 			switch line[0] {
 			case '+':
 				currentHunk.Lines = append(currentHunk.Lines, DiffLine{
 					OldLineNo: 0,
 					NewLineNo: newLine,
 					Kind:      LineAdded,
-					Content:   line[1:], // skip '+'
+					Content:   line[1:],
 				})
 				newLine++
 			case '-':
@@ -360,7 +332,7 @@ func ParseUnifiedDiff(diff string) (DiffResult, error) {
 					OldLineNo: oldLine,
 					NewLineNo: 0,
 					Kind:      LineRemoved,
-					Content:   line[1:], // skip '-'
+					Content:   line[1:],
 				})
 				oldLine++
 			default:
@@ -394,14 +366,13 @@ func ParseUnifiedDiff(diff string) (DiffResult, error) {
 	return result, nil
 }
 
-// HighlightIntralineChanges updates the content of lines in a hunk to show
-// character-level differences within lines.
+// HighlightIntralineChanges updates lines in a hunk to show character-level differences
 func HighlightIntralineChanges(h *Hunk, style StyleConfig) {
 	var updated []DiffLine
 	dmp := diffmatchpatch.New()
 
 	for i := 0; i < len(h.Lines); i++ {
-		// Look for removed line followed by added line, which might have similar content
+		// Look for removed line followed by added line
 		if i+1 < len(h.Lines) &&
 			h.Lines[i].Kind == LineRemoved &&
 			h.Lines[i+1].Kind == LineAdded {
@@ -411,12 +382,40 @@ func HighlightIntralineChanges(h *Hunk, style StyleConfig) {
 
 			// Find character-level differences
 			patches := dmp.DiffMain(oldLine.Content, newLine.Content, false)
-			patches = dmp.DiffCleanupEfficiency(patches)
 			patches = dmp.DiffCleanupSemantic(patches)
+			patches = dmp.DiffCleanupMerge(patches)
+			patches = dmp.DiffCleanupEfficiency(patches)
 
-			// Apply highlighting to the differences
-			oldLine.Content = colorizeSegments(patches, true, style)
-			newLine.Content = colorizeSegments(patches, false, style)
+			segments := make([]Segment, 0)
+
+			removeStart := 0
+			addStart := 0
+			for _, patch := range patches {
+				switch patch.Type {
+				case diffmatchpatch.DiffDelete:
+					segments = append(segments, Segment{
+						Start: removeStart,
+						End:   removeStart + len(patch.Text),
+						Type:  LineRemoved,
+						Text:  patch.Text,
+					})
+					removeStart += len(patch.Text)
+				case diffmatchpatch.DiffInsert:
+					segments = append(segments, Segment{
+						Start: addStart,
+						End:   addStart + len(patch.Text),
+						Type:  LineAdded,
+						Text:  patch.Text,
+					})
+					addStart += len(patch.Text)
+				default:
+					// Context text, no highlighting needed
+					removeStart += len(patch.Text)
+					addStart += len(patch.Text)
+				}
+			}
+			oldLine.Segments = segments
+			newLine.Segments = segments
 
 			updated = append(updated, oldLine, newLine)
 			i++ // Skip the next line as we've already processed it
@@ -428,45 +427,7 @@ func HighlightIntralineChanges(h *Hunk, style StyleConfig) {
 	h.Lines = updated
 }
 
-// colorizeSegments applies styles to the character-level diff segments.
-func colorizeSegments(diffs []diffmatchpatch.Diff, isOld bool, style StyleConfig) string {
-	var buf strings.Builder
-
-	removeBg := lipgloss.NewStyle().
-		Background(style.RemovedHighlightBg).
-		Foreground(style.RemovedHighlightFg)
-
-	addBg := lipgloss.NewStyle().
-		Background(style.AddedHighlightBg).
-		Foreground(style.AddedHighlightFg)
-
-	removedLineStyle := lipgloss.NewStyle().Background(style.RemovedLineBg)
-	addedLineStyle := lipgloss.NewStyle().Background(style.AddedLineBg)
-
-	for _, d := range diffs {
-		switch d.Type {
-		case diffmatchpatch.DiffEqual:
-			// Handle text that's the same in both versions
-			buf.WriteString(d.Text)
-		case diffmatchpatch.DiffDelete:
-			// Handle deleted text (only show in old version)
-			if isOld {
-				buf.WriteString(removeBg.Render(d.Text))
-				buf.WriteString(removedLineStyle.Render(""))
-			}
-		case diffmatchpatch.DiffInsert:
-			// Handle inserted text (only show in new version)
-			if !isOld {
-				buf.WriteString(addBg.Render(d.Text))
-				buf.WriteString(addedLineStyle.Render(""))
-			}
-		}
-	}
-
-	return buf.String()
-}
-
-// pairLines converts a flat list of diff lines to pairs for side-by-side display.
+// pairLines converts a flat list of diff lines to pairs for side-by-side display
 func pairLines(lines []DiffLine) []linePair {
 	var pairs []linePair
 	i := 0
@@ -498,7 +459,7 @@ func pairLines(lines []DiffLine) []linePair {
 // Syntax Highlighting
 // -------------------------------------------------------------------------
 
-// SyntaxHighlight applies syntax highlighting to a string based on the file extension.
+// SyntaxHighlight applies syntax highlighting to text based on file extension
 func SyntaxHighlight(w io.Writer, source, fileName, formatter string, bg lipgloss.TerminalColor) error {
 	// Determine the language lexer to use
 	l := lexers.Match(fileName)
@@ -515,21 +476,98 @@ func SyntaxHighlight(w io.Writer, source, fileName, formatter string, bg lipglos
 	if f == nil {
 		f = formatters.Fallback
 	}
-
-	// Get the style
-	s := styles.Get("dracula")
-	if s == nil {
-		s = styles.Fallback
-	}
-
+	theme := `
+	<style name="vscode-dark-plus">
+	<!-- Base colors -->
+	<entry type="Background" style="bg:#1E1E1E"/>
+	<entry type="Text" style="#D4D4D4"/>
+	<entry type="Other" style="#D4D4D4"/>
+	<entry type="Error" style="#F44747"/>
+	<!-- Keywords - using the Control flow / Special keywords color -->
+	<entry type="Keyword" style="#C586C0"/>
+	<entry type="KeywordConstant" style="#4FC1FF"/>
+	<entry type="KeywordDeclaration" style="#C586C0"/>
+	<entry type="KeywordNamespace" style="#C586C0"/>
+	<entry type="KeywordPseudo" style="#C586C0"/>
+	<entry type="KeywordReserved" style="#C586C0"/>
+	<entry type="KeywordType" style="#4EC9B0"/>
+	<!-- Names -->
+	<entry type="Name" style="#D4D4D4"/>
+	<entry type="NameAttribute" style="#9CDCFE"/>
+	<entry type="NameBuiltin" style="#4EC9B0"/>
+	<entry type="NameBuiltinPseudo" style="#9CDCFE"/>
+	<entry type="NameClass" style="#4EC9B0"/>
+	<entry type="NameConstant" style="#4FC1FF"/>
+	<entry type="NameDecorator" style="#DCDCAA"/>
+	<entry type="NameEntity" style="#9CDCFE"/>
+	<entry type="NameException" style="#4EC9B0"/>
+	<entry type="NameFunction" style="#DCDCAA"/>
+	<entry type="NameLabel" style="#C8C8C8"/>
+	<entry type="NameNamespace" style="#4EC9B0"/>
+	<entry type="NameOther" style="#9CDCFE"/>
+	<entry type="NameTag" style="#569CD6"/>
+	<entry type="NameVariable" style="#9CDCFE"/>
+	<entry type="NameVariableClass" style="#9CDCFE"/>
+	<entry type="NameVariableGlobal" style="#9CDCFE"/>
+	<entry type="NameVariableInstance" style="#9CDCFE"/>
+	<!-- Literals -->
+	<entry type="Literal" style="#CE9178"/>
+	<entry type="LiteralDate" style="#CE9178"/>
+	<entry type="LiteralString" style="#CE9178"/>
+	<entry type="LiteralStringBacktick" style="#CE9178"/>
+	<entry type="LiteralStringChar" style="#CE9178"/>
+	<entry type="LiteralStringDoc" style="#CE9178"/>
+	<entry type="LiteralStringDouble" style="#CE9178"/>
+	<entry type="LiteralStringEscape" style="#d7ba7d"/>
+	<entry type="LiteralStringHeredoc" style="#CE9178"/>
+	<entry type="LiteralStringInterpol" style="#CE9178"/>
+	<entry type="LiteralStringOther" style="#CE9178"/>
+	<entry type="LiteralStringRegex" style="#d16969"/>
+	<entry type="LiteralStringSingle" style="#CE9178"/>
+	<entry type="LiteralStringSymbol" style="#CE9178"/>
+	<!-- Numbers - using the numberLiteral color -->
+	<entry type="LiteralNumber" style="#b5cea8"/>
+	<entry type="LiteralNumberBin" style="#b5cea8"/>
+	<entry type="LiteralNumberFloat" style="#b5cea8"/>
+	<entry type="LiteralNumberHex" style="#b5cea8"/>
+	<entry type="LiteralNumberInteger" style="#b5cea8"/>
+	<entry type="LiteralNumberIntegerLong" style="#b5cea8"/>
+	<entry type="LiteralNumberOct" style="#b5cea8"/>
+	<!-- Operators -->
+	<entry type="Operator" style="#D4D4D4"/>
+	<entry type="OperatorWord" style="#C586C0"/>
+	<entry type="Punctuation" style="#D4D4D4"/>
+	<!-- Comments - standard VSCode Dark+ comment color -->
+	<entry type="Comment" style="#6A9955"/>
+	<entry type="CommentHashbang" style="#6A9955"/>
+	<entry type="CommentMultiline" style="#6A9955"/>
+	<entry type="CommentSingle" style="#6A9955"/>
+	<entry type="CommentSpecial" style="#6A9955"/>
+	<entry type="CommentPreproc" style="#C586C0"/>
+	<!-- Generic styles -->
+	<entry type="Generic" style="#D4D4D4"/>
+	<entry type="GenericDeleted" style="#F44747"/>
+	<entry type="GenericEmph" style="italic #D4D4D4"/>
+	<entry type="GenericError" style="#F44747"/>
+	<entry type="GenericHeading" style="bold #D4D4D4"/>
+	<entry type="GenericInserted" style="#b5cea8"/>
+	<entry type="GenericOutput" style="#808080"/>
+	<entry type="GenericPrompt" style="#D4D4D4"/>
+	<entry type="GenericStrong" style="bold #D4D4D4"/>
+	<entry type="GenericSubheading" style="bold #D4D4D4"/>
+	<entry type="GenericTraceback" style="#F44747"/>
+	<entry type="GenericUnderline" style="underline"/>
+	<entry type="TextWhitespace" style="#D4D4D4"/>
+</style>
+`
+
+	r := strings.NewReader(theme)
+	style := chroma.MustNewXMLStyle(r)
 	// Modify the style to use the provided background
-	s, err := s.Builder().Transform(
+	s, err := style.Builder().Transform(
 		func(t chroma.StyleEntry) chroma.StyleEntry {
 			r, g, b, _ := bg.RGBA()
-			ru8 := uint8(r >> 8)
-			gu8 := uint8(g >> 8)
-			bu8 := uint8(b >> 8)
-			t.Background = chroma.NewColour(ru8, gu8, bu8)
+			t.Background = chroma.NewColour(uint8(r>>8), uint8(g>>8), uint8(b>>8))
 			return t
 		},
 	).Build()
@@ -546,7 +584,7 @@ func SyntaxHighlight(w io.Writer, source, fileName, formatter string, bg lipglos
 	return f.Format(w, s, it)
 }
 
-// highlightLine applies syntax highlighting to a single line.
+// highlightLine applies syntax highlighting to a single line
 func highlightLine(fileName string, line string, bg lipgloss.TerminalColor) string {
 	var buf bytes.Buffer
 	err := SyntaxHighlight(&buf, line, fileName, "terminal16m", bg)
@@ -556,7 +594,7 @@ func highlightLine(fileName string, line string, bg lipgloss.TerminalColor) stri
 	return buf.String()
 }
 
-// createStyles generates the lipgloss styles needed for rendering diffs.
+// createStyles generates the lipgloss styles needed for rendering diffs
 func createStyles(config StyleConfig) (removedLineStyle, addedLineStyle, contextLineStyle, lineNumberStyle lipgloss.Style) {
 	removedLineStyle = lipgloss.NewStyle().Background(config.RemovedLineBg)
 	addedLineStyle = lipgloss.NewStyle().Background(config.AddedLineBg)
@@ -566,7 +604,106 @@ func createStyles(config StyleConfig) (removedLineStyle, addedLineStyle, context
 	return
 }
 
-// renderLeftColumn formats the left side of a side-by-side diff.
+// -------------------------------------------------------------------------
+// Rendering Functions
+// -------------------------------------------------------------------------
+
+// applyHighlighting applies intra-line highlighting to a piece of text
+func applyHighlighting(content string, segments []Segment, segmentType LineType, highlightBg lipgloss.Color,
+) string {
+	// Find all ANSI sequences in the content
+	ansiRegex := regexp.MustCompile(`\x1b(?:[@-Z\\-_]|\[[0-9?]*(?:;[0-9?]*)*[@-~])`)
+	ansiMatches := ansiRegex.FindAllStringIndex(content, -1)
+
+	// Build a mapping of visible character positions to their actual indices
+	visibleIdx := 0
+	ansiSequences := make(map[int]string)
+	lastAnsiSeq := "\x1b[0m" // Default reset sequence
+
+	for i := 0; i < len(content); {
+		isAnsi := false
+		for _, match := range ansiMatches {
+			if match[0] == i {
+				ansiSequences[visibleIdx] = content[match[0]:match[1]]
+				lastAnsiSeq = content[match[0]:match[1]]
+				i = match[1]
+				isAnsi = true
+				break
+			}
+		}
+		if isAnsi {
+			continue
+		}
+
+		// For non-ANSI positions, store the last ANSI sequence
+		if _, exists := ansiSequences[visibleIdx]; !exists {
+			ansiSequences[visibleIdx] = lastAnsiSeq
+		}
+		visibleIdx++
+		i++
+	}
+
+	// Apply highlighting
+	var sb strings.Builder
+	inSelection := false
+	currentPos := 0
+
+	for i := 0; i < len(content); {
+		// Check if we're at an ANSI sequence
+		isAnsi := false
+		for _, match := range ansiMatches {
+			if match[0] == i {
+				sb.WriteString(content[match[0]:match[1]]) // Preserve ANSI sequence
+				i = match[1]
+				isAnsi = true
+				break
+			}
+		}
+		if isAnsi {
+			continue
+		}
+
+		// Check for segment boundaries
+		for _, seg := range segments {
+			if seg.Type == segmentType {
+				if currentPos == seg.Start {
+					inSelection = true
+				}
+				if currentPos == seg.End {
+					inSelection = false
+				}
+			}
+		}
+
+		// Get current character
+		char := string(content[i])
+
+		if inSelection {
+			// Get the current styling
+			currentStyle := ansiSequences[currentPos]
+
+			// Apply background highlight
+			sb.WriteString("\x1b[48;2;")
+			r, g, b, _ := highlightBg.RGBA()
+			sb.WriteString(fmt.Sprintf("%d;%d;%dm", r>>8, g>>8, b>>8))
+			sb.WriteString(char)
+			sb.WriteString("\x1b[49m") // Reset only background
+
+			// Reapply the original ANSI sequence
+			sb.WriteString(currentStyle)
+		} else {
+			// Not in selection, just copy the character
+			sb.WriteString(char)
+		}
+
+		currentPos++
+		i++
+	}
+
+	return sb.String()
+}
+
+// renderLeftColumn formats the left side of a side-by-side diff
 func renderLeftColumn(fileName string, dl *DiffLine, colWidth int, styles StyleConfig) string {
 	if dl == nil {
 		contextLineStyle := lipgloss.NewStyle().Background(styles.ContextLineBg)
@@ -575,9 +712,9 @@ func renderLeftColumn(fileName string, dl *DiffLine, colWidth int, styles StyleC
 
 	removedLineStyle, _, contextLineStyle, lineNumberStyle := createStyles(styles)
 
+	// Determine line style based on line type
 	var marker string
 	var bgStyle lipgloss.Style
-
 	switch dl.Kind {
 	case LineRemoved:
 		marker = removedLineStyle.Foreground(styles.RemovedFg).Render("-")
@@ -591,18 +728,29 @@ func renderLeftColumn(fileName string, dl *DiffLine, colWidth int, styles StyleC
 		bgStyle = contextLineStyle
 	}
 
+	// Format line number
 	lineNum := ""
 	if dl.OldLineNo > 0 {
 		lineNum = fmt.Sprintf("%6d", dl.OldLineNo)
 	}
 
+	// Create the line prefix
 	prefix := lineNumberStyle.Render(lineNum + " " + marker)
+
+	// Apply syntax highlighting
 	content := highlightLine(fileName, dl.Content, bgStyle.GetBackground())
 
+	// Apply intra-line highlighting for removed lines
+	if dl.Kind == LineRemoved && len(dl.Segments) > 0 {
+		content = applyHighlighting(content, dl.Segments, LineRemoved, styles.RemovedHighlightBg)
+	}
+
+	// Add a padding space for removed lines
 	if dl.Kind == LineRemoved {
 		content = bgStyle.Render(" ") + content
 	}
 
+	// Create the final line and truncate if needed
 	lineText := prefix + content
 	return bgStyle.MaxHeight(1).Width(colWidth).Render(
 		ansi.Truncate(
@@ -613,7 +761,7 @@ func renderLeftColumn(fileName string, dl *DiffLine, colWidth int, styles StyleC
 	)
 }
 
-// renderRightColumn formats the right side of a side-by-side diff.
+// renderRightColumn formats the right side of a side-by-side diff
 func renderRightColumn(fileName string, dl *DiffLine, colWidth int, styles StyleConfig) string {
 	if dl == nil {
 		contextLineStyle := lipgloss.NewStyle().Background(styles.ContextLineBg)
@@ -622,9 +770,9 @@ func renderRightColumn(fileName string, dl *DiffLine, colWidth int, styles Style
 
 	_, addedLineStyle, contextLineStyle, lineNumberStyle := createStyles(styles)
 
+	// Determine line style based on line type
 	var marker string
 	var bgStyle lipgloss.Style
-
 	switch dl.Kind {
 	case LineAdded:
 		marker = addedLineStyle.Foreground(styles.AddedFg).Render("+")
@@ -638,18 +786,29 @@ func renderRightColumn(fileName string, dl *DiffLine, colWidth int, styles Style
 		bgStyle = contextLineStyle
 	}
 
+	// Format line number
 	lineNum := ""
 	if dl.NewLineNo > 0 {
 		lineNum = fmt.Sprintf("%6d", dl.NewLineNo)
 	}
 
+	// Create the line prefix
 	prefix := lineNumberStyle.Render(lineNum + " " + marker)
+
+	// Apply syntax highlighting
 	content := highlightLine(fileName, dl.Content, bgStyle.GetBackground())
 
+	// Apply intra-line highlighting for added lines
+	if dl.Kind == LineAdded && len(dl.Segments) > 0 {
+		content = applyHighlighting(content, dl.Segments, LineAdded, styles.AddedHighlightBg)
+	}
+
+	// Add a padding space for added lines
 	if dl.Kind == LineAdded {
 		content = bgStyle.Render(" ") + content
 	}
 
+	// Create the final line and truncate if needed
 	lineText := prefix + content
 	return bgStyle.MaxHeight(1).Width(colWidth).Render(
 		ansi.Truncate(
@@ -661,10 +820,10 @@ func renderRightColumn(fileName string, dl *DiffLine, colWidth int, styles Style
 }
 
 // -------------------------------------------------------------------------
-// Public API Methods
+// Public API
 // -------------------------------------------------------------------------
 
-// RenderSideBySideHunk formats a hunk for side-by-side display.
+// RenderSideBySideHunk formats a hunk for side-by-side display
 func RenderSideBySideHunk(fileName string, h Hunk, opts ...SideBySideOption) string {
 	// Apply options to create the configuration
 	config := NewSideBySideConfig(opts...)
@@ -692,7 +851,7 @@ func RenderSideBySideHunk(fileName string, h Hunk, opts ...SideBySideOption) str
 	return sb.String()
 }
 
-// FormatDiff creates a side-by-side formatted view of a diff.
+// FormatDiff creates a side-by-side formatted view of a diff
 func FormatDiff(diffText string, opts ...SideBySideOption) (string, error) {
 	diffResult, err := ParseUnifiedDiff(diffText)
 	if err != nil {
@@ -700,11 +859,18 @@ func FormatDiff(diffText string, opts ...SideBySideOption) (string, error) {
 	}
 
 	var sb strings.Builder
-
 	config := NewSideBySideConfig(opts...)
+
 	for i, h := range diffResult.Hunks {
 		if i > 0 {
-			sb.WriteString(lipgloss.NewStyle().Background(config.Style.HunkLineBg).Foreground(config.Style.HunkLineFg).Width(config.TotalWidth).Render(h.Header) + "\n")
+			// Render hunk header
+			sb.WriteString(
+				lipgloss.NewStyle().
+					Background(config.Style.HunkLineBg).
+					Foreground(config.Style.HunkLineFg).
+					Width(config.TotalWidth).
+					Render(h.Header) + "\n",
+			)
 		}
 		sb.WriteString(RenderSideBySideHunk(diffResult.OldFile, h, opts...))
 	}
@@ -712,14 +878,16 @@ func FormatDiff(diffText string, opts ...SideBySideOption) (string, error) {
 	return sb.String(), nil
 }
 
-// GenerateDiff creates a unified diff from two file contents.
+// GenerateDiff creates a unified diff from two file contents
 func GenerateDiff(beforeContent, afterContent, fileName string) (string, int, int) {
+	// Create temporary directory for git operations
 	tempDir, err := os.MkdirTemp("", "git-diff-temp")
 	if err != nil {
 		return "", 0, 0
 	}
 	defer os.RemoveAll(tempDir)
 
+	// Initialize git repo
 	repo, err := git.PlainInit(tempDir, false)
 	if err != nil {
 		return "", 0, 0
@@ -730,6 +898,7 @@ func GenerateDiff(beforeContent, afterContent, fileName string) (string, int, in
 		return "", 0, 0
 	}
 
+	// Write the "before" content and commit it
 	fullPath := filepath.Join(tempDir, fileName)
 	if err = os.MkdirAll(filepath.Dir(fullPath), 0o755); err != nil {
 		return "", 0, 0
@@ -754,7 +923,9 @@ func GenerateDiff(beforeContent, afterContent, fileName string) (string, int, in
 		return "", 0, 0
 	}
 
+	// Write the "after" content and commit it
 	if err = os.WriteFile(fullPath, []byte(afterContent), 0o644); err != nil {
+		return "", 0, 0
 	}
 
 	_, err = wt.Add(fileName)
@@ -773,6 +944,7 @@ func GenerateDiff(beforeContent, afterContent, fileName string) (string, int, in
 		return "", 0, 0
 	}
 
+	// Get the diff between the two commits
 	beforeCommitObj, err := repo.CommitObject(beforeCommit)
 	if err != nil {
 		return "", 0, 0
@@ -788,6 +960,7 @@ func GenerateDiff(beforeContent, afterContent, fileName string) (string, int, in
 		return "", 0, 0
 	}
 
+	// Count additions and removals
 	additions := 0
 	removals := 0
 	for _, fileStat := range patch.Stats() {