diff --git a/Cargo.toml b/Cargo.toml index a592100499..cc0226adc2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,9 +9,11 @@ bincode = { version = "1.3.3" } cacache = { version = "10.0.1" } chrono = { version = "0.4.21" } clap = { version = "3.2.16", features = ["derive"] } +clearscreen = "1.0.10" colored = { version = "2.0.0" } fern = { version = "0.6.1" } log = { version = "0.4.17" } +notify = "4.0.17" rayon = { version = "1.5.3" } rustpython-parser = { git = "https://github.com/RustPython/RustPython.git", rev = "dff916d45c5d13074d21ad329a5ab68a6499426a" } serde = { version = "1.0.143", features = ["derive"] } diff --git a/src/bin/main.rs b/src/bin/main.rs index 1ddbdf7070..ec6280f988 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,9 +1,11 @@ use std::path::PathBuf; -use std::time::Instant; +use std::sync::mpsc::channel; +use std::time::{Duration, Instant}; use anyhow::Result; use clap::{Parser, ValueHint}; -use log::{error, info}; +use log::{debug, error}; +use notify::{watcher, RecursiveMode, Watcher}; use rayon::prelude::*; use rust_python_linter::fs::collect_python_files; use rust_python_linter::linter::check_path; @@ -18,6 +20,8 @@ struct Cli { files: Vec, #[clap(short, long, action)] verbose: bool, + #[clap(short, long, action)] + watch: bool, } fn set_up_logging(verbose: bool) -> Result<()> { @@ -42,16 +46,12 @@ fn set_up_logging(verbose: bool) -> Result<()> { .map_err(|e| e.into()) } -fn main() -> Result<()> { - let cli = Cli::parse(); - - set_up_logging(cli.verbose)?; - +fn run_once(files: &[PathBuf]) -> Result<()> { // Collect all the files to check. let start = Instant::now(); - let files: Vec = cli.files.iter().flat_map(collect_python_files).collect(); + let files: Vec = files.iter().flat_map(collect_python_files).collect(); let duration = start.elapsed(); - info!("Identified files to lint in: {:?}", duration); + debug!("Identified files to lint in: {:?}", duration); let start = Instant::now(); let messages: Vec = files @@ -65,10 +65,12 @@ fn main() -> Result<()> { .flatten() .collect(); let duration = start.elapsed(); - info!("Checked files in: {:?}", duration); + debug!("Checked files in: {:?}", duration); + + println!("Found {} error(s).", messages.len()); if !messages.is_empty() { - println!("Found {} error(s)!", messages.len()); + println!(); for message in messages { println!("{}", message); } @@ -76,3 +78,40 @@ fn main() -> Result<()> { Ok(()) } + +fn main() -> Result<()> { + let cli = Cli::parse(); + + set_up_logging(cli.verbose)?; + + if cli.watch { + clearscreen::clear()?; + println!("Starting linter in watch mode..."); + println!(); + + run_once(&cli.files)?; + + let (tx, rx) = channel(); + let mut watcher = watcher(tx, Duration::from_secs(1))?; + for file in &cli.files { + watcher.watch(file, RecursiveMode::Recursive)?; + } + + loop { + match rx.recv() { + Ok(_) => { + clearscreen::clear()?; + println!("File change detected..."); + println!(); + + run_once(&cli.files)? + } + Err(e) => return Err(e.into()), + } + } + } else { + run_once(&cli.files)?; + } + + Ok(()) +}