@@ -3,6 +3,8 @@ package keyboard
33import (
44 "fmt"
55 "os"
6+ "sync"
7+ "sync/atomic"
68
79 "github.com/containerd/console"
810
@@ -64,27 +66,39 @@ func stopListener() error {
6466// return false, nil // Return false to continue listening
6567// })
6668func Listen (onKeyPress func (key keys.Key ) (stop bool , err error )) error {
67- cancel := make (chan bool )
68- stopRoutine := false
69-
70- go func () {
71- for {
72- select {
73- case c := <- cancel :
74- if c {
75- return
69+ var (
70+ callbackMu sync.Mutex
71+ closeOnce sync.Once
72+ stopOnce sync.Once
73+ stopRoutine atomic.Bool
74+ )
75+
76+ stopped := make (chan struct {})
77+ stop := func () {
78+ stopOnce .Do (func () {
79+ stopRoutine .Store (true )
80+ closeOnce .Do (func () {
81+ closeInput ()
82+
83+ if inputTTY != nil {
84+ _ = inputTTY .Close ()
7685 }
86+ })
87+ close (stopped )
88+ })
89+ }
7790
78- case keyInfo := <- mockChannel :
79- stopRoutine , _ = onKeyPress (keyInfo )
80- if stopRoutine {
81- closeInput ()
91+ handleKeyPress := func (key keys.Key ) (bool , error ) {
92+ callbackMu .Lock ()
93+ defer callbackMu .Unlock ()
8294
83- _ = inputTTY . Close ( )
84- }
85- }
95+ shouldStop , err := onKeyPress ( key )
96+ if shouldStop {
97+ stop ()
8698 }
87- }()
99+
100+ return shouldStop , err
101+ }
88102
89103 err := startListener ()
90104 if err != nil {
@@ -93,28 +107,53 @@ func Listen(onKeyPress func(key keys.Key) (stop bool, err error)) error {
93107 }
94108 }
95109
96- for ! stopRoutine {
97- key , keyErr := getKeyPress ()
98- if keyErr != nil {
99- return keyErr
100- }
110+ cancel := make (chan struct {})
111+ var mockWG sync.WaitGroup
112+ mockWG .Add (1 )
113+
114+ go func () {
115+ defer mockWG .Done ()
101116
102- // check if returned key is empty
103- // if reflect.DeepEqual(key, keys.Key{}) {
104- // return nil
105- // }
117+ for {
118+ select {
119+ case <- cancel :
120+ return
106121
107- stop , stopErr := onKeyPress (key )
108- if stopErr != nil {
109- return stopErr
122+ case keyInfo := <- mockChannel :
123+ shouldStop , _ := handleKeyPress (keyInfo )
124+ if shouldStop {
125+ return
126+ }
127+ }
110128 }
129+ }()
111130
112- if stop {
113- closeInput ()
131+ defer func () {
132+ close (cancel )
133+ mockWG .Wait ()
134+ }()
135+
136+ if inputTTY == nil {
137+ <- stopped
138+ } else {
139+ for ! stopRoutine .Load () {
140+ key , keyErr := getKeyPress ()
141+ if keyErr != nil {
142+ return keyErr
143+ }
144+
145+ if stopRoutine .Load () {
146+ break
147+ }
114148
115- _ = inputTTY .Close ()
149+ shouldStop , stopErr := handleKeyPress (key )
150+ if stopErr != nil {
151+ return stopErr
152+ }
116153
117- break
154+ if shouldStop {
155+ break
156+ }
118157 }
119158 }
120159
@@ -123,8 +162,6 @@ func Listen(onKeyPress func(key keys.Key) (stop bool, err error)) error {
123162 return err
124163 }
125164
126- cancel <- true
127-
128165 return nil
129166}
130167
0 commit comments