@@ -6,6 +6,7 @@ use clap::{Parser, Subcommand};
66use console:: Emoji ;
77use notify_debouncer_mini:: notify:: { self , RecursiveMode } ;
88use notify_debouncer_mini:: { new_debouncer, DebouncedEventKind } ;
9+ use shlex:: Shlex ;
910use std:: ffi:: OsStr ;
1011use std:: fs;
1112use std:: io:: { self , prelude:: * } ;
@@ -244,47 +245,49 @@ fn main() {
244245}
245246
246247fn spawn_watch_shell (
247- failed_exercise_hint : & Arc < Mutex < Option < String > > > ,
248+ failed_exercise_hint : Arc < Mutex < Option < String > > > ,
248249 should_quit : Arc < AtomicBool > ,
249250) {
250- let failed_exercise_hint = Arc :: clone ( failed_exercise_hint) ;
251251 println ! ( "Welcome to watch mode! You can type 'help' to get an overview of the commands you can use here." ) ;
252- thread:: spawn ( move || loop {
253- let mut input = String :: new ( ) ;
254- match io:: stdin ( ) . read_line ( & mut input) {
255- Ok ( _) => {
256- let input = input. trim ( ) ;
257- if input == "hint" {
258- if let Some ( hint) = & * failed_exercise_hint. lock ( ) . unwrap ( ) {
259- println ! ( "{hint}" ) ;
260- }
261- } else if input == "clear" {
262- println ! ( "\x1B [2J\x1B [1;1H" ) ;
263- } else if input. eq ( "quit" ) {
264- should_quit. store ( true , Ordering :: SeqCst ) ;
265- println ! ( "Bye!" ) ;
266- } else if input. eq ( "help" ) {
267- println ! ( "Commands available to you in watch mode:" ) ;
268- println ! ( " hint - prints the current exercise's hint" ) ;
269- println ! ( " clear - clears the screen" ) ;
270- println ! ( " quit - quits watch mode" ) ;
271- println ! ( " !<cmd> - executes a command, like `!rustc --explain E0381`" ) ;
272- println ! ( " help - displays this help message" ) ;
273- println ! ( ) ;
274- println ! ( "Watch mode automatically re-evaluates the current exercise" ) ;
275- println ! ( "when you edit a file's contents." )
276- } else if let Some ( cmd) = input. strip_prefix ( '!' ) {
277- let parts: Vec < & str > = cmd. split_whitespace ( ) . collect ( ) ;
278- if parts. is_empty ( ) {
279- println ! ( "no command provided" ) ;
280- } else if let Err ( e) = Command :: new ( parts[ 0 ] ) . args ( & parts[ 1 ..] ) . status ( ) {
281- println ! ( "failed to execute command `{cmd}`: {e}" ) ;
282- }
283- } else {
284- println ! ( "unknown command: {input}" ) ;
252+
253+ thread:: spawn ( move || {
254+ let mut input = String :: with_capacity ( 32 ) ;
255+ let mut stdin = io:: stdin ( ) . lock ( ) ;
256+
257+ loop {
258+ // Recycle input buffer.
259+ input. clear ( ) ;
260+
261+ if let Err ( e) = stdin. read_line ( & mut input) {
262+ println ! ( "error reading command: {e}" ) ;
263+ }
264+
265+ let input = input. trim ( ) ;
266+ if input == "hint" {
267+ if let Some ( hint) = & * failed_exercise_hint. lock ( ) . unwrap ( ) {
268+ println ! ( "{hint}" ) ;
269+ }
270+ } else if input == "clear" {
271+ println ! ( "\x1B [2J\x1B [1;1H" ) ;
272+ } else if input == "quit" {
273+ should_quit. store ( true , Ordering :: SeqCst ) ;
274+ println ! ( "Bye!" ) ;
275+ } else if input == "help" {
276+ println ! ( "{WATCH_MODE_HELP_MESSAGE}" ) ;
277+ } else if let Some ( cmd) = input. strip_prefix ( '!' ) {
278+ let mut parts = Shlex :: new ( cmd) ;
279+
280+ let Some ( program) = parts. next ( ) else {
281+ println ! ( "no command provided" ) ;
282+ continue ;
283+ } ;
284+
285+ if let Err ( e) = Command :: new ( program) . args ( parts) . status ( ) {
286+ println ! ( "failed to execute command `{cmd}`: {e}" ) ;
285287 }
288+ } else {
289+ println ! ( "unknown command: {input}\n {WATCH_MODE_HELP_MESSAGE}" ) ;
286290 }
287- Err ( error) => println ! ( "error reading command: {error}" ) ,
288291 }
289292 } ) ;
290293}
@@ -345,7 +348,7 @@ fn watch(
345348 Ok ( _) => return Ok ( WatchStatus :: Finished ) ,
346349 Err ( exercise) => Arc :: new ( Mutex :: new ( Some ( exercise. hint . clone ( ) ) ) ) ,
347350 } ;
348- spawn_watch_shell ( & failed_exercise_hint, Arc :: clone ( & should_quit) ) ;
351+ spawn_watch_shell ( Arc :: clone ( & failed_exercise_hint) , Arc :: clone ( & should_quit) ) ;
349352 loop {
350353 match rx. recv_timeout ( Duration :: from_secs ( 1 ) ) {
351354 Ok ( event) => match event {
@@ -462,3 +465,13 @@ const WELCOME: &str = r" welcome to...
462465 | | | |_| \__ \ |_| | | | | | (_| \__ \
463466 |_| \__,_|___/\__|_|_|_| |_|\__, |___/
464467 |___/" ;
468+
469+ const WATCH_MODE_HELP_MESSAGE : & str = "Commands available to you in watch mode:
470+ hint - prints the current exercise's hint
471+ clear - clears the screen
472+ quit - quits watch mode
473+ !<cmd> - executes a command, like `!rustc --explain E0381`
474+ help - displays this help message
475+
476+ Watch mode automatically re-evaluates the current exercise
477+ when you edit a file's contents." ;
0 commit comments