From 48d7730a5c913c2ba48af862a7dd1a8fa110f4b5 Mon Sep 17 00:00:00 2001 From: Ron Rise Date: Mon, 12 May 2025 21:58:17 -0400 Subject: [PATCH] derp, helper method rename --- interactive/model.go | 111 ++++++++++++++++++++++-------------------- interactive/params.go | 81 ++++++++++++++++++++++-------- interactive/update.go | 82 +++++++++++++++++++++++++------ interactive/view.go | 21 +++++--- 4 files changed, 202 insertions(+), 93 deletions(-) diff --git a/interactive/model.go b/interactive/model.go index c34dba5..03086c6 100644 --- a/interactive/model.go +++ b/interactive/model.go @@ -3,6 +3,7 @@ package interactive import ( "fmt" "github.com/aws/aws-sdk-go/aws" + "github.com/charmbracelet/bubbles/key" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/huh" "github.com/siteworxpro/img-proxy-url-generator/config" @@ -11,18 +12,21 @@ import ( ) type Model struct { - Form *huh.Form + Fields []huh.Field generator *generator.Generator url *string format *generator.Format selectedParams *[]UrlParam err error + focusField huh.Field + inParamsFields bool } type UrlParam interface { value() string + display() string key() string - Input() *huh.Input + Input() huh.Field } func InitialModel(c *cli.Context) Model { @@ -33,49 +37,10 @@ func InitialModel(c *cli.Context) Model { format: generator.ToPtr(generator.DEF), } - options := []UrlParam{ - Height{ - paramValue: "40", - }, - Width{ - paramValue: "40", - }, - } + fields := make([]huh.Field, 0) + fields = append(fields, m.initialFields()...) - var huhOptions []huh.Option[UrlParam] - for _, option := range options { - huhOptions = append(huhOptions, huh.NewOption[UrlParam](option.value(), option)) - } - - form := huh.NewForm( - huh.NewGroup( - huh.NewInput(). - Key("imgUrl"). - Description("The URL of the image to generate a proxy for."). - Title("Image URL"). - Value(m.url). - Prompt("Enter the image URL:"), - - huh.NewMultiSelect[UrlParam](). - Description("Params to add to the URL."). - Options(huhOptions...). - Value(m.selectedParams), - huh.NewSelect[generator.Format](). - Description("Convert the image format."). - Options( - huh.NewOption[generator.Format]("JPEG", generator.JPG), - huh.NewOption[generator.Format]("PNG", generator.PNG), - huh.NewOption[generator.Format]("BMP", generator.BMP), - huh.NewOption[generator.Format]("Default", generator.DEF), - ). - Key("format"). - Title("Format"). - Value(m.format), - ), - m.selectedOptionFields(), - ).WithShowHelp(false) - - m.Form = form + m.Fields = fields cfg, _ := config.NewConfig(c.String("config")) @@ -98,20 +63,62 @@ func InitialModel(c *cli.Context) Model { return m } -func (m Model) selectedOptionFields() *huh.Group { +func (m Model) initialFields() []huh.Field { + fields := make([]huh.Field, 0) - if m.selectedParams == nil || len(*m.selectedParams) == 0 { - return huh.NewGroup( - huh.NewText().Description("No params selected.").Title("Params").CharLimit(0), - ) + options := []UrlParam{ + NewHeight(), + NewWidth(), } - for _, param := range *m.selectedParams { - fields = append(fields, param.Input()) + var huhOptions []huh.Option[UrlParam] + for _, option := range options { + huhOptions = append(huhOptions, huh.NewOption[UrlParam](option.display(), option)) } - return huh.NewGroup(fields...) + fields = append(fields, + huh.NewInput(). + Key("imgUrl"). + Description("The URL of the image to generate a proxy for."). + Title("Image URL"). + Value(m.url). + Prompt("Enter the image URL:"), + ) + fields = append(fields, + huh.NewMultiSelect[UrlParam](). + Description("Params to add to the URL."). + Options(huhOptions...). + Value(m.selectedParams). + WithKeyMap(&huh.KeyMap{ + MultiSelect: huh.MultiSelectKeyMap{ + Up: key.NewBinding(key.WithKeys("up"), key.WithHelp("up", "up")), + Down: key.NewBinding(key.WithKeys("down"), key.WithHelp("down", "down")), + Toggle: key.NewBinding(key.WithKeys(" "), key.WithHelp(" ", "toggle")), + }, + }), + ) + + fields = append(fields, huh.NewSelect[generator.Format](). + Description("Convert the image format."). + Options( + huh.NewOption[generator.Format]("JPEG", generator.JPG), + huh.NewOption[generator.Format]("PNG", generator.PNG), + huh.NewOption[generator.Format]("BMP", generator.BMP), + huh.NewOption[generator.Format]("Default", generator.DEF), + ). + Key("format"). + Title("Format"). + Value(m.format). + WithKeyMap(&huh.KeyMap{ + Select: huh.SelectKeyMap{ + Up: key.NewBinding(key.WithKeys("up"), key.WithHelp("up", "up")), + Down: key.NewBinding(key.WithKeys("down"), key.WithHelp("down", "down")), + }, + }), + ) + + return fields } func (m Model) Init() tea.Cmd { diff --git a/interactive/params.go b/interactive/params.go index d570d69..e1f701f 100644 --- a/interactive/params.go +++ b/interactive/params.go @@ -1,45 +1,84 @@ package interactive -import "github.com/charmbracelet/huh" +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/charmbracelet/huh" +) + +/** + * Height + */ type Height struct { - UrlParam - paramValue string + paramValue *string + field *huh.Input +} + +func NewHeight() *Height { + h := &Height{ + paramValue: aws.String(""), + field: huh.NewInput(). + Key("h"). + Description("The height of the image."). + Title("Height"), + } + + h.field.Value(h.paramValue) + + return h +} + +func (h Height) display() string { + return "height" } func (h Height) value() string { - return "height" + return *h.paramValue } func (h Height) key() string { return "h" } -func (h Height) Input() *huh.Input { - return huh.NewInput(). - Key(h.key()). - Description("The height of the image."). - Title("Height"). - Value(&h.paramValue) +func (h Height) Input() huh.Field { + return h.field } type Width struct { - UrlParam - paramValue string + paramValue *string + field *huh.Input } -func (h Width) value() string { +/** + * Width + */ + +func NewWidth() *Width { + w := &Width{ + paramValue: aws.String(""), + field: huh.NewInput(). + Key("h"). + Description("The width of the image."). + Title("With"), + } + + w.field.Value(w.paramValue) + + return w +} + +func (h Width) display() string { return "width" } -func (h Width) key() string { - return "w" +func (h Width) value() string { + return *h.paramValue } -func (h Width) Input() *huh.Input { - return huh.NewInput(). - Key(h.key()). - Description("The width of the image."). - Title("Width"). - Value(&h.paramValue) +func (h Width) key() string { + return "h" +} + +func (h Width) Input() huh.Field { + return h.field } diff --git a/interactive/update.go b/interactive/update.go index ef93a55..1b1ee08 100644 --- a/interactive/update.go +++ b/interactive/update.go @@ -7,31 +7,85 @@ import ( func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + if m.focusField == nil { + m.Fields[0].Focus() + m.focusField = m.Fields[0] + } + if msg, ok := msg.(tea.KeyMsg); ok { switch msg.String() { case "tab": - if m.Form.GetFocusedField().GetKey() == "format" { - return m, m.Form.NextGroup() - } + if m.focusField != nil { + // get the index of the current field + index := -1 - c := m.Form.NextField() - return m, c - case "shift+tab": - if m.Form.GetFocusedField().GetKey() == "imgUrl" { - return m, nil - } + if m.inParamsFields { + for i, field := range *m.selectedParams { + if field.Input() == m.focusField { + index = i + break + } + } + } else { + for i, field := range m.Fields { + if field == m.focusField { + index = i + break + } + } + } - c := m.Form.PrevField() - return m, c + // if the field is not found, return + if index == -1 { + return m, nil + } + + // if the field is the last one, and we have params selected go to the param fields + if !m.inParamsFields && index == len(m.Fields)-1 && len(*m.selectedParams) > 0 { + m.focusField.Blur() + m.inParamsFields = true + paramsFields := *m.selectedParams + m.focusField = paramsFields[0].Input() + m.focusField.Focus() + + // if the field is the last one, and we have params selected go to the first non params field + } else if m.inParamsFields && index == len(*m.selectedParams)-1 { + m.focusField.Blur() + m.inParamsFields = false + m.focusField = m.Fields[0] + m.focusField.Focus() + + // if not in the params fields and the field is the last one, go to the first one + } else if index == len(m.Fields)-1 && !m.inParamsFields { + m.focusField.Blur() + m.focusField = m.Fields[0] + m.focusField.Focus() + } else { + // otherwise, go to the next field + m.focusField.Blur() + if m.inParamsFields { + paramsFields := *m.selectedParams + m.focusField = paramsFields[index+1].Input() + } else { + m.focusField = m.Fields[index+1] + } + m.focusField.Focus() + } + } case "ctrl+c", "esc": return m, tea.Quit case "enter": return m, nil default: - form, cmd := m.Form.Update(msg) - m.Form = form.(*huh.Form) + if m.focusField != nil { + md, cmd := m.focusField.(huh.Field).Update(msg) - return m, cmd + if md != nil { + m.focusField = md.(huh.Field) + } + + return m, cmd + } } } diff --git a/interactive/view.go b/interactive/view.go index a714e35..8dbd2d8 100644 --- a/interactive/view.go +++ b/interactive/view.go @@ -13,21 +13,30 @@ func (m Model) View() string { Underline(true). Render("Welcome to the img-proxy URL Generator!") + "\n\n" - if m.Form == nil { - return "" - } - if m.err != nil { return output + "Error: " + m.err.Error() + "\n" + "Press Ctrl+C to exit.\n" } - output = output + m.Form.View() + "\n" + for _, field := range m.Fields { + output += field.View() + "\n\n" + } + + for _, field := range *m.selectedParams { + output += field.Input().View() + "\n\n" + } if *m.url == "" { return output + help() } - url, _ := m.generator.GenerateUrl(*m.url, []string{}, *m.format) + params := make([]string, 0) + for _, field := range *m.selectedParams { + if field.value() != "" { + params = append(params, field.key()+":"+field.value()) + } + } + + url, _ := m.generator.GenerateUrl(*m.url, params, *m.format) output += fmt.Sprintf("\nGenerated URL: %s\n\n", lipgloss.NewStyle(). Bold(true).