@@ -6,8 +6,8 @@ use crossterm::{
66 terminal, QueueableCommand ,
77} ;
88use std:: {
9- io:: { self , StdoutLock , Write } ,
10- sync:: mpsc:: Sender ,
9+ io:: { self , Read , StdoutLock , Write } ,
10+ sync:: mpsc:: { sync_channel , Sender , SyncSender } ,
1111 thread,
1212} ;
1313
@@ -34,6 +34,7 @@ pub struct WatchState<'a> {
3434 done_status : DoneStatus ,
3535 manual_run : bool ,
3636 term_width : u16 ,
37+ terminal_event_unpause_sender : SyncSender < ( ) > ,
3738}
3839
3940impl < ' a > WatchState < ' a > {
@@ -46,8 +47,16 @@ impl<'a> WatchState<'a> {
4647 . context ( "Failed to get the terminal size" ) ?
4748 . 0 ;
4849
50+ let ( terminal_event_unpause_sender, terminal_event_unpause_receiver) = sync_channel ( 0 ) ;
51+
4952 thread:: Builder :: new ( )
50- . spawn ( move || terminal_event_handler ( watch_event_sender, manual_run) )
53+ . spawn ( move || {
54+ terminal_event_handler (
55+ watch_event_sender,
56+ terminal_event_unpause_receiver,
57+ manual_run,
58+ )
59+ } )
5160 . context ( "Failed to spawn a thread to handle terminal events" ) ?;
5261
5362 Ok ( Self {
@@ -57,6 +66,7 @@ impl<'a> WatchState<'a> {
5766 done_status : DoneStatus :: Pending ,
5867 manual_run,
5968 term_width,
69+ terminal_event_unpause_sender,
6070 } )
6171 }
6272
@@ -95,6 +105,44 @@ impl<'a> WatchState<'a> {
95105 Ok ( ( ) )
96106 }
97107
108+ pub fn reset_exercise ( & mut self , stdout : & mut StdoutLock ) -> Result < ( ) > {
109+ clear_terminal ( stdout) ?;
110+
111+ stdout. write_all ( b"Resetting will undo all your changes to the file " ) ?;
112+ stdout. write_all ( self . app_state . current_exercise ( ) . path . as_bytes ( ) ) ?;
113+ stdout. write_all ( b"\n Reset (y/n)? " ) ?;
114+ stdout. flush ( ) ?;
115+
116+ {
117+ let mut stdin = io:: stdin ( ) . lock ( ) ;
118+ let mut answer = [ 0 ] ;
119+ loop {
120+ stdin
121+ . read_exact ( & mut answer)
122+ . context ( "Failed to read the user's input" ) ?;
123+
124+ match answer[ 0 ] {
125+ b'y' | b'Y' => {
126+ self . app_state . reset_current_exercise ( ) ?;
127+
128+ // The file watcher reruns the exercise otherwise.
129+ if self . manual_run {
130+ self . run_current_exercise ( stdout) ?;
131+ }
132+ }
133+ b'n' | b'N' => self . render ( stdout) ?,
134+ _ => continue ,
135+ }
136+
137+ break ;
138+ }
139+ }
140+
141+ self . terminal_event_unpause_sender . send ( ( ) ) ?;
142+
143+ Ok ( ( ) )
144+ }
145+
98146 pub fn handle_file_change (
99147 & mut self ,
100148 exercise_ind : usize ,
@@ -117,13 +165,6 @@ impl<'a> WatchState<'a> {
117165 }
118166
119167 fn show_prompt ( & self , stdout : & mut StdoutLock ) -> io:: Result < ( ) > {
120- if self . manual_run {
121- stdout. queue ( SetAttribute ( Attribute :: Bold ) ) ?;
122- stdout. write_all ( b"r" ) ?;
123- stdout. queue ( ResetColor ) ?;
124- stdout. write_all ( b":run / " ) ?;
125- }
126-
127168 if self . done_status != DoneStatus :: Pending {
128169 stdout. queue ( SetAttribute ( Attribute :: Bold ) ) ?;
129170 stdout. write_all ( b"n" ) ?;
@@ -135,6 +176,13 @@ impl<'a> WatchState<'a> {
135176 stdout. write_all ( b" / " ) ?;
136177 }
137178
179+ if self . manual_run {
180+ stdout. queue ( SetAttribute ( Attribute :: Bold ) ) ?;
181+ stdout. write_all ( b"r" ) ?;
182+ stdout. queue ( ResetColor ) ?;
183+ stdout. write_all ( b":run / " ) ?;
184+ }
185+
138186 if !self . show_hint {
139187 stdout. queue ( SetAttribute ( Attribute :: Bold ) ) ?;
140188 stdout. write_all ( b"h" ) ?;
@@ -147,6 +195,11 @@ impl<'a> WatchState<'a> {
147195 stdout. queue ( ResetColor ) ?;
148196 stdout. write_all ( b":list / " ) ?;
149197
198+ stdout. queue ( SetAttribute ( Attribute :: Bold ) ) ?;
199+ stdout. write_all ( b"x" ) ?;
200+ stdout. queue ( ResetColor ) ?;
201+ stdout. write_all ( b":reset / " ) ?;
202+
150203 stdout. queue ( SetAttribute ( Attribute :: Bold ) ) ?;
151204 stdout. write_all ( b"q" ) ?;
152205 stdout. queue ( ResetColor ) ?;
0 commit comments