feat: use the new diff formatter

Kujtim Hoxha created

Change summary

internal/llm/tools/edit.go                                 | 54 ++++---
internal/tui/components/chat/messages/renderer.go          | 11 +
internal/tui/components/core/helpers.go                    | 11 +
internal/tui/components/dialogs/permissions/permissions.go |  9 
4 files changed, 55 insertions(+), 30 deletions(-)

Detailed changes

internal/llm/tools/edit.go 🔗

@@ -24,14 +24,16 @@ type EditParams struct {
 }
 
 type EditPermissionsParams struct {
-	FilePath string `json:"file_path"`
-	Diff     string `json:"diff"`
+	FilePath   string `json:"file_path"`
+	OldContent string `json:"old_content,omitempty"`
+	NewContent string `json:"new_content,omitempty"`
 }
 
 type EditResponseMetadata struct {
-	Diff      string `json:"diff"`
-	Additions int    `json:"additions"`
-	Removals  int    `json:"removals"`
+	Additions  int    `json:"additions"`
+	Removals   int    `json:"removals"`
+	OldContent string `json:"old_content,omitempty"`
+	NewContent string `json:"new_content,omitempty"`
 }
 
 type editTool struct {
@@ -191,7 +193,7 @@ func (e *editTool) createNewFile(ctx context.Context, filePath, content string)
 		return ToolResponse{}, fmt.Errorf("session ID and message ID are required for creating a new file")
 	}
 
-	diff, additions, removals := diff.GenerateDiff(
+	_, additions, removals := diff.GenerateDiff(
 		"",
 		content,
 		filePath,
@@ -209,8 +211,9 @@ func (e *editTool) createNewFile(ctx context.Context, filePath, content string)
 			Action:      "write",
 			Description: fmt.Sprintf("Create file %s", filePath),
 			Params: EditPermissionsParams{
-				FilePath: filePath,
-				Diff:     diff,
+				FilePath:   filePath,
+				OldContent: "",
+				NewContent: content,
 			},
 		},
 	)
@@ -243,9 +246,10 @@ func (e *editTool) createNewFile(ctx context.Context, filePath, content string)
 	return WithResponseMetadata(
 		NewTextResponse("File created: "+filePath),
 		EditResponseMetadata{
-			Diff:      diff,
-			Additions: additions,
-			Removals:  removals,
+			OldContent: "",
+			NewContent: content,
+			Additions:  additions,
+			Removals:   removals,
 		},
 	), nil
 }
@@ -301,7 +305,7 @@ func (e *editTool) deleteContent(ctx context.Context, filePath, oldString string
 		return ToolResponse{}, fmt.Errorf("session ID and message ID are required for creating a new file")
 	}
 
