option for multiple inputs
This commit is contained in:
parent
cbd6eb52b1
commit
a2868c8783
10 changed files with 78 additions and 44 deletions
|
@ -16,3 +16,6 @@ notify-debouncer-mini = "0.2.1"
|
||||||
ron = "0.8.0"
|
ron = "0.8.0"
|
||||||
serde = { version = "1.0.144", features = ["derive"] }
|
serde = { version = "1.0.144", features = ["derive"] }
|
||||||
termion = "1.5.6"
|
termion = "1.5.6"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
lto = true
|
||||||
|
|
15
example/simple/main.c
Normal file
15
example/simple/main.c
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../../test.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int a;
|
||||||
|
printf("hello, world!! %d\n", a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_it_works() {
|
||||||
|
assert_eq_int(2 + 2, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_it_fails() {
|
||||||
|
assert_eq_int(2 + 2, 5);
|
||||||
|
}
|
|
@ -1,3 +1,3 @@
|
||||||
pub fn main(_file: String) {
|
pub fn main(_files: Vec<String>) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
31
src/main.rs
31
src/main.rs
|
@ -22,16 +22,13 @@ pub enum Commands {
|
||||||
/// Checks a source file for conformance with piscine limitations.
|
/// Checks a source file for conformance with piscine limitations.
|
||||||
check {
|
check {
|
||||||
/// File to check.
|
/// File to check.
|
||||||
/// Supports globing
|
files: Vec<String>,
|
||||||
#[clap(default_value_t = String::from("*"))]
|
|
||||||
file: String,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Runs a file
|
/// Runs a file
|
||||||
run {
|
run {
|
||||||
/// File to run.
|
/// Files to run.
|
||||||
#[clap(default_value_t = String::from("./main.c"))]
|
files: Vec<String>,
|
||||||
file: String,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Runs tests contained within a particular test file or
|
/// Runs tests contained within a particular test file or
|
||||||
|
@ -40,9 +37,8 @@ pub enum Commands {
|
||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
capture: bool,
|
capture: bool,
|
||||||
|
|
||||||
/// File to run tests from.
|
/// Files to run tests from.
|
||||||
#[clap(default_value_t = String::from("./test.c"))]
|
files: Vec<String>,
|
||||||
file: String,
|
|
||||||
|
|
||||||
/// Specific test to run.
|
/// Specific test to run.
|
||||||
test: Option<String>,
|
test: Option<String>,
|
||||||
|
@ -50,9 +46,8 @@ pub enum Commands {
|
||||||
|
|
||||||
/// Watches changes to source files and re run them
|
/// Watches changes to source files and re run them
|
||||||
watch {
|
watch {
|
||||||
/// File to run.
|
/// Files to run.
|
||||||
#[clap(default_value_t = String::from("./main.c"))]
|
files: Vec<String>,
|
||||||
file: String,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,15 +55,15 @@ fn main() {
|
||||||
let args: Arguments = Parser::parse();
|
let args: Arguments = Parser::parse();
|
||||||
|
|
||||||
match args.command {
|
match args.command {
|
||||||
Commands::check { file } => check::main(file),
|
Commands::check { files } => check::main(files),
|
||||||
Commands::run { file } => {
|
Commands::run { files } => {
|
||||||
run::main(file);
|
run::main(files);
|
||||||
}
|
}
|
||||||
Commands::test {
|
Commands::test {
|
||||||
capture,
|
capture,
|
||||||
file,
|
files,
|
||||||
test,
|
test,
|
||||||
} => test::main(capture, file, test),
|
} => test::main(capture, files, test),
|
||||||
Commands::watch { file } => watch::main(file),
|
Commands::watch { files } => watch::main(files),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ use crate::{
|
||||||
utils::{log_failure, log_success},
|
utils::{log_failure, log_success},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main(file: String) -> Option<()> {
|
pub fn main(files: Vec<String>) -> Option<()> {
|
||||||
let source_file = file.into();
|
let source_file = files.into_iter().map(|f| f.into()).collect();
|
||||||
let compiled = CompileTask::new(source_file)
|
let compiled = CompileTask::new(source_file)
|
||||||
.with_flag("-Wall")
|
.with_flag("-Wall")
|
||||||
.with_flag("-Wextra")
|
.with_flag("-Wextra")
|
||||||
|
|
21
src/tasks.rs
21
src/tasks.rs
|
@ -4,10 +4,12 @@ use std::{
|
||||||
process::{Command, ExitStatus},
|
process::{Command, ExitStatus},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::utils::{log_command_run, log_separator, tmp_file_path, Apply};
|
use crate::utils::{
|
||||||
|
log_command_run, log_separator, log_separator_bottom, log_separator_top, tmp_file_path, Apply,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct CompileTask {
|
pub struct CompileTask {
|
||||||
file: PathBuf,
|
files: Vec<PathBuf>,
|
||||||
addition: Vec<String>,
|
addition: Vec<String>,
|
||||||
flags: Vec<String>,
|
flags: Vec<String>,
|
||||||
}
|
}
|
||||||
|
@ -15,9 +17,9 @@ pub struct CompileTask {
|
||||||
// TODO: split compile & compile raw
|
// TODO: split compile & compile raw
|
||||||
|
|
||||||
impl CompileTask {
|
impl CompileTask {
|
||||||
pub fn new(file: PathBuf) -> Self {
|
pub fn new(files: Vec<PathBuf>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
file,
|
files,
|
||||||
addition: vec![],
|
addition: vec![],
|
||||||
flags: vec![],
|
flags: vec![],
|
||||||
}
|
}
|
||||||
|
@ -35,7 +37,8 @@ impl CompileTask {
|
||||||
|
|
||||||
pub fn run(self) -> Result<PathBuf, ExitStatus> {
|
pub fn run(self) -> Result<PathBuf, ExitStatus> {
|
||||||
let proc_source = self.gen_source();
|
let proc_source = self.gen_source();
|
||||||
let sources = vec![proc_source, self.file.clone()];
|
let mut sources = self.files.clone();
|
||||||
|
sources.push(proc_source);
|
||||||
self.compile(sources)
|
self.compile(sources)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,9 +59,9 @@ impl CompileTask {
|
||||||
.args(self.flags.clone())
|
.args(self.flags.clone())
|
||||||
.args(sources.iter().map(|s| s.to_str().unwrap()));
|
.args(sources.iter().map(|s| s.to_str().unwrap()));
|
||||||
log_command_run(&command);
|
log_command_run(&command);
|
||||||
log_separator();
|
log_separator_top();
|
||||||
let status = command.status().unwrap();
|
let status = command.status().unwrap();
|
||||||
log_separator();
|
log_separator_bottom();
|
||||||
status.success().then_some(output_path).ok_or(status)
|
status.success().then_some(output_path).ok_or(status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,9 +78,9 @@ impl RunTask {
|
||||||
pub fn run(self) -> Result<(), ExitStatus> {
|
pub fn run(self) -> Result<(), ExitStatus> {
|
||||||
let mut command = Command::new(self.file);
|
let mut command = Command::new(self.file);
|
||||||
log_command_run(&command);
|
log_command_run(&command);
|
||||||
log_separator();
|
log_separator_top();
|
||||||
let status = command.status().unwrap();
|
let status = command.status().unwrap();
|
||||||
log_separator();
|
log_separator_bottom();
|
||||||
if status.success() {
|
if status.success() {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub fn main(_capture: bool, _file: String, _test: Option<String>) {
|
pub fn main(_capture: bool, _files: Vec<String>, _test: Option<String>) {
|
||||||
let content = todo!();
|
let content = todo!();
|
||||||
let tests = find_tests(content);
|
let tests = find_tests(content);
|
||||||
for test in tests {
|
for test in tests {
|
||||||
|
|
|
@ -42,6 +42,14 @@ pub fn log_separator() {
|
||||||
println!("────────────────")
|
println!("────────────────")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn log_separator_top() {
|
||||||
|
println!("───────────────┐")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn log_separator_bottom() {
|
||||||
|
println!("───────────────┘")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn log_failure(text: &str) {
|
pub fn log_failure(text: &str) {
|
||||||
log_pi_prefix();
|
log_pi_prefix();
|
||||||
let text = format!("{}{text}{}", color::Fg(color::Red), color::Fg(color::Reset));
|
let text = format!("{}{text}{}", color::Fg(color::Red), color::Fg(color::Reset));
|
||||||
|
|
27
src/watch.rs
27
src/watch.rs
|
@ -1,6 +1,5 @@
|
||||||
use std::{path::Path, sync::mpsc, time::Duration};
|
use std::{path::Path, sync::mpsc, time::Duration};
|
||||||
|
|
||||||
use notify::{Error, Event, Watcher};
|
|
||||||
use notify_debouncer_mini::new_debouncer;
|
use notify_debouncer_mini::new_debouncer;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -9,16 +8,16 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Repeater {
|
pub struct Repeater {
|
||||||
file: String,
|
files: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Repeater {
|
impl Repeater {
|
||||||
pub fn new(file: String) -> Self {
|
pub fn new(files: Vec<String>) -> Self {
|
||||||
Self { file }
|
Self { files }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn repeat(&self) -> Option<()> {
|
pub fn repeat(&self) -> Option<()> {
|
||||||
let source = CompileTask::new(self.file.clone().into())
|
let binary = CompileTask::new(self.files.clone().into_iter().map(|f| f.into()).collect())
|
||||||
.run()
|
.run()
|
||||||
.map(Option::from)
|
.map(Option::from)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
|
@ -27,7 +26,7 @@ impl Repeater {
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
log_success("compilation successful");
|
log_success("compilation successful");
|
||||||
RunTask::new(source)
|
RunTask::new(binary)
|
||||||
.run()
|
.run()
|
||||||
.map(Option::from)
|
.map(Option::from)
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
|
@ -41,18 +40,20 @@ impl Repeater {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main(file: String) {
|
pub fn main(files: Vec<String>) {
|
||||||
log_process(&format!("watching file '{file}'"));
|
log_process(&format!("watching files '{files:?}'"));
|
||||||
let repeater = Repeater::new(file.clone());
|
let repeater = Repeater::new(files.clone());
|
||||||
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(100), None, send).unwrap();
|
||||||
|
|
||||||
debouncer
|
for file in files {
|
||||||
.watcher()
|
debouncer
|
||||||
.watch(Path::new(&file), notify::RecursiveMode::Recursive)
|
.watcher()
|
||||||
.unwrap();
|
.watch(Path::new(&file), notify::RecursiveMode::Recursive)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
for events in rec {
|
for events in rec {
|
||||||
for _ in events.unwrap() {
|
for _ in events.unwrap() {
|
||||||
|
|
9
test.h
Normal file
9
test.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void assert_eq_int(int left, int right) {
|
||||||
|
if (left != right) {
|
||||||
|
printf("assertion failed\n'%i' != '%i'\n", left, right);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue