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