commands.go

  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}