Просмотр исходного кода

feat: show git diff in reverted messages

adamdotdevin 6 месяцев назад
Родитель
Сommit
a129e122aa

+ 33 - 0
packages/tui/internal/components/chat/messages.go

@@ -5,6 +5,8 @@ import (
 	"fmt"
 	"fmt"
 	"log/slog"
 	"log/slog"
 	"slices"
 	"slices"
+	"sort"
+	"strconv"
 	"strings"
 	"strings"
 
 
 	tea "github.com/charmbracelet/bubbletea/v2"
 	tea "github.com/charmbracelet/bubbletea/v2"
@@ -14,6 +16,7 @@ import (
 	"github.com/sst/opencode/internal/app"
 	"github.com/sst/opencode/internal/app"
 	"github.com/sst/opencode/internal/commands"
 	"github.com/sst/opencode/internal/commands"
 	"github.com/sst/opencode/internal/components/dialog"
 	"github.com/sst/opencode/internal/components/dialog"
+	"github.com/sst/opencode/internal/components/diff"
 	"github.com/sst/opencode/internal/components/toast"
 	"github.com/sst/opencode/internal/components/toast"
 	"github.com/sst/opencode/internal/layout"
 	"github.com/sst/opencode/internal/layout"
 	"github.com/sst/opencode/internal/styles"
 	"github.com/sst/opencode/internal/styles"
@@ -569,6 +572,36 @@ func (m *messagesComponent) renderView() tea.Cmd {
 			hint += revertedStyle.Render(" (or /redo) to restore")
 			hint += revertedStyle.Render(" (or /redo) to restore")
 
 
 			content += "\n" + hint
 			content += "\n" + hint
+			if m.app.Session.Revert.Diff != "" {
+				t := theme.CurrentTheme()
+				s := styles.NewStyle().Background(t.BackgroundPanel())
+				green := s.Foreground(t.Success()).Render
+				red := s.Foreground(t.Error()).Render
+				content += "\n"
+				stats, err := diff.ParseStats(m.app.Session.Revert.Diff)
+				if err != nil {
+					slog.Error("Failed to parse diff stats", "error", err)
+				} else {
+					var files []string
+					for file := range stats {
+						files = append(files, file)
+					}
+					sort.Strings(files)
+
+					for _, file := range files {
+						fileStats := stats[file]
+						display := file
+						if fileStats.Added > 0 {
+							display += green(" +" + strconv.Itoa(int(fileStats.Added)))
+						}
+						if fileStats.Removed > 0 {
+							display += red(" -" + strconv.Itoa(int(fileStats.Removed)))
+						}
+						content += "\n" + display
+					}
+				}
+			}
+
 			content = styles.NewStyle().
 			content = styles.NewStyle().
 				Background(t.BackgroundPanel()).
 				Background(t.BackgroundPanel()).
 				Width(width - 6).
 				Width(width - 6).

+ 58 - 0
packages/tui/internal/components/diff/parse.go

@@ -0,0 +1,58 @@
+package diff
+
+import (
+	"bufio"
+	"fmt"
+	"strings"
+)
+
+type DiffStats struct {
+	Added    int
+	Removed  int
+	Modified int
+}
+
+func ParseStats(diff string) (map[string]DiffStats, error) {
+	stats := make(map[string]DiffStats)
+	var currentFile string
+	scanner := bufio.NewScanner(strings.NewReader(diff))
+
+	for scanner.Scan() {
+		line := scanner.Text()
+		if strings.HasPrefix(line, "---") {
+			continue
+		} else if strings.HasPrefix(line, "+++") {
+			parts := strings.SplitN(line, " ", 2)
+			if len(parts) == 2 {
+				currentFile = strings.TrimPrefix(parts[1], "b/")
+			}
+			continue
+		}
+		if strings.HasPrefix(line, "@@") {
+			continue
+		}
+		if currentFile == "" {
+			continue
+		}
+
+		fileStats := stats[currentFile]
+		switch {
+		case strings.HasPrefix(line, "+"):
+			fileStats.Added++
+		case strings.HasPrefix(line, "-"):
+			fileStats.Removed++
+		}
+		stats[currentFile] = fileStats
+	}
+
+	if err := scanner.Err(); err != nil {
+		return nil, fmt.Errorf("error reading diff string: %w", err)
+	}
+
+	for file, fileStats := range stats {
+		fileStats.Modified = fileStats.Added + fileStats.Removed
+		stats[file] = fileStats
+	}
+
+	return stats, nil
+}