diff --git a/prompt.go b/prompt.go index 8e35123..d5b9d8b 100644 --- a/prompt.go +++ b/prompt.go @@ -4,6 +4,7 @@ import ( "fmt" "io" "strings" + "sync" "text/template" "github.com/chzyer/readline" @@ -113,6 +114,9 @@ type PromptTemplates struct { // Run will keep the prompt alive until it has been canceled from the command prompt or it has received a valid // value. It will return the value and an error if any occurred during the prompt's execution. func (p *Prompt) Run() (string, error) { + mutex := new(sync.Mutex) + closing := false + var err error err = p.prepareTemplates() @@ -159,6 +163,13 @@ func (p *Prompt) Run() (string, error) { cur := NewCursor(input, p.Pointer, eraseDefault) listen := func(input []rune, pos int, key rune) ([]rune, int, bool) { + mutex.Lock() + defer mutex.Unlock() + + if closing { + return nil, 0, false + } + _, _, keepOn := cur.Listen(input, pos, key) err := validFn(cur.Get()) var prompt []byte @@ -193,6 +204,7 @@ func (p *Prompt) Run() (string, error) { for { _, err = rl.Readline() + mutex.Lock() inputErr = validFn(cur.Get()) if inputErr == nil { break @@ -201,8 +213,12 @@ func (p *Prompt) Run() (string, error) { if err != nil { break } + mutex.Unlock() } + defer mutex.Unlock() + closing = true + if err != nil { switch err { case readline.ErrInterrupt: diff --git a/select.go b/select.go index b58ed97..ca59838 100644 --- a/select.go +++ b/select.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "os" + "sync" "text/tabwriter" "text/template" @@ -220,6 +221,9 @@ func (s *Select) RunCursorAt(cursorPos, scroll int) (int, string, error) { } func (s *Select) innerRun(cursorPos, scroll int, top rune) (int, string, error) { + mutex := new(sync.Mutex) + closing := false + c := &readline.Config{ Stdin: s.Stdin, Stdout: s.Stdout, @@ -254,6 +258,13 @@ func (s *Select) innerRun(cursorPos, scroll int, top rune) (int, string, error) s.list.SetStart(scroll) c.SetListener(func(line []rune, pos int, key rune) ([]rune, int, bool) { + mutex.Lock() + defer mutex.Unlock() + + if closing { + return nil, 0, false + } + switch { case key == KeyEnter: return nil, 0, true @@ -373,6 +384,10 @@ func (s *Select) innerRun(cursorPos, scroll int, top rune) (int, string, error) } + mutex.Lock() + defer mutex.Unlock() + closing = true + if err != nil { if err.Error() == "Interrupt" { err = ErrInterrupt