okami.mom/albedo
git clone https://git.nkp.pet/okami.mom/albedo
8101869
main
1package tui 2 3import ( 4"strings" 5 6 tea"charm.land/bubbletea/v2" 7"github.com/charmbracelet/x/ansi" 8) 9 10// confirm is the one way a screen asks before something far-reaching: 11// enter does it, esc leaves it, and every other key is ignored, so a stray 12// press while you read the question changes nothing. 13type confirm struct { 14prompt string // what will happen, and the question 15verb string // what enter does, in the hint 16what string // which action this asks about; the screen dispatches on it 17target string // what the action applies to 18failed bool // the last attempt failed, so enter retries 19} 20 21func (c confirm )asking ()bool {return c .prompt != "" } 22 23func (c * confirm )ask (what ,target ,verb ,prompt string ) { 24* c = confirm {prompt :prompt ,verb :verb ,what :what ,target :target } 25} 26 27func (c * confirm )dismiss () {* c = confirm {} } 28 29// key settles a key press while asking: yes on enter, dismissed on esc, 30// and ignored otherwise. It reports whether the key was for the question. 31func (c * confirm )key (msg tea.KeyPressMsg ) (yes bool ) { 32switch msg .String () { 33case "enter" : 34return true 35case "esc" ,"ctrl+c" : 36c .dismiss () 37 } 38return false 39} 40 41// footer is the question, the last failure if there was one, and the keys. 42func (c confirm )footer (width int ,failure string )string { 43var rows []string 44for line := range strings .SplitSeq (ansi .Wrap (c .prompt ,max (1 ,width - 1 )," " ),"\n" ) { 45rows = append (rows ," " + DefaultStyles .Warning .Render (line )) 46 } 47if failure != "" { 48rows = append (rows ," " + DefaultStyles .Error .Render (ansi .Truncate (failure ,max (1 ,width - 1 ),"…" ))) 49 } 50verb := c .verb 51if c .failed || failure != "" { 52verb = "retry" 53 } 54return strings .Join (append (rows ," " + keyHints (hint {"enter" ,verb },hint {"esc" ,"cancel" })),"\n" ) 55}