package setup import ( "bubble/bootstrap" "bubble/types" "fmt" tea "github.com/charmbracelet/bubbletea" "github.com/sirupsen/logrus" ) func Start() { p := tea.NewProgram(NewMain(), tea.WithAltScreen()) if _, err := p.Run(); err != nil { panic(err) } } type Main struct { current tea.Model Applications []types.PackageApplication CurrentApplication *types.PackageApplication CurrentSection *types.Section CurrentSectionIdx int width int height int } func NewMain() *Main { apps := bootstrap.LoadApplications() return &Main{ Applications: apps, current: NewListModel(apps), CurrentSectionIdx: 0, } } func (m *Main) Init() tea.Cmd { return m.current.Init() } func (m *Main) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd m.current, cmd = m.current.Update(msg) switch msg := msg.(type) { case tea.WindowSizeMsg: m.width = msg.Width m.height = msg.Height m.current, cmd = m.current.Update(msg) case tea.KeyMsg: switch msg.String() { case "ctrl+c", "q": return m, tea.Quit } case types.NextSectionMsg: m.CurrentSectionIdx++ if m.CurrentSectionIdx == len(m.CurrentApplication.Sections) { return m, tea.Quit } for sectionIdx := m.CurrentSectionIdx; sectionIdx < len(m.CurrentApplication.Sections); sectionIdx++ { //todo переделать. Учесть динамические индексы. section := m.CurrentApplication.Sections[sectionIdx] if CheckCondition(section.Condition, m.CurrentApplication) { m.CurrentSectionIdx = sectionIdx m.CurrentSection = §ion break } } if m.CurrentSection == nil { logrus.Infof("next section, eq nil, out, idx %d", m.CurrentSectionIdx) return m, tea.Quit } //todo переделать. Учесть динамические индексы. if m.CurrentSectionIdx == len(m.CurrentApplication.Sections)-1 && m.CurrentSection.Type == "final" { m.current = NewFinalModel(m.CurrentApplication.Variables, m.width, m.height) } else { m.current = NewFormModel(m.CurrentApplication, m.CurrentSectionIdx, 0) } case types.SugarMsg: m.Sugar(msg) case types.SelectedAppMsg: //получаем сообщение о выборе приложения m.CurrentApplication = &m.Applications[msg.Index] //ищем доступную секцию for sectionIdx := 0; sectionIdx < len(m.CurrentApplication.Sections); sectionIdx++ { section := m.CurrentApplication.Sections[sectionIdx] if CheckCondition(section.Condition, m.CurrentApplication) { m.CurrentSectionIdx = sectionIdx m.CurrentSection = §ion break } } //если секция не была найдена, то выходим if m.CurrentSection == nil { logrus.Infof("select app, eq nil, out") return m, tea.Quit } //создаем новую форму m.current = NewFormModel(m.CurrentApplication, m.CurrentSectionIdx, 0) } return m, cmd } func (m *Main) View() string { return m.current.View() } func (m *Main) Sugar(sugar types.SugarMsg) { if m.IsMultiField(sugar.VariableName) { m.DeactivateField(sugar.VariableName, sugar.FieldName) } if IsParent(sugar.VariableName, m.CurrentApplication.Sections) { if sugar.Compute != "" { Recompute(m.CurrentApplication) } m.current = NewFormModel(m.CurrentApplication, m.CurrentSectionIdx, sugar.Focus) } } func IsParent(variableName string, sections []types.Section) bool { for _, section := range sections { for _, parent := range section.Parent { if parent == variableName { return true } } for _, field := range section.Fields { for _, parent := range field.Parent { if parent == variableName { return true } } } } return false } func (m *Main) IsMultiField(variableName string) bool { var count int for _, section := range m.CurrentApplication.Sections { for _, field := range section.Fields { if field.Name == variableName { count++ } } } return count > 1 } func (m *Main) DeactivateField(variableName, fieldName string) { for sectionIdx, section := range m.CurrentApplication.Sections { for fieldIdx, field := range section.Fields { if field.Variable.Name == variableName { if field.Name != fieldName { m.CurrentApplication.Sections[sectionIdx].Fields[fieldIdx].Active = false } else { m.CurrentApplication.Sections[sectionIdx].Fields[fieldIdx].Active = true } } } } } func (m *Main) RecomputeFields() { for i := range m.CurrentApplication.Sections { section := &m.CurrentApplication.Sections[i] for j := range section.Fields { field := §ion.Fields[j] if field.FieldType == "compute" && field.Compute != "" { if field.Variable != nil { continue } value, err := ComputeValue(field.Compute, m.CurrentApplication) if err != nil { value = fmt.Sprintf("Ошибка вычисления: %v", err) } field.Variable.Value = value } } } }