1package repo
2
3import (
4 "fmt"
5 "io"
6 "strings"
7
8 "github.com/charmbracelet/bubbles/list"
9 tea "github.com/charmbracelet/bubbletea"
10 "github.com/charmbracelet/soft-serve/git"
11 "github.com/charmbracelet/soft-serve/ui/styles"
12 "github.com/muesli/reflow/truncate"
13)
14
15// LogItem is a item in the log list that displays a git commit.
16type LogItem struct {
17 *git.Commit
18}
19
20// ID implements selector.IdentifiableItem.
21func (i LogItem) ID() string {
22 return i.Commit.ID.String()
23}
24
25// Title returns the item title. Implements list.DefaultItem.
26func (i LogItem) Title() string {
27 if i.Commit != nil {
28 return strings.Split(i.Commit.Message, "\n")[0]
29 }
30 return ""
31}
32
33// Description returns the item description. Implements list.DefaultItem.
34func (i LogItem) Description() string { return "" }
35
36// FilterValue implements list.Item.
37func (i LogItem) FilterValue() string { return i.Title() }
38
39// LogItemDelegate is the delegate for LogItem.
40type LogItemDelegate struct {
41 style *styles.Styles
42}
43
44// Height returns the item height. Implements list.ItemDelegate.
45func (d LogItemDelegate) Height() int { return 1 }
46
47// Spacing returns the item spacing. Implements list.ItemDelegate.
48func (d LogItemDelegate) Spacing() int { return 0 }
49
50// Update updates the item. Implements list.ItemDelegate.
51func (d LogItemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd { return nil }
52
53// Render renders the item. Implements list.ItemDelegate.
54func (d LogItemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) {
55 i, ok := listItem.(LogItem)
56 if !ok {
57 return
58 }
59 if i.Commit == nil {
60 return
61 }
62
63 hash := i.Commit.ID.String()
64 leftMargin := d.style.LogItemSelector.GetMarginLeft() +
65 d.style.LogItemSelector.GetWidth() +
66 d.style.LogItemHash.GetMarginLeft() +
67 d.style.LogItemHash.GetWidth() +
68 d.style.LogItemInactive.GetMarginLeft()
69 title := truncateString(i.Title(), m.Width()-leftMargin, "…")
70 if index == m.Index() {
71 fmt.Fprint(w, d.style.LogItemSelector.Render(">")+
72 d.style.LogItemHash.Bold(true).Render(hash[:7])+
73 d.style.LogItemActive.Render(title))
74 } else {
75 fmt.Fprint(w, d.style.LogItemSelector.Render(" ")+
76 d.style.LogItemHash.Render(hash[:7])+
77 d.style.LogItemInactive.Render(title))
78 }
79}
80
81func truncateString(s string, max int, tail string) string {
82 if max < 0 {
83 max = 0
84 }
85 return truncate.StringWithTail(s, uint(max), tail)
86}