onboarding.go

 1package model
 2
 3import (
 4	"fmt"
 5	"log/slog"
 6	"strings"
 7
 8	"charm.land/bubbles/v2/key"
 9	tea "charm.land/bubbletea/v2"
10	"charm.land/lipgloss/v2"
11	"github.com/charmbracelet/crush/internal/config"
12	"github.com/charmbracelet/crush/internal/home"
13	"github.com/charmbracelet/crush/internal/ui/common"
14)
15
16func (m *UI) markProjectInitialized() tea.Msg {
17	// TODO: handle error so we show it in the tui footer
18	err := config.MarkProjectInitialized()
19	if err != nil {
20		slog.Error(err.Error())
21	}
22	return nil
23}
24
25func (m *UI) updateInitializeView(msg tea.KeyPressMsg) (cmds []tea.Cmd) {
26	switch {
27	case key.Matches(msg, m.keyMap.Initialize.Enter):
28		if m.onboarding.yesInitializeSelected {
29			cmds = append(cmds, m.initializeProject())
30		} else {
31			cmds = append(cmds, m.skipInitializeProject())
32		}
33	case key.Matches(msg, m.keyMap.Initialize.Switch):
34		m.onboarding.yesInitializeSelected = !m.onboarding.yesInitializeSelected
35	case key.Matches(msg, m.keyMap.Initialize.Yes):
36		cmds = append(cmds, m.initializeProject())
37	case key.Matches(msg, m.keyMap.Initialize.No):
38		cmds = append(cmds, m.skipInitializeProject())
39	}
40	return cmds
41}
42
43func (m *UI) initializeProject() tea.Cmd {
44	// TODO: initialize the project
45	// for now we just go to the landing page
46	m.state = uiLanding
47	m.focus = uiFocusEditor
48	// TODO: actually send a message to the agent
49	return m.markProjectInitialized
50}
51
52func (m *UI) skipInitializeProject() tea.Cmd {
53	// TODO: initialize the project
54	m.state = uiLanding
55	m.focus = uiFocusEditor
56	// mark the project as initialized
57	return m.markProjectInitialized
58}
59
60func (m *UI) initializeView() string {
61	cfg := m.com.Config()
62	s := m.com.Styles.Initialize
63	cwd := home.Short(cfg.WorkingDir())
64	initFile := cfg.Options.InitializeAs
65
66	header := s.Header.Render("Would you like to initialize this project?")
67	path := s.Accent.PaddingLeft(2).Render(cwd)
68	desc := s.Content.Render(fmt.Sprintf("When I initialize your codebase I examine the project and put the result into an %s file which serves as general context.", initFile))
69	hint := s.Content.Render("You can also initialize anytime via ") + s.Accent.Render("ctrl+p") + s.Content.Render(".")
70	prompt := s.Content.Render("Would you like to initialize now?")
71
72	buttons := common.ButtonGroup(m.com.Styles, []common.ButtonOpts{
73		{Text: "Yep!", Selected: m.onboarding.yesInitializeSelected},
74		{Text: "Nope", Selected: !m.onboarding.yesInitializeSelected},
75	}, " ")
76
77	// max width 60 so the text is compact
78	width := min(m.layout.main.Dx(), 60)
79
80	return lipgloss.NewStyle().
81		Width(width).
82		Height(m.layout.main.Dy()).
83		PaddingBottom(1).
84		AlignVertical(lipgloss.Bottom).
85		Render(strings.Join(
86			[]string{
87				header,
88				path,
89				desc,
90				hint,
91				prompt,
92				buttons,
93			},
94			"\n\n",
95		))
96}