CheckIn/prompt.go

96 lines
2.2 KiB
Go

package main
import (
"errors"
"fmt"
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/muesli/termenv"
"os/user"
"strings"
)
// PromptInput prompts the user for input and returns either a well-formed status (leading ~user) or an empty string.
func PromptInput() (string, error) {
model, err := newInputModel()
if err != nil {
return "", err
}
p := tea.NewProgram(model)
err = p.Start()
if err != nil {
return "", err
}
return model.String(), nil
}
type inputModel struct {
// Contains the model of the child text entry widget
input textinput.Model
// The prompt presented to the user
prompt string
// Any error that occurs while processing.
Err error
}
// newInputModel creates a new inputModel ready for use, populated with a random prompt.
func newInputModel() (*inputModel, error) {
user, err := user.Current()
if err != nil {
return &inputModel{}, err
}
model := inputModel{}
model.prompt = fmt.Sprintf("What's ~%s up to?", user.Username)
model.input = textinput.NewModel()
// The input's Prompt is used to prepend an unchangeable prefix to the input.
model.input.Prompt = fmt.Sprintf("~%s", user.Username)
model.input.SetValue(" ")
model.input.CursorEnd()
model.input.Focus()
return &model, nil
}
// String will return either a valid status with all whitespace removed or a blank string.
func (m *inputModel) String() string {
output := strings.TrimRight(m.input.Value(), " \n\t\r")
if output == "" {
return output
}
return fmt.Sprintf("%s%s", m.input.Prompt, output)
}
func (m *inputModel) Init() tea.Cmd {
return textinput.Blink
}
func (m *inputModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.Type {
case tea.KeyCtrlC, tea.KeyEsc:
m.Err = errors.New("user cancelled input")
fallthrough
case tea.KeyCtrlD, tea.KeyEnter:
return m, tea.Quit
}
case error:
m.Err = msg
return m, tea.Quit
}
var cmd tea.Cmd
m.input, cmd = m.input.Update(msg)
return m, cmd
}
func (m *inputModel) View() string {
if termenv.ColorProfile() == termenv.Ascii {
return fmt.Sprintf("%s %s", m.prompt, m.input.View())
}
return fmt.Sprintf("%s %s", termenv.String(m.prompt).Bold(), m.input.View())
}