feat: huh for gum input (#524)

This commit is contained in:
Maas Lalani 2024-03-28 16:29:08 -04:00 committed by GitHub
parent 3a717104a9
commit 4a560b1953
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 109 deletions

View file

@ -2,13 +2,11 @@ package input
import ( import (
"fmt" "fmt"
"os"
"github.com/charmbracelet/bubbles/textinput" "github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/huh"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/gum/cursor"
"github.com/charmbracelet/gum/internal/exit"
"github.com/charmbracelet/gum/internal/stdin" "github.com/charmbracelet/gum/internal/stdin"
) )
@ -22,40 +20,41 @@ func (o Options) Run() error {
i.SetValue(in) i.SetValue(in)
} }
i.Focus() theme := huh.ThemeCharm()
i.Prompt = o.Prompt theme.Focused.Base = lipgloss.NewStyle()
i.Placeholder = o.Placeholder theme.Focused.TextInput.Cursor = o.CursorStyle.ToLipgloss()
i.Width = o.Width theme.Focused.TextInput.Placeholder = o.PlaceholderStyle.ToLipgloss()
i.PromptStyle = o.PromptStyle.ToLipgloss() theme.Focused.TextInput.Prompt = o.PromptStyle.ToLipgloss()
i.PlaceholderStyle = o.PlaceholderStyle.ToLipgloss() theme.Focused.Title = o.HeaderStyle.ToLipgloss()
i.Cursor.Style = o.CursorStyle.ToLipgloss()
i.Cursor.SetMode(cursor.Modes[o.CursorMode]) var value string
i.CharLimit = o.CharLimit var echoMode huh.EchoMode
if o.Password { if o.Password {
i.EchoMode = textinput.EchoPassword echoMode = huh.EchoModePassword
i.EchoCharacter = '•' } else {
echoMode = huh.EchoModeNormal
} }
p := tea.NewProgram(model{ err := huh.NewForm(
textinput: i, huh.NewGroup(
aborted: false, huh.NewInput().
header: o.Header, Prompt(o.Prompt).
headerStyle: o.HeaderStyle.ToLipgloss(), Placeholder(o.Placeholder).
timeout: o.Timeout, CharLimit(o.CharLimit).
hasTimeout: o.Timeout > 0, EchoMode(echoMode).
autoWidth: o.Width < 1, Title(o.Header).
}, tea.WithOutput(os.Stderr)) Value(&value),
tm, err := p.Run() ),
).
WithShowHelp(false).
WithTheme(theme).
Run()
if err != nil { if err != nil {
return fmt.Errorf("failed to run input: %w", err) return err
}
m := tm.(model)
if m.aborted {
return exit.ErrAborted
} }
fmt.Println(m.textinput.Value()) fmt.Println(value)
return nil return nil
} }

View file

@ -1,77 +0,0 @@
// Package input provides a shell script interface for the text input bubble.
// https://github.com/charmbracelet/bubbles/tree/master/textinput
//
// It can be used to prompt the user for some input. The text the user entered
// will be sent to stdout.
//
// $ gum input --placeholder "What's your favorite gum?" > answer.text
package input
import (
"time"
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/gum/timeout"
"github.com/charmbracelet/lipgloss"
)
type model struct {
autoWidth bool
header string
headerStyle lipgloss.Style
textinput textinput.Model
quitting bool
aborted bool
timeout time.Duration
hasTimeout bool
}
func (m model) Init() tea.Cmd {
return tea.Batch(
textinput.Blink,
timeout.Init(m.timeout, nil),
)
}
func (m model) View() string {
if m.quitting {
return ""
}
if m.header != "" {
header := m.headerStyle.Render(m.header)
return lipgloss.JoinVertical(lipgloss.Left, header, m.textinput.View())
}
return m.textinput.View()
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case timeout.TickTimeoutMsg:
if msg.TimeoutValue <= 0 {
m.quitting = true
m.aborted = true
return m, tea.Quit
}
m.timeout = msg.TimeoutValue
return m, timeout.Tick(msg.TimeoutValue, msg.Data)
case tea.WindowSizeMsg:
if m.autoWidth {
m.textinput.Width = msg.Width - lipgloss.Width(m.textinput.Prompt) - 1
}
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c", "esc":
m.quitting = true
m.aborted = true
return m, tea.Quit
case "enter":
m.quitting = true
return m, tea.Quit
}
}
var cmd tea.Cmd
m.textinput, cmd = m.textinput.Update(msg)
return m, cmd
}