1package tui
2
3import (
4 "fmt"
5
6 tea "github.com/charmbracelet/bubbletea"
7 "github.com/charmbracelet/lipgloss"
8 "github.com/charmbracelet/soft/config"
9 br "github.com/charmbracelet/soft/tui/bubbles/repo"
10 "github.com/charmbracelet/soft/tui/bubbles/selection"
11 "github.com/muesli/termenv"
12)
13
14type errMsg struct{ err error }
15
16func (e errMsg) Error() string {
17 return e.err.Error()
18}
19
20func (b *Bubble) setupCmd() tea.Msg {
21 if b.config == nil || b.config.Source == nil {
22 return errMsg{err: fmt.Errorf("config not set")}
23 }
24 lipgloss.SetColorProfile(termenv.ANSI256)
25 mes, err := b.menuEntriesFromSource()
26 if err != nil {
27 return errMsg{err}
28 }
29 if len(mes) == 0 {
30 return errMsg{fmt.Errorf("no repos found")}
31 }
32 b.repoMenu = mes
33 rs := make([]string, 0)
34 for _, m := range mes {
35 rs = append(rs, m.Name)
36 }
37 b.repoSelect = selection.NewBubble(rs, b.styles)
38 b.boxes[0] = b.repoSelect
39
40 // Jump to an initial repo
41 ir := -1
42 if b.initialRepo != "" {
43 for i, me := range b.repoMenu {
44 if me.Repo == b.initialRepo {
45 ir = i
46 }
47 }
48 }
49 if ir == -1 {
50 b.boxes[1] = b.repoMenu[0].bubble
51 b.activeBox = 0
52 } else {
53 b.boxes[1] = b.repoMenu[ir].bubble
54 b.repoSelect.SelectedItem = ir
55 b.activeBox = 1
56 }
57
58 b.state = loadedState
59 return nil
60}
61
62func (b *Bubble) menuEntriesFromSource() ([]MenuEntry, error) {
63 mes := make([]MenuEntry, 0)
64 for _, r := range b.config.Repos {
65 me, err := b.newMenuEntry(r.Name, r.Repo)
66 if err != nil {
67 return nil, err
68 }
69 mes = append(mes, me)
70 }
71 rs := b.config.Source.AllRepos()
72OUTER:
73 for _, r := range rs {
74 for _, me := range mes {
75 if r.Name == me.Repo {
76 continue OUTER
77 }
78 }
79 me, err := b.newMenuEntry(r.Name, r.Name)
80 if err != nil {
81 return nil, err
82 }
83 mes = append(mes, me)
84 }
85 return mes, nil
86}
87
88func (b *Bubble) newMenuEntry(name string, repo string) (MenuEntry, error) {
89 var tmplConfig *config.Config
90 me := MenuEntry{Name: name, Repo: repo}
91 width := b.width
92 boxLeftWidth := b.styles.Menu.GetWidth() + b.styles.Menu.GetHorizontalFrameSize()
93 // TODO: also send this along with a tea.WindowSizeMsg
94 var heightMargin = lipgloss.Height(b.headerView()) +
95 lipgloss.Height(b.footerView()) +
96 b.styles.RepoBody.GetVerticalFrameSize() +
97 b.styles.App.GetVerticalMargins()
98 if repo == "config" {
99 tmplConfig = b.config
100 }
101 rb := br.NewBubble(
102 b.config.Source,
103 me.Repo,
104 b.styles,
105 width,
106 boxLeftWidth,
107 b.height,
108 heightMargin,
109 tmplConfig,
110 )
111 rb.Host = b.config.Host
112 rb.Port = b.config.Port
113 initCmd := rb.Init()
114 msg := initCmd()
115 switch msg := msg.(type) {
116 case br.ErrMsg:
117 return me, fmt.Errorf("missing %s: %s", me.Repo, msg.Error)
118 }
119 me.bubble = rb
120 return me, nil
121}