summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Vesteraas <erik@vestera.as>2018-11-26 12:41:39 +0100
committerErik Vesteraas <erik@vestera.as>2018-11-26 12:45:29 +0100
commit9d16d6b63d9a399d9e7d65a7aa7993ba94253e40 (patch)
tree206fb6b6536af9b64221313339ef1f3b4dabf2c0
parent586285cd0b9b309e6823885a31871adf8f933294 (diff)
Add watch mode, and don't panic on clean failure
-rw-r--r--Cargo.toml1
-rw-r--r--src/main.rs170
2 files changed, 103 insertions, 68 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 5ac31cd..c1f81fd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,3 +8,4 @@ clap = "2.32.0"
indicatif = "0.9.0"
console = "0.6.2"
syntect = "3.0.2"
+notify = "4.0.0"
diff --git a/src/main.rs b/src/main.rs
index 685618d..3cdd0b4 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,6 +3,7 @@ extern crate clap;
extern crate console;
extern crate indicatif;
extern crate syntect;
+extern crate notify;
use clap::{App, Arg, SubCommand};
use console::{style, Emoji};
@@ -14,6 +15,11 @@ use syntect::util::{as_24_bit_terminal_escaped, LinesWithEndings};
use std::fs::remove_file;
use std::io::BufRead;
use std::process::Command;
+use std::fs::read_to_string;
+use std::sync::mpsc::channel;
+use std::time::Duration;
+use notify::DebouncedEvent;
+use notify::{RecommendedWatcher, Watcher, RecursiveMode};
fn main() {
let matches = App::new("rustlings")
@@ -21,6 +27,7 @@ fn main() {
.author("Olivia Hugger")
.about("Test")
.subcommand(SubCommand::with_name("verify").alias("v"))
+ .subcommand(SubCommand::with_name("watch").alias("w"))
.subcommand(
SubCommand::with_name("run")
.alias("r")
@@ -57,7 +64,7 @@ fn main() {
let formatstr =
format!("{} Successfully ran {}", Emoji("✅", "✓"), filename);
println!("{}", style(formatstr).green());
- clean().unwrap();
+ clean();
} else {
println!("{}", String::from_utf8_lossy(&runcmd.stdout));
println!("{}", String::from_utf8_lossy(&runcmd.stderr));
@@ -65,7 +72,7 @@ fn main() {
let formatstr =
format!("{} Ran {} with errors", Emoji("⚠️ ", "!"), filename);
println!("{}", style(formatstr).red());
- clean().unwrap();
+ clean();
}
} else {
bar.finish_and_clear();
@@ -76,7 +83,7 @@ fn main() {
);
println!("{}", style(formatstr).red());
println!("{}", String::from_utf8_lossy(&compilecmd.stderr));
- clean().unwrap();
+ clean();
}
} else {
panic!("Please supply a filename!");
@@ -84,60 +91,14 @@ fn main() {
}
if let Some(_) = matches.subcommand_matches("verify") {
- compile_only("exercises/ex1.rs");
- compile_only("exercises/ex2.rs");
- compile_only("exercises/ex3.rs");
- compile_only("exercises/ex4.rs");
- compile_only("exercises/ex5.rs");
-
- compile_only("exercises/variables/variables1.rs");
- compile_only("exercises/variables/variables2.rs");
- compile_only("exercises/variables/variables3.rs");
- compile_only("exercises/variables/variables4.rs");
-
- compile_only("exercises/functions/functions1.rs");
- compile_only("exercises/functions/functions2.rs");
- compile_only("exercises/functions/functions3.rs");
- compile_only("exercises/functions/functions4.rs");
- compile_only("exercises/functions/functions5.rs");
-
- compile_only("exercises/primitive_types/primitive_types1.rs");
- compile_only("exercises/primitive_types/primitive_types2.rs");
- compile_only("exercises/primitive_types/primitive_types3.rs");
- compile_only("exercises/primitive_types/primitive_types4.rs");
- compile_only("exercises/primitive_types/primitive_types5.rs");
- compile_only("exercises/primitive_types/primitive_types6.rs");
-
- test("exercises/tests/tests1.rs");
- test("exercises/tests/tests2.rs");
- test("exercises/tests/tests3.rs");
- test("exercises/tests/tests4.rs");
-
- test("exercises/if/if1.rs");
-
- compile_only("exercises/strings/strings1.rs");
- compile_only("exercises/strings/strings2.rs");
- compile_only("exercises/strings/strings3.rs");
-
- compile_only("exercises/move_semantics/move_semantics1.rs");
- compile_only("exercises/move_semantics/move_semantics2.rs");
- compile_only("exercises/move_semantics/move_semantics3.rs");
- compile_only("exercises/move_semantics/move_semantics4.rs");
-
- compile_only("exercises/modules/modules1.rs");
- compile_only("exercises/modules/modules2.rs");
-
- compile_only("exercises/macros/macros1.rs");
- compile_only("exercises/macros/macros2.rs");
- compile_only("exercises/macros/macros3.rs");
- compile_only("exercises/macros/macros4.rs");
-
- test("exercises/error_handling/errors1.rs");
- test("exercises/error_handling/errors2.rs");
- test("exercises/error_handling/errors3.rs");
- test("exercises/error_handling/errorsn.rs");
- compile_only("exercises/error_handling/option1.rs");
- test("exercises/error_handling/result1.rs");
+ match verify() {
+ Ok(_) => {}
+ Err(_) => std::process::exit(1),
+ }
+ }
+
+ if let Some(_) = matches.subcommand_matches("watch") {
+ watch().unwrap();
}
if let None = matches.subcommand_name() {
@@ -152,7 +113,79 @@ fn main() {
println!("\x1b[0m");
}
-fn compile_only(filename: &str) {
+fn watch() -> notify::Result<()> {
+ let (tx, rx) = channel();
+
+ let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(2))?;
+ watcher.watch("./exercises", RecursiveMode::Recursive)?;
+
+ let _ignored = verify();
+
+ loop {
+ match rx.recv() {
+ Ok(event) => {
+ match event {
+ DebouncedEvent::Chmod(_)
+ | DebouncedEvent::Write(_) => {
+ let _ignored = verify();
+ }
+ _ => {}
+ }
+ },
+ Err(e) => println!("watch error: {:?}", e),
+ }
+ }
+}
+
+fn verify() -> Result<(), ()> {
+ compile_only("exercises/ex1.rs")?;
+ compile_only("exercises/ex2.rs")?;
+ compile_only("exercises/ex3.rs")?;
+ compile_only("exercises/ex4.rs")?;
+ compile_only("exercises/ex5.rs")?;
+ compile_only("exercises/variables/variables1.rs")?;
+ compile_only("exercises/variables/variables2.rs")?;
+ compile_only("exercises/variables/variables3.rs")?;
+ compile_only("exercises/variables/variables4.rs")?;
+ compile_only("exercises/functions/functions1.rs")?;
+ compile_only("exercises/functions/functions2.rs")?;
+ compile_only("exercises/functions/functions3.rs")?;
+ compile_only("exercises/functions/functions4.rs")?;
+ compile_only("exercises/functions/functions5.rs")?;
+ compile_only("exercises/primitive_types/primitive_types1.rs")?;
+ compile_only("exercises/primitive_types/primitive_types2.rs")?;
+ compile_only("exercises/primitive_types/primitive_types3.rs")?;
+ compile_only("exercises/primitive_types/primitive_types4.rs")?;
+ compile_only("exercises/primitive_types/primitive_types5.rs")?;
+ compile_only("exercises/primitive_types/primitive_types6.rs")?;
+ test("exercises/tests/tests1.rs")?;
+ test("exercises/tests/tests2.rs")?;
+ test("exercises/tests/tests3.rs")?;
+ test("exercises/tests/tests4.rs")?;
+ test("exercises/if/if1.rs")?;
+ compile_only("exercises/strings/strings1.rs")?;
+ compile_only("exercises/strings/strings2.rs")?;
+ compile_only("exercises/strings/strings3.rs")?;
+ compile_only("exercises/move_semantics/move_semantics1.rs")?;
+ compile_only("exercises/move_semantics/move_semantics2.rs")?;
+ compile_only("exercises/move_semantics/move_semantics3.rs")?;
+ compile_only("exercises/move_semantics/move_semantics4.rs")?;
+ compile_only("exercises/modules/modules1.rs")?;
+ compile_only("exercises/modules/modules2.rs")?;
+ compile_only("exercises/macros/macros1.rs")?;
+ compile_only("exercises/macros/macros2.rs")?;
+ compile_only("exercises/macros/macros3.rs")?;
+ compile_only("exercises/macros/macros4.rs")?;
+ test("exercises/error_handling/errors1.rs")?;
+ test("exercises/error_handling/errors2.rs")?;
+ test("exercises/error_handling/errors3.rs")?;
+ test("exercises/error_handling/errorsn.rs")?;
+ compile_only("exercises/error_handling/option1.rs")?;
+ test("exercises/error_handling/result1.rs")?;
+ Ok(())
+}
+
+fn compile_only(filename: &str) -> Result<(), ()> {
let bar = ProgressBar::new_spinner();
bar.set_message(format!("Compiling {}...", filename).as_str());
bar.enable_steady_tick(100);
@@ -168,7 +201,8 @@ fn compile_only(filename: &str) {
filename
);
println!("{}", style(formatstr).green());
- clean().unwrap();
+ clean();
+ Ok(())
} else {
let formatstr = format!(
"{} Compilation of {} failed! Compiler error message:\n",
@@ -177,12 +211,12 @@ fn compile_only(filename: &str) {
);
println!("{}", style(formatstr).red());
println!("{}", String::from_utf8_lossy(&compilecmd.stderr));
- clean().unwrap();
- std::process::exit(1);
+ clean();
+ Err(())
}
}
-fn test(filename: &str) {
+fn test(filename: &str) -> Result<(), ()> {
let bar = ProgressBar::new_spinner();
bar.set_message(format!("Testing {}...", filename).as_str());
bar.enable_steady_tick(100);
@@ -194,7 +228,8 @@ fn test(filename: &str) {
if testcmd.status.success() {
let formatstr = format!("{} Successfully tested {}!", Emoji("✅", "✓"), filename);
println!("{}", style(formatstr).green());
- clean().unwrap();
+ clean();
+ Ok(())
} else {
let formatstr = format!(
"{} Testing of {} failed! Please try again.",
@@ -202,12 +237,11 @@ fn test(filename: &str) {
filename
);
println!("{}", style(formatstr).red());
- clean().unwrap();
- std::process::exit(1);
+ clean();
+ Err(())
}
}
-fn clean() -> Result<(), std::io::Error> {
- remove_file("temp")?;
- Ok(())
+fn clean() {
+ let _ignored = remove_file("temp");
}