-	diff, additions, removals := diff.GenerateDiff(
+	_, additions, removals := diff.GenerateDiff(
 		oldContent,
 		newContent,
 		filePath,
@@ -320,8 +324,9 @@ func (e *editTool) deleteContent(ctx context.Context, filePath, oldString string
 			Action:      "write",
 			Description: fmt.Sprintf("Delete content from file %s", filePath),
 			Params: EditPermissionsParams{
-				FilePath: filePath,
-				Diff:     diff,
+				FilePath:   filePath,
+				OldContent: oldContent,
+				NewContent: newContent,
 			},
 		},
 	)
@@ -362,9 +367,10 @@ func (e *editTool) deleteContent(ctx context.Context, filePath, oldString string
 	return WithResponseMetadata(
 		NewTextResponse("Content deleted from file: "+filePath),
 		EditResponseMetadata{
-			Diff:      diff,
-			Additions: additions,
-			Removals:  removals,
+			OldContent: oldContent,
+			NewContent: newContent,
+			Additions:  additions,
+			Removals:   removals,
 		},
 	), nil
 }
@@ -422,7 +428,7 @@ func (e *editTool) replaceContent(ctx context.Context, filePath, oldString, newS
 	if sessionID == "" || messageID == "" {
 		return ToolResponse{}, fmt.Errorf("session ID and message ID are required for creating a new file")
 	}
-	diff, additions, removals := diff.GenerateDiff(
+	_, additions, removals := diff.GenerateDiff(
 		oldContent,
 		newContent,
 		filePath,
@@ -440,8 +446,9 @@ func (e *editTool) replaceContent(ctx context.Context, filePath, oldString, newS
 			Action:      "write",
 			Description: fmt.Sprintf("Replace content in file %s", filePath),
 			Params: EditPermissionsParams{
-				FilePath: filePath,
-				Diff:     diff,
+				FilePath:   filePath,
+				OldContent: oldContent,
+				NewContent: newContent,
 			},
 		},
 	)
@@ -482,8 +489,9 @@ func (e *editTool) replaceContent(ctx context.Context, filePath, oldString, newS
 	return WithResponseMetadata(
 		NewTextResponse("Content replaced in file: "+filePath),
 		EditResponseMetadata{
-			Diff:      diff,
-			Additions: additions,
-			Removals:  removals,
+			OldContent: oldContent,
+			NewContent: newContent,
+			Additions:  additions,
+			Removals:   removals,
 		}), nil
 }

internal/tui/components/chat/messages/renderer.go 🔗

@@ -6,11 +6,11 @@ import (
 	"strings"
 	"time"
 
-	"github.com/charmbracelet/crush/internal/diff"
 	"github.com/charmbracelet/crush/internal/fileutil"
 	"github.com/charmbracelet/crush/internal/highlight"
 	"github.com/charmbracelet/crush/internal/llm/agent"
 	"github.com/charmbracelet/crush/internal/llm/tools"
+	"github.com/charmbracelet/crush/internal/tui/components/core"
 	"github.com/charmbracelet/crush/internal/tui/styles"
 	"github.com/charmbracelet/lipgloss/v2"
 	"github.com/charmbracelet/lipgloss/v2/tree"
@@ -257,9 +257,12 @@ func (er editRenderer) Render(v *toolCallCmp) string {
 			return renderPlainContent(v, v.result.Content)
 		}
 
-		trunc := truncateHeight(meta.Diff, responseContextHeight)
-		diffView, _ := diff.FormatDiff(trunc, diff.WithTotalWidth(v.textWidth()-2))
-		return diffView
+		formatter := core.DiffFormatter().
+			Before(fileutil.PrettyPath(params.FilePath), meta.OldContent).
+			After(fileutil.PrettyPath(params.FilePath), meta.NewContent).
+			Split().
+			Width(v.textWidth() - 2) // -2 for padding
+		return formatter.String()
 	})
 }
 

internal/tui/components/core/helpers.go 🔗

@@ -4,6 +4,8 @@ import (
 	"image/color"
 	"strings"
 
+	"github.com/alecthomas/chroma/v2"
+	"github.com/charmbracelet/crush/internal/exp/diffview"
 	"github.com/charmbracelet/crush/internal/tui/styles"
 	"github.com/charmbracelet/lipgloss/v2"
 	"github.com/charmbracelet/x/ansi"
@@ -131,3 +133,12 @@ func SelectableButtons(buttons []ButtonOpts, spacing string) string {
 
 	return lipgloss.JoinHorizontal(lipgloss.Left, parts...)
 }
+
+func DiffFormatter() *diffview.DiffView {
+	formatDiff := diffview.New()
+	style := chroma.MustNewStyle("crush", styles.GetChromaTheme())
+	diff := formatDiff.
+		SyntaxHightlight(true).
+		ChromaStyle(style)
+	return diff
+}

internal/tui/components/dialogs/permissions/permissions.go 🔗

@@ -267,10 +267,13 @@ func (p *permissionDialogCmp) renderBashContent() string {
 
 func (p *permissionDialogCmp) renderEditContent() string {
 	if pr, ok := p.permission.Params.(tools.EditPermissionsParams); ok {
-		diff := p.GetOrSetDiff(p.permission.ID, func() (string, error) {
-			return diff.FormatDiff(pr.Diff, diff.WithTotalWidth(p.contentViewPort.Width()))
-		})
+		formatter := core.DiffFormatter().
+			Before(fileutil.PrettyPath(pr.FilePath), pr.OldContent).
+			After(fileutil.PrettyPath(pr.FilePath), pr.NewContent).
+			Width(p.contentViewPort.Width()).
+			Split()
 
+		diff := formatter.String()
 		contentHeight := min(p.height-9, lipgloss.Height(diff))
 		p.contentViewPort.SetHeight(contentHeight)
 		p.contentViewPort.SetContent(diff)