mirror of
https://github.com/charmbracelet/gum
synced 2024-04-30 05:32:52 +02:00
feat: huh gum write (#525)
This commit is contained in:
parent
2f0ea96504
commit
4d5d53169e
|
@ -2,15 +2,10 @@ package write
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/bubbles/textarea"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
|
||||
"github.com/charmbracelet/gum/cursor"
|
||||
"github.com/charmbracelet/gum/internal/exit"
|
||||
"github.com/charmbracelet/gum/internal/stdin"
|
||||
"github.com/charmbracelet/huh"
|
||||
)
|
||||
|
||||
// Run provides a shell script interface for the text area bubble.
|
||||
|
@ -21,48 +16,33 @@ func (o Options) Run() error {
|
|||
o.Value = strings.ReplaceAll(in, "\r", "")
|
||||
}
|
||||
|
||||
a := textarea.New()
|
||||
a.Focus()
|
||||
var value = o.Value
|
||||
|
||||
a.Prompt = o.Prompt
|
||||
a.Placeholder = o.Placeholder
|
||||
a.ShowLineNumbers = o.ShowLineNumbers
|
||||
a.CharLimit = o.CharLimit
|
||||
theme := huh.ThemeCharm()
|
||||
theme.Focused.Base = o.BaseStyle.ToLipgloss()
|
||||
theme.Focused.TextInput.Cursor = o.CursorStyle.ToLipgloss()
|
||||
theme.Focused.Title = o.HeaderStyle.ToLipgloss()
|
||||
theme.Focused.TextInput.Placeholder = o.PlaceholderStyle.ToLipgloss()
|
||||
theme.Focused.TextInput.Prompt = o.PromptStyle.ToLipgloss()
|
||||
|
||||
style := textarea.Style{
|
||||
Base: o.BaseStyle.ToLipgloss(),
|
||||
Placeholder: o.PlaceholderStyle.ToLipgloss(),
|
||||
CursorLine: o.CursorLineStyle.ToLipgloss(),
|
||||
CursorLineNumber: o.CursorLineNumberStyle.ToLipgloss(),
|
||||
EndOfBuffer: o.EndOfBufferStyle.ToLipgloss(),
|
||||
LineNumber: o.LineNumberStyle.ToLipgloss(),
|
||||
Prompt: o.PromptStyle.ToLipgloss(),
|
||||
}
|
||||
err := huh.NewForm(
|
||||
huh.NewGroup(
|
||||
huh.NewText().
|
||||
Title(o.Header).
|
||||
Placeholder(o.Placeholder).
|
||||
CharLimit(o.CharLimit).
|
||||
ShowLineNumbers(o.ShowLineNumbers).
|
||||
Value(&value),
|
||||
),
|
||||
).
|
||||
WithWidth(o.Width).
|
||||
WithHeight(o.Height).
|
||||
WithShowHelp(false).Run()
|
||||
|
||||
a.BlurredStyle = style
|
||||
a.FocusedStyle = style
|
||||
a.Cursor.Style = o.CursorStyle.ToLipgloss()
|
||||
a.Cursor.SetMode(cursor.Modes[o.CursorMode])
|
||||
|
||||
a.SetWidth(o.Width)
|
||||
a.SetHeight(o.Height)
|
||||
a.SetValue(o.Value)
|
||||
|
||||
p := tea.NewProgram(model{
|
||||
textarea: a,
|
||||
header: o.Header,
|
||||
headerStyle: o.HeaderStyle.ToLipgloss(),
|
||||
autoWidth: o.Width < 1,
|
||||
}, tea.WithOutput(os.Stderr))
|
||||
tm, err := p.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to run write: %w", err)
|
||||
}
|
||||
m := tm.(model)
|
||||
if m.aborted {
|
||||
return exit.ErrAborted
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(m.textarea.Value())
|
||||
fmt.Println(value)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -15,13 +15,14 @@ type Options struct {
|
|||
CharLimit int `help:"Maximum value length (0 for no limit)" default:"400"`
|
||||
CursorMode string `prefix:"cursor." name:"mode" help:"Cursor mode" default:"blink" enum:"blink,hide,static" env:"GUM_WRITE_CURSOR_MODE"`
|
||||
|
||||
BaseStyle style.Styles `embed:"" prefix:"base." envprefix:"GUM_WRITE_BASE_"`
|
||||
CursorLineNumberStyle style.Styles `embed:"" prefix:"cursor-line-number." set:"defaultForeground=7" envprefix:"GUM_WRITE_CURSOR_LINE_NUMBER_"`
|
||||
CursorLineStyle style.Styles `embed:"" prefix:"cursor-line." envprefix:"GUM_WRITE_CURSOR_LINE_"`
|
||||
CursorStyle style.Styles `embed:"" prefix:"cursor." set:"defaultForeground=212" envprefix:"GUM_WRITE_CURSOR_"`
|
||||
BaseStyle style.Styles `embed:"" prefix:"base." envprefix:"GUM_WRITE_BASE_"`
|
||||
CursorStyle style.Styles `embed:"" prefix:"cursor." set:"defaultForeground=212" envprefix:"GUM_WRITE_CURSOR_"`
|
||||
HeaderStyle style.Styles `embed:"" prefix:"header." set:"defaultForeground=240" envprefix:"GUM_WRITE_HEADER_"`
|
||||
PlaceholderStyle style.Styles `embed:"" prefix:"placeholder." set:"defaultForeground=240" envprefix:"GUM_WRITE_PLACEHOLDER_"`
|
||||
PromptStyle style.Styles `embed:"" prefix:"prompt." set:"defaultForeground=7" envprefix:"GUM_WRITE_PROMPT_"`
|
||||
|
||||
EndOfBufferStyle style.Styles `embed:"" prefix:"end-of-buffer." set:"defaultForeground=0" envprefix:"GUM_WRITE_END_OF_BUFFER_"`
|
||||
LineNumberStyle style.Styles `embed:"" prefix:"line-number." set:"defaultForeground=7" envprefix:"GUM_WRITE_LINE_NUMBER_"`
|
||||
HeaderStyle style.Styles `embed:"" prefix:"header." set:"defaultForeground=240" envprefix:"GUM_WRITE_HEADER_"`
|
||||
PlaceholderStyle style.Styles `embed:"" prefix:"placeholder." set:"defaultForeground=240" envprefix:"GUM_WRITE_PLACEHOLDER_"`
|
||||
PromptStyle style.Styles `embed:"" prefix:"prompt." set:"defaultForeground=7" envprefix:"GUM_WRITE_PROMPT_"`
|
||||
CursorLineNumberStyle style.Styles `embed:"" prefix:"cursor-line-number." set:"defaultForeground=7" envprefix:"GUM_WRITE_CURSOR_LINE_NUMBER_"`
|
||||
CursorLineStyle style.Styles `embed:"" prefix:"cursor-line." envprefix:"GUM_WRITE_CURSOR_LINE_"`
|
||||
}
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
// Package write provides a shell script interface for the text area bubble.
|
||||
// https://github.com/charmbracelet/bubbles/tree/master/textarea
|
||||
//
|
||||
// It can be used to ask the user to write some long form of text (multi-line)
|
||||
// input. The text the user entered will be sent to stdout.
|
||||
// Text entry is completed with CTRL+D and aborted with CTRL+C or Escape.
|
||||
//
|
||||
// $ gum write > output.text
|
||||
package write
|
||||
|
||||
import (
|
||||
"github.com/charmbracelet/bubbles/textarea"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
type model struct {
|
||||
autoWidth bool
|
||||
aborted bool
|
||||
header string
|
||||
headerStyle lipgloss.Style
|
||||
quitting bool
|
||||
textarea textarea.Model
|
||||
}
|
||||
|
||||
func (m model) Init() tea.Cmd { return textarea.Blink }
|
||||
func (m model) View() string {
|
||||
if m.quitting {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Display the header above the text area if it is not empty.
|
||||
if m.header != "" {
|
||||
header := m.headerStyle.Render(m.header)
|
||||
return lipgloss.JoinVertical(lipgloss.Left, header, m.textarea.View())
|
||||
}
|
||||
|
||||
return m.textarea.View()
|
||||
}
|
||||
|
||||
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case tea.WindowSizeMsg:
|
||||
if m.autoWidth {
|
||||
m.textarea.SetWidth(msg.Width)
|
||||
}
|
||||
case tea.KeyMsg:
|
||||
switch msg.String() {
|
||||
case "ctrl+c":
|
||||
m.aborted = true
|
||||
m.quitting = true
|
||||
return m, tea.Quit
|
||||
case "ctrl+d", "esc":
|
||||
m.quitting = true
|
||||
return m, tea.Quit
|
||||
}
|
||||
}
|
||||
|
||||
var cmd tea.Cmd
|
||||
m.textarea, cmd = m.textarea.Update(msg)
|
||||
return m, cmd
|
||||
}
|
Loading…
Reference in a new issue