on main help sign in
feat: use the new diff formatter
commited06ea21ffa9c55e847207524169adeed5588202 authorKujtim Hoxha <kujtimii.h@gmail.com> dateSat 14 Jun 2025, 14:58 (1 year ago) parent382b7f8
4 files changed+55−30
internal/llm/tools/edit.go+31−23 internal/tui/components/chat/messages/renderer.go+7−4 internal/tui/components/core/helpers.go+11 internal/tui/components/dialogs/permissions/permissions.go+6−3
internal/llm/tools/edit.go+31−23
@@ -24,14 +24,16 @@ type EditParams struct {
2424}
2525
2626type EditPermissionsParams struct {
27− FilePath string `json:"file_path"`
28− Diff string `json:"diff"`
27+ FilePath string `json:"file_path"`
28+ OldContent string `json:"old_content,omitempty"`
29+ NewContent string `json:"new_content,omitempty"`
2930}
3031
3132type EditResponseMetadata struct {
32− Diff string `json:"diff"`
33− Additions int `json:"additions"`
34− Removals int `json:"removals"`
33+ Additions int `json:"additions"`
34+ Removals int `json:"removals"`
35+ OldContent string `json:"old_content,omitempty"`
36+ NewContent string `json:"new_content,omitempty"`
3537}
3638
3739type editTool struct {
@@ -191,7 +193,7 @@ func (e *editTool) createNewFile(ctx context.Context, filePath, content string)
191193 return ToolResponse{}, fmt.Errorf("session ID and message ID are required for creating a new file")
192194 }
193195
194− diff, additions, removals := diff.GenerateDiff(
196+ _, additions, removals := diff.GenerateDiff(
195197 "",
196198 content,
197199 filePath,
@@ -209,8 +211,9 @@ func (e *editTool) createNewFile(ctx context.Context, filePath, content string)
209211 Action: "write",
210212 Description: fmt.Sprintf("Create file %s", filePath),
211213 Params: EditPermissionsParams{
212− FilePath: filePath,
213− Diff: diff,
214+ FilePath: filePath,
215+ OldContent: "",
216+ NewContent: content,
214217 },
215218 },
216219 )
@@ -243,9 +246,10 @@ func (e *editTool) createNewFile(ctx context.Context, filePath, content string)
243246 return WithResponseMetadata(
244247 NewTextResponse("File created: "+filePath),
245248 EditResponseMetadata{
246− Diff: diff,
247− Additions: additions,
248− Removals: removals,
249+ OldContent: "",
250+ NewContent: content,
251+ Additions: additions,
252+ Removals: removals,
249253 },
250254 ), nil
251255}
@@ -301,7 +305,7 @@ func (e *editTool) deleteContent(ctx context.Context, filePath, oldString string
301305 return ToolResponse{}, fmt.Errorf("session ID and message ID are required for creating a new file")
302306 }
303307
304− diff, additions, removals := diff.GenerateDiff(
308+ _, additions, removals := diff.GenerateDiff(
305309 oldContent,
306310 newContent,
307311 filePath,
@@ -320,8 +324,9 @@ func (e *editTool) deleteContent(ctx context.Context, filePath, oldString string
320324 Action: "write",
321325 Description: fmt.Sprintf("Delete content from file %s", filePath),
322326 Params: EditPermissionsParams{
323− FilePath: filePath,
324− Diff: diff,
327+ FilePath: filePath,
328+ OldContent: oldContent,
329+ NewContent: newContent,
325330 },
326331 },
327332 )
@@ -362,9 +367,10 @@ func (e *editTool) deleteContent(ctx context.Context, filePath, oldString string
362367 return WithResponseMetadata(
363368 NewTextResponse("Content deleted from file: "+filePath),
364369 EditResponseMetadata{
365− Diff: diff,
366− Additions: additions,
367− Removals: removals,
370+ OldContent: oldContent,
371+ NewContent: newContent,
372+ Additions: additions,
373+ Removals: removals,
368374 },
369375 ), nil
370376}
@@ -422,7 +428,7 @@ func (e *editTool) replaceContent(ctx context.Context, filePath, oldString, newS
422428 if sessionID == "" || messageID == "" {
423429 return ToolResponse{}, fmt.Errorf("session ID and message ID are required for creating a new file")
424430 }
425− diff, additions, removals := diff.GenerateDiff(
431+ _, additions, removals := diff.GenerateDiff(
426432 oldContent,
427433 newContent,
428434 filePath,
@@ -440,8 +446,9 @@ func (e *editTool) replaceContent(ctx context.Context, filePath, oldString, newS
440446 Action: "write",
441447 Description: fmt.Sprintf("Replace content in file %s", filePath),
442448 Params: EditPermissionsParams{
443− FilePath: filePath,
444− Diff: diff,
449+ FilePath: filePath,
450+ OldContent: oldContent,
451+ NewContent: newContent,
445452 },
446453 },
447454 )
@@ -482,8 +489,9 @@ func (e *editTool) replaceContent(ctx context.Context, filePath, oldString, newS
482489 return WithResponseMetadata(
483490 NewTextResponse("Content replaced in file: "+filePath),
484491 EditResponseMetadata{
485− Diff: diff,
486− Additions: additions,
487− Removals: removals,
492+ OldContent: oldContent,
493+ NewContent: newContent,
494+ Additions: additions,
495+ Removals: removals,
488496 }), nil
489497}
internal/tui/components/chat/messages/renderer.go+7−4
@@ -6,11 +6,11 @@ import (
66 "strings"
77 "time"
88
9− "github.com/charmbracelet/crush/internal/diff"
109 "github.com/charmbracelet/crush/internal/fileutil"
1110 "github.com/charmbracelet/crush/internal/highlight"
1211 "github.com/charmbracelet/crush/internal/llm/agent"
1312 "github.com/charmbracelet/crush/internal/llm/tools"
13+ "github.com/charmbracelet/crush/internal/tui/components/core"
1414 "github.com/charmbracelet/crush/internal/tui/styles"
1515 "github.com/charmbracelet/lipgloss/v2"
1616 "github.com/charmbracelet/lipgloss/v2/tree"
@@ -257,9 +257,12 @@ func (er editRenderer) Render(v *toolCallCmp) string {
257257 return renderPlainContent(v, v.result.Content)
258258 }
259259
260− trunc := truncateHeight(meta.Diff, responseContextHeight)
261− diffView, _ := diff.FormatDiff(trunc, diff.WithTotalWidth(v.textWidth()-2))
262− return diffView
260+ formatter := core.DiffFormatter().
261+ Before(fileutil.PrettyPath(params.FilePath), meta.OldContent).
262+ After(fileutil.PrettyPath(params.FilePath), meta.NewContent).
263+ Split().
264+ Width(v.textWidth() - 2) // -2 for padding
265+ return formatter.String()
263266 })
264267}
265268
internal/tui/components/core/helpers.go+11
@@ -4,6 +4,8 @@ import (
44 "image/color"
55 "strings"
66
7+ "github.com/alecthomas/chroma/v2"
8+ "github.com/charmbracelet/crush/internal/exp/diffview"
79 "github.com/charmbracelet/crush/internal/tui/styles"
810 "github.com/charmbracelet/lipgloss/v2"
911 "github.com/charmbracelet/x/ansi"
@@ -131,3 +133,12 @@ func SelectableButtons(buttons []ButtonOpts, spacing string) string {
131133
132134 return lipgloss.JoinHorizontal(lipgloss.Left, parts...)
133135}
136+
137+func DiffFormatter() *diffview.DiffView {
138+ formatDiff := diffview.New()
139+ style := chroma.MustNewStyle("crush", styles.GetChromaTheme())
140+ diff := formatDiff.
141+ SyntaxHightlight(true).
142+ ChromaStyle(style)
143+ return diff
144+}
internal/tui/components/dialogs/permissions/permissions.go+6−3
@@ -267,10 +267,13 @@ func (p *permissionDialogCmp) renderBashContent() string {
267267
268268func (p *permissionDialogCmp) renderEditContent() string {
269269 if pr, ok := p.permission.Params.(tools.EditPermissionsParams); ok {
270− diff := p.GetOrSetDiff(p.permission.ID, func() (string, error) {
271− return diff.FormatDiff(pr.Diff, diff.WithTotalWidth(p.contentViewPort.Width()))
272− })
270+ formatter := core.DiffFormatter().
271+ Before(fileutil.PrettyPath(pr.FilePath), pr.OldContent).
272+ After(fileutil.PrettyPath(pr.FilePath), pr.NewContent).
273+ Width(p.contentViewPort.Width()).
274+ Split()
273275
276+ diff := formatter.String()
274277 contentHeight := min(p.height-9, lipgloss.Height(diff))
275278 p.contentViewPort.SetHeight(contentHeight)
276279 p.contentViewPort.SetContent(diff)