✨ Better log viewer in launchpad
This commit is contained in:
126
pkg/launchpad/interactive/dev_mode.go
Normal file
126
pkg/launchpad/interactive/dev_mode.go
Normal file
@@ -0,0 +1,126 @@
|
||||
package interactive
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.solsynth.dev/goatworks/turbine/pkg/launchpad/config"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
var (
|
||||
titleStyle = lipgloss.NewStyle().
|
||||
Background(lipgloss.Color("62")).
|
||||
Foreground(lipgloss.Color("230")).
|
||||
Padding(0, 1)
|
||||
|
||||
helpStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("241"))
|
||||
)
|
||||
|
||||
type model struct {
|
||||
services []config.Service
|
||||
cursor int
|
||||
selected map[int]struct{}
|
||||
startServices bool
|
||||
}
|
||||
|
||||
func initialModel(services []config.Service) model {
|
||||
selected := make(map[int]struct{})
|
||||
for i := range services {
|
||||
selected[i] = struct{}{}
|
||||
}
|
||||
return model{
|
||||
services: services,
|
||||
selected: selected,
|
||||
}
|
||||
}
|
||||
|
||||
func (m model) Init() tea.Cmd {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case tea.KeyMsg:
|
||||
switch msg.String() {
|
||||
case "ctrl+c", "q":
|
||||
return m, tea.Quit
|
||||
|
||||
case "up", "k":
|
||||
if m.cursor > 0 {
|
||||
m.cursor--
|
||||
}
|
||||
|
||||
case "down", "j":
|
||||
if m.cursor < len(m.services)-1 {
|
||||
m.cursor++
|
||||
}
|
||||
|
||||
case " ":
|
||||
if _, ok := m.selected[m.cursor]; ok {
|
||||
delete(m.selected, m.cursor)
|
||||
} else {
|
||||
m.selected[m.cursor] = struct{}{}
|
||||
}
|
||||
case "enter":
|
||||
m.startServices = true
|
||||
return m, tea.Quit
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m model) View() string {
|
||||
var b strings.Builder
|
||||
|
||||
b.WriteString(titleStyle.Render("Select services to start"))
|
||||
b.WriteString("\n\n")
|
||||
|
||||
for i, service := range m.services {
|
||||
cursor := " "
|
||||
if m.cursor == i {
|
||||
cursor = ">"
|
||||
}
|
||||
|
||||
checked := " "
|
||||
if _, ok := m.selected[i]; ok {
|
||||
checked = "x"
|
||||
}
|
||||
|
||||
b.WriteString(fmt.Sprintf("%s [%s] %s\n", cursor, checked, service.Name))
|
||||
}
|
||||
|
||||
b.WriteString("\n")
|
||||
b.WriteString(helpStyle.Render("Use up/down to navigate, space to select, enter to start, q to quit."))
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (m model) SelectedServices() []config.Service {
|
||||
var selectedServices []config.Service
|
||||
for i := range m.selected {
|
||||
selectedServices = append(selectedServices, m.services[i])
|
||||
}
|
||||
return selectedServices
|
||||
}
|
||||
|
||||
func SelectServices(services []config.Service) ([]config.Service, error) {
|
||||
if len(services) == 0 {
|
||||
return nil, fmt.Errorf("no services defined in launchpad.toml")
|
||||
}
|
||||
m := initialModel(services)
|
||||
p := tea.NewProgram(m)
|
||||
|
||||
finalModel, err := p.Run()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fm := finalModel.(model)
|
||||
if fm.startServices {
|
||||
return fm.SelectedServices(), nil
|
||||
}
|
||||
|
||||
return nil, nil // User quit
|
||||
}
|
||||
Reference in New Issue
Block a user