1package repo
2
3import (
4 "fmt"
5 "io"
6
7 "github.com/charmbracelet/bubbles/key"
8 "github.com/charmbracelet/bubbles/list"
9 tea "github.com/charmbracelet/bubbletea"
10 "github.com/charmbracelet/lipgloss"
11 "github.com/charmbracelet/soft-serve/git"
12 "github.com/charmbracelet/soft-serve/ui/common"
13)
14
15// RefItem is a git reference item.
16type RefItem struct {
17 *git.Reference
18}
19
20// ID implements selector.IdentifiableItem.
21func (i RefItem) ID() string {
22 return i.Reference.Name().String()
23}
24
25// Title implements list.DefaultItem.
26func (i RefItem) Title() string {
27 return i.Reference.Name().Short()
28}
29
30// Description implements list.DefaultItem.
31func (i RefItem) Description() string {
32 return ""
33}
34
35// Short returns the short name of the reference.
36func (i RefItem) Short() string {
37 return i.Reference.Name().Short()
38}
39
40// FilterValue implements list.Item.
41func (i RefItem) FilterValue() string { return i.Short() }
42
43// RefItems is a list of git references.
44type RefItems []RefItem
45
46// Len implements sort.Interface.
47func (cl RefItems) Len() int { return len(cl) }
48
49// Swap implements sort.Interface.
50func (cl RefItems) Swap(i, j int) { cl[i], cl[j] = cl[j], cl[i] }
51
52// Less implements sort.Interface.
53func (cl RefItems) Less(i, j int) bool {
54 return cl[i].Short() < cl[j].Short()
55}
56
57// RefItemDelegate is the delegate for the ref item.
58type RefItemDelegate struct {
59 common *common.Common
60}
61
62// Height implements list.ItemDelegate.
63func (d RefItemDelegate) Height() int { return 1 }
64
65// Spacing implements list.ItemDelegate.
66func (d RefItemDelegate) Spacing() int { return 0 }
67
68// Update implements list.ItemDelegate.
69func (d RefItemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd {
70 idx := m.Index()
71 item, ok := m.SelectedItem().(RefItem)
72 if !ok {
73 return nil
74 }
75 switch msg := msg.(type) {
76 case tea.KeyMsg:
77 switch {
78 case key.Matches(msg, d.common.KeyMap.Copy):
79 d.common.Copy.Copy(item.Title())
80 return m.SetItem(idx, item)
81 }
82 }
83 return nil
84}
85
86// Render implements list.ItemDelegate.
87func (d RefItemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) {
88 s := d.common.Styles
89 i, ok := listItem.(RefItem)
90 if !ok {
91 return
92 }
93
94 var st lipgloss.Style
95 var selector string
96
97 isTag := i.Reference.IsTag()
98 isActive := index == m.Index()
99
100 if isTag && isActive {
101 st = s.RefItemTagActive
102 } else if isTag {
103 st = s.RefItemTagInactive
104 } else if isActive {
105 st = s.RefItemActive
106 } else {
107 st = s.RefItemInactive
108 }
109
110 if isActive {
111 selector = s.RefItemSelector.String()
112 } else {
113 selector = " "
114 }
115
116 ref := i.Short()
117 ref = s.RefItemBranch.Render(ref)
118 refMaxWidth := m.Width() -
119 s.RefItemSelector.GetMarginLeft() -
120 s.RefItemSelector.GetWidth() -
121 s.RefItemInactive.GetMarginLeft()
122 ref = common.TruncateString(ref, refMaxWidth)
123 ref = st.Render(ref)
124 fmt.Fprint(w, selector, ref)
125}