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