steps.go

  1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  2//
  3// SPDX-License-Identifier: AGPL-3.0-or-later
  4
  5package init
  6
  7import (
  8	"errors"
  9
 10	"github.com/charmbracelet/huh"
 11	"github.com/spf13/cobra"
 12
 13	"git.secluded.site/lune/internal/config"
 14)
 15
 16// runUIPrefsStep runs the UI preferences configuration step.
 17func runUIPrefsStep(cfg *config.Config) wizardNav {
 18	color := cfg.UI.Color
 19	if color == "" {
 20		color = "auto"
 21	}
 22
 23	err := huh.NewSelect[string]().
 24		Title("Color output").
 25		Description("When should lune use colored output?").
 26		Options(
 27			huh.NewOption("Auto (detect terminal capability)", "auto"),
 28			huh.NewOption("Always", "always"),
 29			huh.NewOption("Never", "never"),
 30		).
 31		Value(&color).
 32		Run()
 33	if err != nil {
 34		if errors.Is(err, huh.ErrUserAborted) {
 35			return navQuit
 36		}
 37
 38		return navQuit
 39	}
 40
 41	cfg.UI.Color = color
 42
 43	return navNext
 44}
 45
 46// runAreasStep runs the areas configuration step.
 47func runAreasStep(cfg *config.Config) wizardNav {
 48	return manageAreasAsStep(cfg)
 49}
 50
 51// runNotebooksStep runs the notebooks configuration step.
 52func runNotebooksStep(cfg *config.Config) wizardNav {
 53	return manageNotebooksAsStep(cfg)
 54}
 55
 56// runHabitsStep runs the habits configuration step.
 57func runHabitsStep(cfg *config.Config) wizardNav {
 58	return manageHabitsAsStep(cfg)
 59}
 60
 61// runDefaultsStep runs the defaults configuration step.
 62func runDefaultsStep(cfg *config.Config) wizardNav {
 63	hasAreas := len(cfg.Areas) > 0
 64	hasNotebooks := len(cfg.Notebooks) > 0
 65
 66	if !hasAreas && !hasNotebooks {
 67		return navNext
 68	}
 69
 70	if hasAreas {
 71		nav := selectDefaultAreaWithNav(cfg)
 72		if nav != navNext {
 73			return nav
 74		}
 75	}
 76
 77	if hasNotebooks {
 78		return selectDefaultNotebookWithNav(cfg)
 79	}
 80
 81	return navNext
 82}
 83
 84// runAccessTokenStep runs the access token configuration step.
 85func runAccessTokenStep(cmd *cobra.Command) wizardNav {
 86	err := configureAccessToken(cmd)
 87	if errors.Is(err, errQuit) {
 88		return navQuit
 89	}
 90
 91	if err != nil {
 92		return navQuit
 93	}
 94
 95	return navNext
 96}
 97
 98// selectDefaultAreaWithNav selects the default area and returns navigation.
 99func selectDefaultAreaWithNav(cfg *config.Config) wizardNav {
100	options := []huh.Option[string]{huh.NewOption("None", "")}
101	for _, area := range cfg.Areas {
102		options = append(options, huh.NewOption(area.Name+" ("+area.Key+")", area.Key))
103	}
104
105	choice, nav := runDefaultSelect("Default area", "Used when no area is specified.", cfg.Defaults.Area, options)
106	if nav != navNext || choice == "" {
107		return nav
108	}
109
110	cfg.Defaults.Area = choice
111
112	return navNext
113}
114
115// selectDefaultNotebookWithNav selects the default notebook and returns navigation.
116func selectDefaultNotebookWithNav(cfg *config.Config) wizardNav {
117	options := []huh.Option[string]{huh.NewOption("None", "")}
118	for _, nb := range cfg.Notebooks {
119		options = append(options, huh.NewOption(nb.Name+" ("+nb.Key+")", nb.Key))
120	}
121
122	desc := "Used when no notebook is specified."
123	choice, nav := runDefaultSelect("Default notebook", desc, cfg.Defaults.Notebook, options)
124
125	if nav != navNext || choice == "" {
126		return nav
127	}
128
129	cfg.Defaults.Notebook = choice
130
131	return navNext
132}
133
134func runDefaultSelect(title, desc, current string, options []huh.Option[string]) (string, wizardNav) {
135	options = append(options,
136		huh.NewOption("← Back", choiceBack),
137		huh.NewOption("Next →", choiceNext),
138	)
139
140	value := current
141
142	err := huh.NewSelect[string]().
143		Title(title).
144		Description(desc).
145		Options(options...).
146		Value(&value).
147		Run()
148	if err != nil {
149		return "", navQuit
150	}
151
152	switch value {
153	case choiceBack:
154		return "", navBack
155	case choiceNext:
156		return "", navNext
157	default:
158		return value, navNext
159	}
160}