1package repo23import (4 "fmt"5 "io"6 "io/fs"7 "strings"89 "charm.land/bubbles/v2/key"10 "charm.land/bubbles/v2/list"11 tea "charm.land/bubbletea/v2"12 "charm.land/lipgloss/v2"13 "github.com/charmbracelet/soft-serve/git"14 "github.com/charmbracelet/soft-serve/pkg/ui/common"15 "github.com/dustin/go-humanize"16)1718// FileItem is a list item for a file.19type FileItem struct {20 entry *git.TreeEntry21}2223// ID returns the ID of the file item.24func (i FileItem) ID() string {25 return i.entry.Name()26}2728// Title returns the title of the file item.29func (i FileItem) Title() string {30 return common.UnquoteFilename(i.entry.Name())31}3233// Description returns the description of the file item.34func (i FileItem) Description() string {35 return ""36}3738// Mode returns the mode of the file item.39func (i FileItem) Mode() fs.FileMode {40 return i.entry.Mode()41}4243// FilterValue implements list.Item.44func (i FileItem) FilterValue() string { return i.Title() }4546// FileItems is a list of file items.47type FileItems []FileItem4849// Len implements sort.Interface.50func (cl FileItems) Len() int { return len(cl) }5152// Swap implements sort.Interface.53func (cl FileItems) Swap(i, j int) { cl[i], cl[j] = cl[j], cl[i] }5455// Less implements sort.Interface.56func (cl FileItems) Less(i, j int) bool {57 if cl[i].entry.IsTree() && cl[j].entry.IsTree() {58 return cl[i].Title() < cl[j].Title()59 } else if cl[i].entry.IsTree() {60 return true61 } else if cl[j].entry.IsTree() {62 return false63 }64 return cl[i].Title() < cl[j].Title()65}6667// FileItemDelegate is the delegate for the file item list.68type FileItemDelegate struct {69 common *common.Common70}7172// Height returns the height of the file item list. Implements list.ItemDelegate.73func (d FileItemDelegate) Height() int { return 1 }7475// Spacing returns the spacing of the file item list. Implements list.ItemDelegate.76func (d FileItemDelegate) Spacing() int { return 0 }7778// Update implements list.ItemDelegate.79func (d FileItemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd {80 item, ok := m.SelectedItem().(FileItem)81 if !ok {82 return nil83 }84 switch msg := msg.(type) {85 case tea.KeyPressMsg:86 switch {87 case key.Matches(msg, d.common.KeyMap.Copy):88 return copyCmd(item.entry.Name(), fmt.Sprintf("File name %q copied to clipboard", item.entry.Name()))89 }90 }91 return nil92}9394// Render implements list.ItemDelegate.95func (d FileItemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) {96 i, ok := listItem.(FileItem)97 if !ok {98 return99 }100101 s := d.common.Styles.Tree102103 name := i.Title()104 size := humanize.Bytes(uint64(i.entry.Size())) //nolint:gosec105 size = strings.ReplaceAll(size, " ", "")106 sizeLen := lipgloss.Width(size)107 if i.entry.IsTree() {108 size = strings.Repeat(" ", sizeLen)109 if index == m.Index() {110 name = s.Active.FileDir.Render(name)111 } else {112 name = s.Normal.FileDir.Render(name)113 }114 }115 var nameStyle, sizeStyle, modeStyle lipgloss.Style116 mode := i.Mode()117 if index == m.Index() {118 nameStyle = s.Active.FileName119 sizeStyle = s.Active.FileSize120 modeStyle = s.Active.FileMode121 fmt.Fprint(w, s.Selector.Render(">")) //nolint:errcheck122 } else {123 nameStyle = s.Normal.FileName124 sizeStyle = s.Normal.FileSize125 modeStyle = s.Normal.FileMode126 fmt.Fprint(w, s.Selector.Render(" ")) //nolint:errcheck127 }128 sizeStyle = sizeStyle.129 Width(8).130 Align(lipgloss.Right).131 MarginLeft(1)132 leftMargin := s.Selector.GetMarginLeft() +133 s.Selector.GetWidth() +134 s.Normal.FileMode.GetMarginLeft() +135 s.Normal.FileMode.GetWidth() +136 nameStyle.GetMarginLeft() +137 sizeStyle.GetHorizontalFrameSize()138 name = common.TruncateString(name, m.Width()-leftMargin)139 name = nameStyle.Render(name)140 size = sizeStyle.Render(size)141 modeStr := modeStyle.Render(mode.String())142 truncate := lipgloss.NewStyle().MaxWidth(m.Width() -143 s.Selector.GetHorizontalFrameSize() -144 s.Selector.GetWidth())145 //nolint:errcheck146 fmt.Fprint(w,147 d.common.Zone.Mark(148 i.ID(),149 truncate.Render(fmt.Sprintf("%s%s%s",150 modeStr,151 size,152 name,153 )),154 ),155 )156}