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 item, ok := m.SelectedItem().(RefItem)
71 if !ok {
72 return nil
73 }
74 switch msg := msg.(type) {
75 case tea.KeyMsg:
76 switch {
77 case key.Matches(msg, d.common.KeyMap.Copy):
78 return copyCmd(item.ID(), fmt.Sprintf("Reference %q copied to clipboard", item.ID()))
79 }
80 }
81 return nil
82}
83
84// Render implements list.ItemDelegate.
85func (d RefItemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) {
86 s := d.common.Styles.Ref
87 i, ok := listItem.(RefItem)
88 if !ok {
89 return
90 }
91
92 var st lipgloss.Style
93 var selector string
94
95 isTag := i.Reference.IsTag()
96 isActive := index == m.Index()
97
98 if isTag && isActive {
99 st = s.Active.ItemTag
100 } else if isTag {
101 st = s.Normal.ItemTag
102 } else if isActive {
103 st = s.Active.Item
104 } else {
105 st = s.Normal.Item
106 }
107
108 if isActive {
109 selector = s.ItemSelector.String()
110 } else {
111 selector = " "
112 }
113
114 ref := i.Short()
115 ref = s.ItemBranch.Render(ref)
116 refMaxWidth := m.Width() -
117 s.ItemSelector.GetMarginLeft() -
118 s.ItemSelector.GetWidth() -
119 s.Normal.Item.GetMarginLeft()
120 ref = common.TruncateString(ref, refMaxWidth)
121 ref = st.Render(ref)
122 fmt.Fprint(w,
123 d.common.Zone.Mark(
124 i.ID(),
125 fmt.Sprint(selector, ref),
126 ),
127 )
128}