mirror of
https://github.com/charmbracelet/gum
synced 2024-05-03 15:03:20 +02:00
feat: huh for gum input (#524)
This commit is contained in:
parent
3a717104a9
commit
4a560b1953
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in a new issue