Files
trufflehog/pkg/tui/components/confirm/confirm.go
Miccah 59fccbcf3f Analyze TUI (#3172)
* Setup TUI entrypoint

* Setup key type selector and form pages

* Add basic confirmation component

* Add basic list selector for analyzer type

* Add form page

* Remove quit confirmation

* Add styles

* Add input text redaction

* Add log file input to form

* Fix some bugs and race conditions

* Remove unused code

* Fix filtering bug
2024-08-05 15:00:46 -07:00

116 lines
2.7 KiB
Go

package confirm
import (
"fmt"
"unicode"
"github.com/charmbracelet/bubbles/key"
tea "github.com/charmbracelet/bubbletea"
"github.com/trufflesecurity/trufflehog/v3/pkg/tui/common"
)
type Confirm struct {
common common.Common
message string
affirmativeChoice string
negativeChoice string
affirmativeUpdate func() (tea.Model, tea.Cmd)
negativeUpdate func() (tea.Model, tea.Cmd)
choice bool
}
type Msg struct {
Choice bool
Message string
}
type ConfirmOpt func(*Confirm)
func WithAffirmativeMessage(msg string) ConfirmOpt {
return func(c *Confirm) { c.affirmativeChoice = msg }
}
func WithNegativeMessage(msg string) ConfirmOpt {
return func(c *Confirm) { c.negativeChoice = msg }
}
func WithDefault(choice bool) ConfirmOpt {
return func(c *Confirm) { c.choice = choice }
}
func WithAffirmativeTransition(m tea.Model, cmd tea.Cmd) ConfirmOpt {
return func(c *Confirm) {
c.affirmativeUpdate = func() (tea.Model, tea.Cmd) {
return m, cmd
}
}
}
func WithNegativeTransition(m tea.Model, cmd tea.Cmd) ConfirmOpt {
return func(c *Confirm) {
c.negativeUpdate = func() (tea.Model, tea.Cmd) {
return m, cmd
}
}
}
func New(c common.Common, msg string, opts ...ConfirmOpt) Confirm {
confirm := Confirm{
common: c,
message: msg,
affirmativeChoice: "Yes",
negativeChoice: "Cancel",
affirmativeUpdate: func() (tea.Model, tea.Cmd) { return nil, nil },
negativeUpdate: func() (tea.Model, tea.Cmd) { return nil, nil },
}
for _, opt := range opts {
opt(&confirm)
}
return confirm
}
func (Confirm) Init() tea.Cmd {
return nil
}
func (c Confirm) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
keyMsg, ok := msg.(tea.KeyMsg)
if !ok {
return c, nil
}
switch {
case key.Matches(keyMsg, c.common.KeyMap.Left) || keyMatchesFirstChar(keyMsg, c.negativeChoice):
c.choice = false
case key.Matches(keyMsg, c.common.KeyMap.Right) || keyMatchesFirstChar(keyMsg, c.affirmativeChoice):
c.choice = true
case key.Matches(keyMsg, c.common.KeyMap.Select):
model, cmd := c.negativeUpdate()
if c.choice {
model, cmd = c.affirmativeUpdate()
}
return model, cmd
}
return c, nil
}
func (c Confirm) View() string {
var affirmative, negative string
if c.choice {
affirmative = fmt.Sprintf("[ %s ]", c.affirmativeChoice)
negative = fmt.Sprintf(" %s ", c.negativeChoice)
} else {
affirmative = fmt.Sprintf(" %s ", c.affirmativeChoice)
negative = fmt.Sprintf("[ %s ]", c.negativeChoice)
}
return fmt.Sprintf("%s\t%s\t%s", c.message, negative, affirmative)
}
func keyMatchesFirstChar(msg tea.KeyMsg, s string) bool {
if s == "" {
return false
}
firstChar := rune(s[0])
return msg.String() == string(unicode.ToLower(firstChar))
}