package main import ( "fmt" "os" "github.com/charmbracelet/bubbles/list" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/huh" "periodic/prddeploy/commands" ) type appState int const ( stateList appState = iota stateForm ) type item string func (i item) FilterValue() string { return string(i) } func (i item) Title() string { return string(i) } func (i item) Description() string { return "" } type model struct { list list.Model form *huh.Form state appState choice int RemoteCommand string PrivateKeyFile string Username string Host string LocalFilepath string DestinationFilepath string } func (m model) DebugState() { fmt.Printf("REMOTE COMMAND: %s\n", m.RemoteCommand) fmt.Printf("PRIVATE KEY FILE: %s\n", m.PrivateKeyFile) fmt.Printf("USERNAME: %s\n", m.Username) fmt.Printf("HOST: %s\n", m.Host) fmt.Printf("LOCAL FILEPATH: %s\n", m.LocalFilepath) fmt.Printf("DESTINATION FILEPATH: %s\n", m.DestinationFilepath) } func (m *model) ReadForm() { m.RemoteCommand = m.form.GetString("remote_command") m.PrivateKeyFile = m.form.GetString("private_key_file") m.Username = m.form.GetString("username") m.Host = m.form.GetString("host") m.LocalFilepath = m.form.GetString("local_filepath") m.DestinationFilepath = m.form.GetString("destination_filepath") } func newModel() model { items := []list.Item{ item("Run Command"), item("Upload File"), } l := list.New(items, list.NewDefaultDelegate(), 80, 20) l.Title = "prddeploy" return model{list: l, state: stateList} } func (m model) Init() tea.Cmd { return nil } func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch m.state { case stateList: switch msg := msg.(type) { case tea.WindowSizeMsg: m.list.SetSize(msg.Width, msg.Height) case tea.KeyMsg: if msg.String() == "enter" { m.choice = m.list.Index() m.state = stateForm if m.choice == 0 { m.form = huh.NewForm( huh.NewGroup( huh.NewInput().Title("Remote Command").Key("remote_command").Value(&m.RemoteCommand), huh.NewInput().Title("Private Key File").Key("private_key_file").Value(&m.PrivateKeyFile), huh.NewInput().Title("Username").Key("username").Value(&m.Username), huh.NewInput().Title("Host").Key("host").Value(&m.Host), ), ) } else { m.form = huh.NewForm( huh.NewGroup( huh.NewInput().Title("Local Filepath").Key("local_filepath").Value(&m.LocalFilepath), huh.NewInput().Title("Destination Filepath").Key("destination_filepath").Value(&m.DestinationFilepath), huh.NewInput().Title("Private Key File").Key("private_key_file").Value(&m.PrivateKeyFile), huh.NewInput().Title("Username").Key("username").Value(&m.Username), huh.NewInput().Title("Host").Key("host").Value(&m.Host), ), ) } return m, m.form.Init() } } var cmd tea.Cmd m.list, cmd = m.list.Update(msg) return m, cmd case stateForm: form, cmd := m.form.Update(msg) if f, ok := form.(*huh.Form); ok { m.form = f } if m.form.State == huh.StateCompleted { m.ReadForm() return m, tea.Quit } if m.form.State == huh.StateAborted { m.ReadForm() return m, tea.Quit } return m, cmd } return m, nil } func (m model) View() string { switch m.state { case stateList: return m.list.View() case stateForm: return m.form.View() } return "" } func main() { p := tea.NewProgram(newModel(), tea.WithAltScreen()) result, err := p.Run() if err != nil { fmt.Fprintf(os.Stderr, "Error running program: %v\n", err) os.Exit(1) } m, ok := result.(model) if !ok || m.form == nil || m.form.State != huh.StateCompleted { return } m.DebugState() if m.choice == 0 { commands.RunCommand(commands.RunCommandArgs{ RemoteCommand: m.RemoteCommand, PrivateKeyFile: m.PrivateKeyFile, Username: m.Username, Host: m.Host, }) } else { commands.UploadFile(commands.UploadFileArgs{ LocalFilepath: m.LocalFilepath, DestinationFilepath: m.DestinationFilepath, PrivateKeyFile: m.PrivateKeyFile, Username: m.Username, Host: m.Host, }) } }