@@ -26,7 +26,6 @@ use tracing::instrument;
2626
2727mod stdin;
2828use stdin:: GhciStdin ;
29- use stdin:: StdinEvent ;
3029
3130mod stdout;
3231use stdout:: GhciStdout ;
@@ -62,13 +61,10 @@ pub struct Ghci {
6261 /// The running `ghci` process.
6362 process : Child ,
6463 /// The handle for the stdout reader task.
65- stdout : JoinHandle < miette:: Result < ( ) > > ,
64+ stdout_handle : JoinHandle < miette:: Result < ( ) > > ,
6665 /// The handle for the stderr reader task.
67- stderr : JoinHandle < miette:: Result < ( ) > > ,
68- /// The handle for the stdin interaction task.
69- stdin : JoinHandle < miette:: Result < ( ) > > ,
70- /// A channel for sending events to interact with the stdin task.
71- stdin_channel : mpsc:: Sender < StdinEvent > ,
66+ stderr_handle : JoinHandle < miette:: Result < ( ) > > ,
67+ stdin : GhciStdin ,
7268 /// Count of 'sync' events sent. This lets us sync stdin/stdout -- we write a message to stdin
7369 /// instructing `ghci` to print a sentinel string, and wait to read that string on `stdout`.
7470 sync_count : AtomicUsize ,
@@ -121,7 +117,6 @@ impl Ghci {
121117 let stderr = child. stderr . take ( ) . unwrap ( ) ;
122118
123119 // TODO: Is this a good capacity? Maybe it should just be 1.
124- let ( stdin_sender, stdin_receiver) = mpsc:: channel ( 8 ) ;
125120 let ( stdout_sender, stdout_receiver) = mpsc:: channel ( 8 ) ;
126121 let ( stderr_sender, stderr_receiver) = mpsc:: channel ( 8 ) ;
127122
@@ -130,23 +125,28 @@ impl Ghci {
130125 // then create weak pointers to it and swap out the tasks.
131126 let stdout_handle = task:: spawn ( async { Ok ( ( ) ) } ) ;
132127 let stderr_handle = task:: spawn ( async { Ok ( ( ) ) } ) ;
133- let stdin_handle = task:: spawn ( async { Ok ( ( ) ) } ) ;
128+
129+ let stdin =
130+ GhciStdin {
131+ stdin,
132+ stdout_sender : stdout_sender. clone ( ) ,
133+ stderr_sender : stderr_sender. clone ( ) ,
134+ } ;
134135
135136 let mut ret = Ghci {
136137 command : command_arc,
137138 process : child,
138- stdout : stdout_handle,
139- stderr : stderr_handle,
140- stdin : stdin_handle,
141- stdin_channel : stdin_sender. clone ( ) ,
139+ stdout_handle,
140+ stderr_handle,
141+ stdin,
142142 sync_count : AtomicUsize :: new ( 0 ) ,
143143 modules : Default :: default ( ) ,
144144 error_path : error_path. clone ( ) ,
145145 setup_commands : setup_commands. clone ( ) ,
146146 test_command,
147147 } ;
148148
149- // Three tasks for my three beautiful streams.
149+ // Two tasks for my two beautiful streams.
150150 let stdout = task:: spawn (
151151 GhciStdout {
152152 reader : IncrementalReader :: new ( stdout) . with_writer ( tokio:: io:: stdout ( ) ) ,
@@ -173,21 +173,11 @@ impl Ghci {
173173 }
174174 . run ( ) ,
175175 ) ;
176- let stdin = task:: spawn (
177- GhciStdin {
178- stdin,
179- stdout_sender : stdout_sender. clone ( ) ,
180- stderr_sender : stderr_sender. clone ( ) ,
181- receiver : stdin_receiver,
182- }
183- . run ( ) ,
184- ) ;
185176
186177 // Now, replace the `JoinHandle`s with the actual values.
187178 {
188- ret. stdout = stdout;
189- ret. stderr = stderr;
190- ret. stdin = stdin;
179+ ret. stdout_handle = stdout;
180+ ret. stderr_handle = stderr;
191181 } ;
192182
193183 // Wait for the stdout job to start up.
@@ -207,13 +197,7 @@ impl Ghci {
207197 let span = tracing:: debug_span!( "Start-of-session initialization" ) ;
208198 let _enter = span. enter ( ) ;
209199 let ( sender, receiver) = oneshot:: channel ( ) ;
210- stdin_sender
211- . send ( StdinEvent :: Initialize {
212- sender,
213- setup_commands,
214- } )
215- . await
216- . into_diagnostic ( ) ?;
200+ ret. stdin . initialize ( sender, setup_commands) . await ?;
217201 receiver. await . into_diagnostic ( ) ?;
218202 }
219203
@@ -317,10 +301,7 @@ impl Ghci {
317301 format_bulleted_list( & needs_reload)
318302 ) ;
319303 let ( sender, receiver) = oneshot:: channel ( ) ;
320- self . stdin_channel
321- . send ( StdinEvent :: Reload ( sender) )
322- . await
323- . into_diagnostic ( ) ?;
304+ self . stdin . reload ( sender) . await ?;
324305 let reload_result = receiver. await . into_diagnostic ( ) ?;
325306 if let Some ( CompilationResult :: Err ) = reload_result {
326307 compilation_failed = true ;
@@ -333,13 +314,7 @@ impl Ghci {
333314 } else {
334315 // If we loaded or reloaded any modules, we should run tests.
335316 let ( sender, receiver) = oneshot:: channel ( ) ;
336- self . stdin_channel
337- . send ( StdinEvent :: Test {
338- sender,
339- test_command : self . test_command . clone ( ) ,
340- } )
341- . await
342- . into_diagnostic ( ) ?;
317+ self . stdin . test ( sender, self . test_command . clone ( ) ) . await ?;
343318 receiver. await . into_diagnostic ( ) ?;
344319 }
345320 }
@@ -352,27 +327,18 @@ impl Ghci {
352327 /// Sync the input and output streams of this `ghci` session. This will block until all input
353328 /// written to the `ghci` process's stdin has been read and processed.
354329 #[ instrument( skip_all, level = "debug" ) ]
355- pub async fn sync ( & self ) -> miette:: Result < ( ) > {
330+ pub async fn sync ( & mut self ) -> miette:: Result < ( ) > {
356331 let ( sentinel, receiver) = SyncSentinel :: new ( & self . sync_count ) ;
357- self . stdin_channel
358- . send ( StdinEvent :: Sync ( sentinel) )
359- . await
360- . into_diagnostic ( ) ?;
332+ self . stdin . sync ( sentinel) . await ?;
361333 receiver. await . into_diagnostic ( ) ?;
362334 Ok ( ( ) )
363335 }
364336
365337 /// Run the user provided test command.
366338 #[ instrument( skip_all, level = "debug" ) ]
367- pub async fn test ( & self ) -> miette:: Result < ( ) > {
339+ pub async fn test ( & mut self ) -> miette:: Result < ( ) > {
368340 let ( sender, receiver) = oneshot:: channel ( ) ;
369- self . stdin_channel
370- . send ( StdinEvent :: Test {
371- sender,
372- test_command : self . test_command . clone ( ) ,
373- } )
374- . await
375- . into_diagnostic ( ) ?;
341+ self . stdin . test ( sender, self . test_command . clone ( ) ) . await ?;
376342 receiver. await . into_diagnostic ( ) ?;
377343 Ok ( ( ) )
378344 }
@@ -381,10 +347,7 @@ impl Ghci {
381347 #[ instrument( skip_all, level = "debug" ) ]
382348 pub async fn refresh_modules ( & mut self ) -> miette:: Result < ( ) > {
383349 let ( sender, receiver) = oneshot:: channel ( ) ;
384- self . stdin_channel
385- . send ( StdinEvent :: ShowModules ( sender) )
386- . await
387- . into_diagnostic ( ) ?;
350+ self . stdin . show_modules ( sender) . await ?;
388351 let map = receiver. await . into_diagnostic ( ) ?;
389352 self . modules = map;
390353 tracing:: debug!(
@@ -403,10 +366,7 @@ impl Ghci {
403366 path : Utf8PathBuf ,
404367 ) -> miette:: Result < Option < CompilationResult > > {
405368 let ( sender, receiver) = oneshot:: channel ( ) ;
406- self . stdin_channel
407- . send ( StdinEvent :: AddModule ( path. clone ( ) , sender) )
408- . await
409- . into_diagnostic ( ) ?;
369+ self . stdin . add_module ( path. clone ( ) , sender) . await ?;
410370 let result = receiver. await . into_diagnostic ( ) ?;
411371 match result {
412372 None => {
@@ -430,9 +390,8 @@ impl Ghci {
430390 async fn stop ( & mut self ) -> miette:: Result < ( ) > {
431391 // TODO: Worth canceling the `mpsc::Receiver`s in the tasks here?
432392 // I'd need to add events for it.
433- self . stdout . abort ( ) ;
434- self . stderr . abort ( ) ;
435- self . stdin . abort ( ) ;
393+ self . stdout_handle . abort ( ) ;
394+ self . stderr_handle . abort ( ) ;
436395
437396 // Kill the old `ghci` process.
438397 // TODO: Worth trying `SIGINT` or closing stdin here?
0 commit comments