7 "github.com/aymanbagabas/go-udiff"
8 "github.com/aymanbagabas/go-udiff/myers"
9 "github.com/charmbracelet/lipgloss/v2"
10 "github.com/charmbracelet/x/ansi"
11 "github.com/charmbracelet/x/exp/charmtone"
14const leadingSymbolsSize = 2
24 layoutUnified layout = iota + 1
28type LineStyle struct {
39var DefaultLightStyle = Style{
41 Code: lipgloss.NewStyle().
42 Foreground(charmtone.Pepper).
43 Background(charmtone.Salt),
45 InsertLine: LineStyle{
46 Symbol: lipgloss.NewStyle().
47 Foreground(charmtone.Turtle).
48 Background(lipgloss.Color("#e8f5e9")),
49 Code: lipgloss.NewStyle().
50 Foreground(charmtone.Pepper).
51 Background(lipgloss.Color("#e8f5e9")),
53 DeleteLine: LineStyle{
54 Symbol: lipgloss.NewStyle().
55 Foreground(charmtone.Cherry).
56 Background(lipgloss.Color("#ffebee")),
57 Code: lipgloss.NewStyle().
58 Foreground(charmtone.Pepper).
59 Background(lipgloss.Color("#ffebee")),
63var DefaultDarkStyle = Style{
65 Code: lipgloss.NewStyle().
66 Foreground(charmtone.Salt).
67 Background(charmtone.Pepper),
69 InsertLine: LineStyle{
70 Symbol: lipgloss.NewStyle().
71 Foreground(charmtone.Turtle).
72 Background(lipgloss.Color("#303a30")),
73 Code: lipgloss.NewStyle().
74 Foreground(charmtone.Salt).
75 Background(lipgloss.Color("#303a30")),
77 DeleteLine: LineStyle{
78 Symbol: lipgloss.NewStyle().
79 Foreground(charmtone.Cherry).
80 Background(lipgloss.Color("#3a3030")),
81 Code: lipgloss.NewStyle().
82 Foreground(charmtone.Salt).
83 Background(lipgloss.Color("#3a3030")),
87// DiffView represents a view for displaying differences between two files.
100 unified udiff.UnifiedDiff
104// New creates a new DiffView with default settings.
105func New() *DiffView {
107 layout: layoutUnified,
108 contextLines: udiff.DefaultContextLines,
110 if lipgloss.HasDarkBackground(os.Stdin, os.Stdout) {
111 dv.style = DefaultDarkStyle
113 dv.style = DefaultLightStyle
118// Unified sets the layout of the DiffView to unified.
119func (dv *DiffView) Unified() *DiffView {
120 dv.layout = layoutUnified
124// Split sets the layout of the DiffView to split (side-by-side).
125func (dv *DiffView) Split() *DiffView {
126 dv.layout = layoutSplit
130// Before sets the "before" file for the DiffView.
131func (dv *DiffView) Before(path, content string) *DiffView {
132 dv.before = file{path: path, content: content}
136// After sets the "after" file for the DiffView.
137func (dv *DiffView) After(path, content string) *DiffView {
138 dv.after = file{path: path, content: content}
142// ContextLines sets the number of context lines for the DiffView.
143func (dv *DiffView) ContextLines(contextLines int) *DiffView {
144 dv.contextLines = contextLines
148// Style sets the style for the DiffView.
149func (dv *DiffView) Style(style Style) *DiffView {
154// SyntaxHighlight sets whether to enable syntax highlighting in the DiffView.
155func (dv *DiffView) SyntaxHighlight(highlight bool) *DiffView {
156 dv.highlight = highlight
160// Height sets the height of the DiffView.
161func (dv *DiffView) Height(height int) *DiffView {
166// Width sets the width of the DiffView.
167func (dv *DiffView) Width(width int) *DiffView {
172// String returns the string representation of the DiffView.
173func (dv *DiffView) String() string {
174 if err := dv.computeDiff(); err != nil {
179 var b strings.Builder
181 for _, h := range dv.unified.Hunks {
182 for _, l := range h.Lines {
183 content := strings.TrimSuffix(l.Content, "\n")
184 width := dv.width - leadingSymbolsSize
188 b.WriteString(dv.style.InsertLine.Symbol.Render("+ "))
189 b.WriteString(dv.style.InsertLine.Code.Width(width).Render(content))
191 b.WriteString(dv.style.DeleteLine.Symbol.Render("- "))
192 b.WriteString(dv.style.DeleteLine.Code.Width(width).Render(content))
194 b.WriteString(dv.style.EqualLine.Code.Width(width + leadingSymbolsSize).Render(" " + content))
203func (dv *DiffView) computeDiff() error {
208 dv.edits = myers.ComputeEdits(
212 dv.unified, dv.err = udiff.ToUnifiedDiff(
222func (dv *DiffView) detectWidth() {
227 for _, h := range dv.unified.Hunks {
228 for _, l := range h.Lines {
229 lineWidth := ansi.StringWidth(strings.TrimSuffix(l.Content, "\n"))
230 lineWidth += leadingSymbolsSize
231 dv.width = max(dv.width, lineWidth)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list