continued API change

This commit is contained in:
JOLIMAITRE Matthieu 2022-09-25 15:58:28 +02:00
parent 044a7ef2df
commit 11598f7f50
6 changed files with 118 additions and 118 deletions

View file

@ -2,22 +2,39 @@ use std::fs;
use termion::color; use termion::color;
use crate::{tasks::FormatTask, utils::log_failure}; use crate::{
tasks::FormatTask,
utils::{log_failure, log_process},
};
const FORMAT_CONFIG: &str = r#"{BasedOnStyle: llvm}"#; const FORMAT_CONFIG: &str = r#"{BasedOnStyle: llvm}"#;
mod testables; mod testables;
pub fn main(files: Vec<String>) {
for file in files {
log_process(&format!("checking '{file}'"));
check_formatting(file.to_string());
let content = fs::read_to_string(&file).unwrap();
for test in testables::tests() {
if let Err(reason) = test.test(content.clone()) {
let name = test.name();
log_failure(&format!("'{file}': rule '{name}' fails:"));
println!("{reason}");
}
}
}
}
pub enum Diff { pub enum Diff {
ToRemove { index: usize, content: String }, ToRemove { index: usize, content: String },
ToAdd { index: usize, content: String }, ToAdd { index: usize, content: String },
Keep { index: usize, content: String }, Keep { index: usize, content: String },
} }
pub fn main(files: Vec<String>) { fn check_formatting(file: String) {
for file in files {
let content = fs::read_to_string(&file).unwrap(); let content = fs::read_to_string(&file).unwrap();
let formatted = FormatTask::new(file, FORMAT_CONFIG.into()).run(); let formatted = FormatTask::new(file.clone(), FORMAT_CONFIG.into()).run();
let mut line_number = 0usize; let mut line_number = 0usize;
let mut invalid = false; let mut invalid = false;
let differences = diff::lines(&content, &formatted) let differences = diff::lines(&content, &formatted)
@ -52,9 +69,8 @@ pub fn main(files: Vec<String>) {
} }
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if invalid { if invalid {
log_failure("invalid formatting:"); log_failure(&format!("'{file}': invalid formatting:"));
let red = color::Fg(color::Red); let red = color::Fg(color::Red);
let green = color::Fg(color::Green); let green = color::Fg(color::Green);
let reset = color::Fg(color::Reset); let reset = color::Fg(color::Reset);
@ -62,14 +78,13 @@ pub fn main(files: Vec<String>) {
for difference in differences { for difference in differences {
match difference { match difference {
Diff::ToRemove { index, content } => { Diff::ToRemove { index, content } => {
println!("{red} {index} - | {content}{reset}") println!("{red}{index:>3} -|{content}{reset}")
} }
Diff::ToAdd { index, content } => { Diff::ToAdd { index, content } => {
println!("{green} {index} + | {content}{reset}") println!("{green}{index:>3} +|{content}{reset}")
} }
Diff::Keep { index, content } => { Diff::Keep { index, content } => {
println!(" {index} | {content}") println!("{index:>3} |{content}")
}
} }
} }
} }

View file

@ -1,5 +1,7 @@
use crate::utils::log_failure;
fn ends_with_newline(source: String) -> Result<(), String> { fn ends_with_newline(source: String) -> Result<(), String> {
if !source.ends_with("\n") { if !source.ends_with('\n') {
Err("source does not end with newline".into()) Err("source does not end with newline".into())
} else { } else {
Ok(()) Ok(())

View file

@ -30,7 +30,7 @@ pub enum Commands {
files: Vec<String>, files: Vec<String>,
}, },
/// Runs tests contained within a particular test file or /// Runs tests contained within a particular test file or the default test file
test { test {
/// Wether to capture standard output or not. /// Wether to capture standard output or not.
#[clap(short, long)] #[clap(short, long)]
@ -44,40 +44,18 @@ pub enum Commands {
tests: Vec<String>, tests: Vec<String>,
}, },
/// Watches changes to source files and re run them /// Watches changes to the project included files and runs a command on changes
watch { watch {
#[clap(subcommand)] #[clap(short)]
command: WatchSubcommand, files: Option<Vec<String>>,
/// command to run on changes (ex: "pi test")
command: String,
}, },
/// ///
init { path: String }, init { path: String },
} }
#[allow(non_camel_case_types)]
#[derive(Subcommand)]
pub enum WatchSubcommand {
/// Runs a set of files or the default target.
run {
/// Files to run.
files: Vec<String>,
},
/// Runs tests contained within a particular test file or
test {
/// Wether to capture standard output or not.
#[clap(short, long)]
capture: bool,
/// Files to run tests from.
files: Vec<String>,
/// Specific tests to run.
#[clap(short, long)]
tests: Vec<String>,
},
}
fn append_includes(list: &mut Vec<String>) { fn append_includes(list: &mut Vec<String>) {
list.extend( list.extend(
Config::get_current() Config::get_current()
@ -117,34 +95,18 @@ fn main() {
mut files, mut files,
tests, tests,
} => { } => {
if files.is_empty() {
files.push(Config::get_current().test_file().to_string());
}
append_includes(&mut files); append_includes(&mut files);
let args = compilation_args(); let args = compilation_args();
let tests = (!tests.is_empty()).then_some(tests); let tests = (!tests.is_empty()).then_some(tests);
test::main(capture, files, args, tests) test::main(capture, files, args, tests)
} }
Commands::watch { Commands::watch { command, files } => {
command: WatchSubcommand::run { mut files }, let mut files = files.unwrap_or_default();
} => {
append_includes(&mut files); append_includes(&mut files);
let args = compilation_args(); watch::main(files, command);
watch::main(files.clone(), move || {
run::main(files.clone(), args.clone());
})
}
Commands::watch {
command: WatchSubcommand::test {
mut files,
tests,
capture,
},
} => {
append_includes(&mut files);
let args = compilation_args();
let tests = (!tests.is_empty()).then_some(tests);
watch::main(files.clone(), move || {
test::main(capture, files.clone(), args.clone(), tests.clone());
})
} }
Commands::init { path } => config::create(path), Commands::init { path } => config::create(path),

View file

@ -143,11 +143,31 @@ impl FormatTask {
command command
.arg(self.file) .arg(self.file)
.arg(format!("-style={config}")) .arg(format!("-style={config}"))
.stdout(Stdio::null()) .stdout(Stdio::piped())
.stderr(Stdio::null()); .stderr(Stdio::piped());
command.status().unwrap(); command.status().unwrap();
let result = command.output().unwrap().stdout; let result = command.output().unwrap().stdout;
String::from_utf8(result).unwrap() String::from_utf8(result).unwrap()
} }
} }
pub struct CmdTask {
command: String,
}
impl CmdTask {
pub fn new(command: String) -> Self {
Self { command }
}
pub fn run(self) -> Result<(), ()> {
Command::new("sh")
.arg("-c")
.arg(self.command)
.stdout(Stdio::inherit())
.output()
.map(|_| ())
.map_err(|_| ())
}
}

View file

@ -2,16 +2,11 @@ use std::{fs, thread, time::Duration};
use crate::{ use crate::{
tasks::{CompileTask, GenTask, RunTask}, tasks::{CompileTask, GenTask, RunTask},
utils::{log_failure, log_process}, utils::{log_failure, log_process, log_success},
}; };
pub fn main(_capture: bool, files: Vec<String>, args: Vec<String>, _test: Option<Vec<String>>) { pub fn main(_capture: bool, files: Vec<String>, args: Vec<String>, _test: Option<Vec<String>>) {
// let includes = files log_process("running tests");
// .iter()
// .cloned()
// .map(|p| PathBuf::from_str(&p).unwrap())
// .collect::<Vec<_>>();
for path in files { for path in files {
let content = fs::read_to_string(&path).unwrap(); let content = fs::read_to_string(&path).unwrap();
let tests = find_tests(content); let tests = find_tests(content);
@ -35,6 +30,7 @@ pub fn main(_capture: bool, files: Vec<String>, args: Vec<String>, _test: Option
} }
} }
} }
log_success("finished");
} }
pub fn find_tests(source: String) -> Vec<String> { pub fn find_tests(source: String) -> Vec<String> {
@ -50,7 +46,10 @@ pub fn gen_test_main(path: &str, test: &str) -> String {
" "
void __pi_test(); void __pi_test();
int main(int _argc, char** _argv) {{ int main(int argc, char** argv) {{
(void)argc;
(void)argv;
__pi_test(); __pi_test();
return 0; return 0;
}} }}

View file

@ -2,7 +2,7 @@ use std::{path::Path, sync::mpsc, time::Duration};
use notify_debouncer_mini::new_debouncer; use notify_debouncer_mini::new_debouncer;
use crate::utils::log_process; use crate::{tasks::CmdTask, utils::log_process};
pub struct Repeater { pub struct Repeater {
op: Box<dyn Fn()>, op: Box<dyn Fn()>,
@ -21,13 +21,15 @@ impl Repeater {
} }
} }
pub fn main(files: Vec<String>, op: impl Fn() + 'static) { pub fn main(files: Vec<String>, command: String) {
log_process(&format!("watching files '{files:?}'")); log_process(&format!("watching files '{files:?}'"));
let repeater = Repeater::new(op); let repeater = Repeater::new(move || {
CmdTask::new(command.clone()).run().unwrap();
});
repeater.repeat(); repeater.repeat();
let (send, rec) = mpsc::channel(); let (send, rec) = mpsc::channel();
let mut debouncer = new_debouncer(Duration::from_millis(100), None, send).unwrap(); let mut debouncer = new_debouncer(Duration::from_millis(300), None, send).unwrap();
for file in files { for file in files {
debouncer debouncer