@@ -101,13 +101,13 @@ func (ui *UI) SetIO(in io.Reader, out io.Writer) {
101101// Run creates a UI and associates the provided Engine to it.
102102// It then starts the UI. I/O must be provided for this call
103103// to not panic.
104- func Run (eng Engine , opts ... Option ) error {
104+ func Run (ctx context. Context , eng Engine , opts ... Option ) error {
105105 if eng == nil {
106106 return ErrNoEngine
107107 }
108108
109109 ui := NewUI (eng )
110- return ui .Run (opts ... )
110+ return ui .Run (ctx , opts ... )
111111}
112112
113113// minRead
@@ -116,11 +116,15 @@ const minRead = 512
116116// Run starts the user interface with the provided sources
117117// for input and output of the interpreter and engine.
118118// The prefix will be printed before every line.
119- func (ui * UI ) Run (opts ... Option ) (err error ) {
119+ func (ui * UI ) Run (ctx context. Context , opts ... Option ) (err error ) {
120120 // Make sure engine is set
121121 if ui .eng == nil {
122122 return ErrNoEngine
123123 }
124+ // Check if context is nil
125+ if ctx == nil {
126+ ctx = context .Background ()
127+ }
124128
125129 // Set options
126130 for _ , opt := range opts {
@@ -129,7 +133,9 @@ func (ui *UI) Run(opts ...Option) (err error) {
129133
130134 // Set signal handling
131135 var cancel func ()
132- ui .ctx , cancel = context .WithCancel (context .Background ())
136+ ui .ctx , cancel = context .WithCancel (ctx )
137+ defer cancel ()
138+ defer close (ui .sigs )
133139 go func () {
134140 for sig := range ui .sigs {
135141 handler , exists := ui .sigHandlers [sig ]
@@ -159,6 +165,7 @@ func (ui *UI) Run(opts ...Option) (err error) {
159165 }()
160166 defer close (ui .reqCh )
161167
168+ var n int
162169 for {
163170 // Write prefix
164171 _ , err = ui .Write (nil )
@@ -168,11 +175,11 @@ func (ui *UI) Run(opts ...Option) (err error) {
168175
169176 // Read line
170177 b := make ([]byte , minRead )
171- _ , err = ui .Read (b )
172- if err != nil {
173- if err == context . Canceled {
174- err = nil
175- }
178+ n , err = ui .Read (b )
179+ if err == context . Canceled {
180+ return nil
181+ }
182+ if err != nil && err != io . EOF || n == 0 {
176183 return
177184 }
178185
@@ -181,6 +188,11 @@ func (ui *UI) Run(opts ...Option) (err error) {
181188 if status != 0 {
182189 return
183190 }
191+
192+ // Check if we hit EOF on previous read
193+ if err == io .EOF {
194+ return
195+ }
184196 }
185197}
186198
@@ -219,7 +231,10 @@ type readResp struct {
219231func (ui * UI ) readAsync (b []byte , readCh chan readResp ) {
220232 var resp readResp
221233 resp .n , resp .err = ui .i .Read (b )
222- readCh <- resp
234+ select {
235+ case <- ui .ctx .Done ():
236+ case readCh <- resp :
237+ }
223238 close (readCh )
224239}
225240
0 commit comments