mirror of
https://github.com/charmbracelet/gum
synced 2024-06-01 05:12:51 +02:00
feat: gum confirm
This commit is contained in:
parent
483da45749
commit
108a680385
30
confirm/command.go
Normal file
30
confirm/command.go
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package confirm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Run provides a shell script interface for prompting a user to confirm an
|
||||||
|
// action with an affirmative or negative answer.
|
||||||
|
func (o Options) Run() error {
|
||||||
|
m, err := tea.NewProgram(model{
|
||||||
|
affirmative: o.Affirmative,
|
||||||
|
negative: o.Negative,
|
||||||
|
vertical: o.Vertical,
|
||||||
|
selected: 0,
|
||||||
|
prompt: o.Prompt,
|
||||||
|
selectedStyle: o.SelectedStyle.ToLipgloss(),
|
||||||
|
unselectedStyle: o.UnselectedStyle.ToLipgloss(),
|
||||||
|
promptStyle: o.PromptStyle.ToLipgloss(),
|
||||||
|
}, tea.WithOutput(os.Stderr)).StartReturningModel()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Exit(m.(model).selected)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
84
confirm/confirm.go
Normal file
84
confirm/confirm.go
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
// Package confirm provides an interface to ask a user to confirm an action.
|
||||||
|
// The user is provided with an interface to choose an affirmative or negative
|
||||||
|
// answer, which is then reflected in the exit code for use in scripting.
|
||||||
|
//
|
||||||
|
// If the user selects the affirmative answer, the program exits with 0. If the
|
||||||
|
// user selects the negative answer, the program exits with 1.
|
||||||
|
//
|
||||||
|
// I.e. confirm if the user wants to delete a file
|
||||||
|
//
|
||||||
|
// $ gum confirm "Are you sure?" && rm file.txt
|
||||||
|
//
|
||||||
|
package confirm
|
||||||
|
|
||||||
|
import (
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
)
|
||||||
|
|
||||||
|
type model struct {
|
||||||
|
prompt string
|
||||||
|
affirmative string
|
||||||
|
negative string
|
||||||
|
vertical bool
|
||||||
|
quitting bool
|
||||||
|
selected int
|
||||||
|
|
||||||
|
// styles
|
||||||
|
promptStyle lipgloss.Style
|
||||||
|
selectedStyle lipgloss.Style
|
||||||
|
unselectedStyle lipgloss.Style
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m model) Init() tea.Cmd { return nil }
|
||||||
|
|
||||||
|
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
switch msg := msg.(type) {
|
||||||
|
case tea.WindowSizeMsg:
|
||||||
|
return m, nil
|
||||||
|
case tea.KeyMsg:
|
||||||
|
switch msg.String() {
|
||||||
|
case "left", "h", "ctrl+p":
|
||||||
|
m.selected = m.selected - 1
|
||||||
|
if m.selected < 0 {
|
||||||
|
m.selected = 1
|
||||||
|
}
|
||||||
|
case "right", "l", "ctrl+n":
|
||||||
|
m.selected = m.selected + 1
|
||||||
|
if m.selected > 1 {
|
||||||
|
m.selected = 0
|
||||||
|
}
|
||||||
|
case "enter":
|
||||||
|
m.quitting = true
|
||||||
|
return m, tea.Quit
|
||||||
|
case "ctrl+c", "q":
|
||||||
|
m.selected = 1
|
||||||
|
m.quitting = true
|
||||||
|
return m, tea.Quit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m model) View() string {
|
||||||
|
if m.quitting {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
joinFunc := lipgloss.JoinHorizontal
|
||||||
|
if m.vertical {
|
||||||
|
joinFunc = lipgloss.JoinVertical
|
||||||
|
}
|
||||||
|
|
||||||
|
var aff, neg string
|
||||||
|
|
||||||
|
if m.selected == 0 {
|
||||||
|
aff = m.selectedStyle.Render(m.affirmative)
|
||||||
|
neg = m.unselectedStyle.Render(m.negative)
|
||||||
|
} else {
|
||||||
|
aff = m.unselectedStyle.Render(m.affirmative)
|
||||||
|
neg = m.selectedStyle.Render(m.negative)
|
||||||
|
}
|
||||||
|
|
||||||
|
return lipgloss.JoinVertical(lipgloss.Center, m.promptStyle.Render(m.prompt), joinFunc(lipgloss.Left, aff, neg))
|
||||||
|
}
|
14
confirm/options.go
Normal file
14
confirm/options.go
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package confirm
|
||||||
|
|
||||||
|
import "github.com/charmbracelet/gum/style"
|
||||||
|
|
||||||
|
// Options is the customization options for the confirm command.
|
||||||
|
type Options struct {
|
||||||
|
Affirmative string `help:"The title of the affirmative action" default:"Yes"`
|
||||||
|
Negative string `help:"The title of the negative action" default:"No"`
|
||||||
|
Prompt string `arg:"" help:"Prompt to display." default:"Are you sure?"`
|
||||||
|
Vertical bool `help:"Whether to display the options vertically" default:"false"`
|
||||||
|
PromptStyle style.Styles `embed:"" prefix:"prompt." help:"The style of the prompt"`
|
||||||
|
UnselectedStyle style.Styles `embed:"" prefix:"unselected." help:"The style of the unselected action" set:"defaultBackground=0" set:"defaultPadding=0 3" set:"defaultMargin=1 1"`
|
||||||
|
SelectedStyle style.Styles `embed:"" prefix:"selected." help:"The style of the selected action" set:"defaultBackground=8" set:"defaultForeground=212" set:"defaultPadding=0 3" set:"defaultMargin=1 1"`
|
||||||
|
}
|
15
gum.go
15
gum.go
|
@ -3,6 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"github.com/charmbracelet/gum/choose"
|
"github.com/charmbracelet/gum/choose"
|
||||||
"github.com/charmbracelet/gum/completion"
|
"github.com/charmbracelet/gum/completion"
|
||||||
|
"github.com/charmbracelet/gum/confirm"
|
||||||
"github.com/charmbracelet/gum/filter"
|
"github.com/charmbracelet/gum/filter"
|
||||||
"github.com/charmbracelet/gum/format"
|
"github.com/charmbracelet/gum/format"
|
||||||
"github.com/charmbracelet/gum/input"
|
"github.com/charmbracelet/gum/input"
|
||||||
|
@ -34,6 +35,20 @@ type Gum struct {
|
||||||
//
|
//
|
||||||
Choose choose.Options `cmd:"" help:"Choose an option from a list of choices"`
|
Choose choose.Options `cmd:"" help:"Choose an option from a list of choices"`
|
||||||
|
|
||||||
|
// Confirm provides an interface to ask a user to confirm an action.
|
||||||
|
// The user is provided with an interface to choose an affirmative or
|
||||||
|
// negative answer, which is then reflected in the exit code for use in
|
||||||
|
// scripting.
|
||||||
|
//
|
||||||
|
// If the user selects the affirmative answer, the program exits with 0.
|
||||||
|
// If the user selects the negative answer, the program exits with 1.
|
||||||
|
//
|
||||||
|
// I.e. confirm if the user wants to delete a file
|
||||||
|
//
|
||||||
|
// $ gum confirm "Are you sure?" && rm file.txt
|
||||||
|
//
|
||||||
|
Confirm confirm.Options `cmd:"" help:"Ask a user to confirm an action"`
|
||||||
|
|
||||||
// Filter provides a fuzzy searching text input to allow filtering a list of
|
// Filter provides a fuzzy searching text input to allow filtering a list of
|
||||||
// options to select one option.
|
// options to select one option.
|
||||||
//
|
//
|
||||||
|
|
3
main.go
3
main.go
|
@ -25,6 +25,9 @@ func main() {
|
||||||
kong.Vars{
|
kong.Vars{
|
||||||
"defaultBackground": "",
|
"defaultBackground": "",
|
||||||
"defaultForeground": "",
|
"defaultForeground": "",
|
||||||
|
"defaultMargin": "0 0",
|
||||||
|
"defaultPadding": "0 0",
|
||||||
|
"defaultUnderline": "false",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
ctx.Run()
|
ctx.Run()
|
||||||
|
|
|
@ -22,5 +22,6 @@ func (s Styles) ToLipgloss() lipgloss.Style {
|
||||||
Bold(s.Bold).
|
Bold(s.Bold).
|
||||||
Faint(s.Faint).
|
Faint(s.Faint).
|
||||||
Italic(s.Italic).
|
Italic(s.Italic).
|
||||||
Strikethrough(s.Strikethrough)
|
Strikethrough(s.Strikethrough).
|
||||||
|
Underline(s.Underline)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,24 +18,25 @@ type Options struct {
|
||||||
// components, through embedding and prefixing.
|
// components, through embedding and prefixing.
|
||||||
type Styles struct {
|
type Styles struct {
|
||||||
// Colors
|
// Colors
|
||||||
Background string `help:"Background color of the ${name=element}" default:"${defaultBackground}" group:"Style Flags"`
|
Background string `help:"Background Color" default:"${defaultBackground}" group:"Style Flags"`
|
||||||
Foreground string `help:"color of the ${name=element}" default:"${defaultForeground}" group:"Style Flags"`
|
Foreground string `help:"Foreground Color" default:"${defaultForeground}" group:"Style Flags"`
|
||||||
|
|
||||||
// Border
|
// Border
|
||||||
Border string `help:"Border style to apply" enum:"none,hidden,normal,rounded,thick,double" default:"none" group:"Style Flags"`
|
Border string `help:"Border Style" enum:"none,hidden,normal,rounded,thick,double" default:"none" group:"Style Flags"`
|
||||||
BorderBackground string `help:"Border background color" group:"Style Flags"`
|
BorderBackground string `help:"Border Background Color" group:"Style Flags"`
|
||||||
BorderForeground string `help:"Border foreground color" group:"Style Flags"`
|
BorderForeground string `help:"Border Foreground Color" group:"Style Flags"`
|
||||||
|
|
||||||
// Layout
|
// Layout
|
||||||
Align string `help:"Text alignment" enum:"left,center,right,bottom,middle,top" default:"left" group:"Style Flags"`
|
Align string `help:"Text Alignment" enum:"left,center,right,bottom,middle,top" default:"left" group:"Style Flags"`
|
||||||
Height int `help:"Height of output" group:"Style Flags"`
|
Height int `help:"Text height" group:"Style Flags"`
|
||||||
Width int `help:"Width of output" group:"Style Flags"`
|
Width int `help:"Text width" group:"Style Flags"`
|
||||||
Margin string `help:"Margin to apply around the text." default:"0 0" group:"Style Flags"`
|
Margin string `help:"Text margin" default:"${defaultMargin}" group:"Style Flags"`
|
||||||
Padding string `help:"Padding to apply around the text." default:"0 0"`
|
Padding string `help:"Text padding" default:"${defaultPadding}" group:"Style Flags"`
|
||||||
|
|
||||||
// Format
|
// Format
|
||||||
Bold bool `help:"Apply bold formatting" group:"Style Flags"`
|
Bold bool `help:"Bold text" group:"Style Flags"`
|
||||||
Faint bool `help:"Apply faint formatting" group:"Style Flags"`
|
Faint bool `help:"Faint text" group:"Style Flags"`
|
||||||
Italic bool `help:"Apply italic formatting" group:"Style Flags"`
|
Italic bool `help:"Italicize text" group:"Style Flags"`
|
||||||
Strikethrough bool `help:"Apply strikethrough formatting" group:"Style Flags"`
|
Strikethrough bool `help:"Strikethrough text" group:"Style Flags"`
|
||||||
|
Underline bool `help:"Underline text" default:"${defaultUnderline}" group:"Style Flags"`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue