@@ -6,8 +6,8 @@ use crossterm::{
6
6
terminal, QueueableCommand ,
7
7
} ;
8
8
use std:: {
9
- io:: { self , StdoutLock , Write } ,
10
- sync:: mpsc:: Sender ,
9
+ io:: { self , Read , StdoutLock , Write } ,
10
+ sync:: mpsc:: { sync_channel , Sender , SyncSender } ,
11
11
thread,
12
12
} ;
13
13
@@ -34,6 +34,7 @@ pub struct WatchState<'a> {
34
34
done_status : DoneStatus ,
35
35
manual_run : bool ,
36
36
term_width : u16 ,
37
+ terminal_event_unpause_sender : SyncSender < ( ) > ,
37
38
}
38
39
39
40
impl < ' a > WatchState < ' a > {
@@ -46,8 +47,16 @@ impl<'a> WatchState<'a> {
46
47
. context ( "Failed to get the terminal size" ) ?
47
48
. 0 ;
48
49
50
+ let ( terminal_event_unpause_sender, terminal_event_unpause_receiver) = sync_channel ( 0 ) ;
51
+
49
52
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
+ } )
51
60
. context ( "Failed to spawn a thread to handle terminal events" ) ?;
52
61
53
62
Ok ( Self {
@@ -57,6 +66,7 @@ impl<'a> WatchState<'a> {
57
66
done_status : DoneStatus :: Pending ,
58
67
manual_run,
59
68
term_width,
69
+ terminal_event_unpause_sender,
60
70
} )
61
71
}
62
72
@@ -95,6 +105,44 @@ impl<'a> WatchState<'a> {
95
105
Ok ( ( ) )
96
106
}
97
107
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
+
98
146
pub fn handle_file_change (
99
147
& mut self ,
100
148
exercise_ind : usize ,
@@ -117,13 +165,6 @@ impl<'a> WatchState<'a> {
117
165
}
118
166
119
167
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
-
127
168
if self . done_status != DoneStatus :: Pending {
128
169
stdout. queue ( SetAttribute ( Attribute :: Bold ) ) ?;
129
170
stdout. write_all ( b"n" ) ?;
@@ -135,6 +176,13 @@ impl<'a> WatchState<'a> {
135
176
stdout. write_all ( b" / " ) ?;
136
177
}
137
178
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
+
138
186
if !self . show_hint {
139
187
stdout. queue ( SetAttribute ( Attribute :: Bold ) ) ?;
140
188
stdout. write_all ( b"h" ) ?;
@@ -147,6 +195,11 @@ impl<'a> WatchState<'a> {
147
195
stdout. queue ( ResetColor ) ?;
148
196
stdout. write_all ( b":list / " ) ?;
149
197
198
+ stdout. queue ( SetAttribute ( Attribute :: Bold ) ) ?;
199
+ stdout. write_all ( b"x" ) ?;
200
+ stdout. queue ( ResetColor ) ?;
201
+ stdout. write_all ( b":reset / " ) ?;
202
+
150
203
stdout. queue ( SetAttribute ( Attribute :: Bold ) ) ?;
151
204
stdout. write_all ( b"q" ) ?;
152
205
stdout. queue ( ResetColor ) ?;
0 commit comments