worked on config

This commit is contained in:
JOLIMAITRE Matthieu 2022-09-25 00:22:41 +02:00
parent a2868c8783
commit 37e5b5e555
9 changed files with 225 additions and 39 deletions

60
Cargo.lock generated
View file

@ -2,6 +2,15 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "aho-corasick"
version = "0.7.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "android_system_properties" name = "android_system_properties"
version = "0.1.5" version = "0.1.5"
@ -46,6 +55,12 @@ version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.0" version = "1.0.0"
@ -144,6 +159,8 @@ dependencies = [
"ron", "ron",
"serde", "serde",
"termion", "termion",
"tree-sitter",
"tree-sitter-c",
] ]
[[package]] [[package]]
@ -282,6 +299,12 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]] [[package]]
name = "mio" name = "mio"
version = "0.8.4" version = "0.8.4"
@ -419,6 +442,23 @@ dependencies = [
"redox_syscall", "redox_syscall",
] ]
[[package]]
name = "regex"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]] [[package]]
name = "ron" name = "ron"
version = "0.8.0" version = "0.8.0"
@ -514,6 +554,26 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "tree-sitter"
version = "0.20.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4423c784fe11398ca91e505cdc71356b07b1a924fc8735cfab5333afe3e18bc"
dependencies = [
"cc",
"regex",
]
[[package]]
name = "tree-sitter-c"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cca211f4827d4b4dc79f388bf67b6fa3bc8a8cfa642161ef24f99f371ba34c7b"
dependencies = [
"cc",
"tree-sitter",
]
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.4" version = "1.0.4"

View file

@ -16,6 +16,8 @@ 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"
tree-sitter = "0.20.9"
tree-sitter-c = "0.20.2"
[profile.release] [profile.release]
lto = true lto = true

View file

View file

@ -1,15 +1,6 @@
#include <stdio.h> #include <stdio.h>
#include "../../test.h"
int main() { int main() {
int a; int a;
printf("hello, world!! %d\n", 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);
}

10
example/simple/test.c Normal file
View file

@ -0,0 +1,10 @@
#include <stdio.h>
#include "../../clib/test.h"
void test_it_works() {
assert_eq_int(2 + 2, 4);
}
void test_it_fails() {
assert_eq_int(2 + 2, 5);
}

View file

@ -1,21 +1,80 @@
pub struct UserConfig { use std::{
main_file: Option<String>, env, fs,
test_file: Option<String>, path::{Path, PathBuf},
includes: Option<Vec<String>>, };
}
use ron::ser::PrettyConfig;
use serde::{Deserialize, Serialize};
use crate::utils::Apply;
#[derive(Debug, Serialize, Deserialize)]
pub struct Config { pub struct Config {
name: String,
main_file: String, main_file: String,
test_file: String, test_file: String,
includes: Vec<String>, includes: Vec<String>,
} }
impl Default for Config { impl Config {
fn default() -> Self { const CONFIG_FILE_NAME: &'static str = "pi.ron";
pub fn new(name: String) -> Self {
Self { Self {
name,
main_file: "main.c".into(), main_file: "main.c".into(),
test_file: "test.c".into(), test_file: "test.c".into(),
includes: vec![], includes: vec![],
} }
} }
pub fn write(&self, mut path: PathBuf) {
path.extend([Self::CONFIG_FILE_NAME]);
let content =
ron::ser::to_string_pretty(self, PrettyConfig::default().struct_names(true)).unwrap();
fs::write(path, content).unwrap();
}
pub fn get_current() -> Self {
let path = env::current_dir().unwrap();
Self::get(&path)
.unwrap_or_else(|| Self::new(path.file_name().unwrap().to_str().unwrap().to_string()))
}
pub fn get(path: &Path) -> Option<Self> {
let path = path.to_path_buf().canonicalize().unwrap();
Self::try_get(&path).or_else(|| path.parent().and_then(Self::get))
}
pub fn name(&self) -> &str {
&self.name
}
pub fn main_file(&self) -> &str {
&self.main_file
}
pub fn test_file(&self) -> &str {
&self.test_file
}
pub fn includes(&self) -> &Vec<String> {
&self.includes
}
fn try_get(path: &Path) -> Option<Self> {
let path = path.to_path_buf().apply(|p| p.push(Self::CONFIG_FILE_NAME));
fs::read_to_string(path)
.ok()
.and_then(|content| ron::from_str(&content).ok())
}
}
pub fn create(path: String) {
let absolute = fs::canonicalize(&path).unwrap();
if !absolute.is_dir() {
panic!("not a directory");
}
let name = absolute.file_name().unwrap();
let config = Config::new(name.to_str().unwrap().to_string());
config.write(absolute);
} }

View file

@ -1,4 +1,5 @@
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use config::Config;
pub mod check; pub mod check;
pub mod config; pub mod config;
@ -14,8 +15,6 @@ pub struct Arguments {
command: Commands, command: Commands,
} }
// TODO: turn files into file lists
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Subcommand)] #[derive(Subcommand)]
pub enum Commands { pub enum Commands {
@ -25,7 +24,7 @@ pub enum Commands {
files: Vec<String>, files: Vec<String>,
}, },
/// Runs a file /// Runs a set of files or the default target.
run { run {
/// Files to run. /// Files to run.
files: Vec<String>, files: Vec<String>,
@ -33,15 +32,16 @@ pub enum Commands {
/// Runs tests contained within a particular test file or /// Runs tests contained within a particular test file or
test { test {
/// W.I.P. Wether to capture standard output or not. /// Wether to capture standard output or not.
#[clap(short, long)] #[clap(short, long)]
capture: bool, capture: bool,
/// Files to run tests from. /// Files to run tests from.
files: Vec<String>, files: Vec<String>,
/// Specific test to run. /// Specific tests to run.
test: Option<String>, #[clap(short, long)]
tests: Vec<String>,
}, },
/// Watches changes to source files and re run them /// Watches changes to source files and re run them
@ -49,6 +49,18 @@ pub enum Commands {
/// Files to run. /// Files to run.
files: Vec<String>, files: Vec<String>,
}, },
///
init { path: String },
}
fn append_includes(list: &mut Vec<String>) {
list.extend(
Config::get_current()
.includes()
.iter()
.map(|f| f.to_string()),
);
} }
fn main() { fn main() {
@ -56,14 +68,23 @@ fn main() {
match args.command { match args.command {
Commands::check { files } => check::main(files), Commands::check { files } => check::main(files),
Commands::run { files } => { Commands::run { mut files } => {
append_includes(&mut files);
run::main(files); run::main(files);
} }
Commands::test { Commands::test {
capture, capture,
files, mut files,
test, tests,
} => test::main(capture, files, test), } => {
Commands::watch { files } => watch::main(files), append_includes(&mut files);
let tests = (!tests.is_empty()).then_some(tests);
test::main(capture, files, tests)
}
Commands::watch { mut files } => {
append_includes(&mut files);
watch::main(files)
}
Commands::init { path } => config::create(path),
} }
} }

View file

@ -2,10 +2,12 @@ use std::{
fs, fs,
path::PathBuf, path::PathBuf,
process::{Command, ExitStatus}, process::{Command, ExitStatus},
thread,
time::Duration,
}; };
use crate::utils::{ use crate::utils::{
log_command_run, log_separator, log_separator_bottom, log_separator_top, tmp_file_path, Apply, log_command_run, log_separator_bottom, log_separator_top, tmp_file_path, Apply,
}; };
pub struct CompileTask { pub struct CompileTask {
@ -62,6 +64,7 @@ impl CompileTask {
log_separator_top(); log_separator_top();
let status = command.status().unwrap(); let status = command.status().unwrap();
log_separator_bottom(); log_separator_bottom();
thread::sleep(Duration::from_millis(100));
status.success().then_some(output_path).ok_or(status) status.success().then_some(output_path).ok_or(status)
} }
} }
@ -88,3 +91,19 @@ impl RunTask {
} }
} }
} }
pub struct GenTask {
content: String,
}
impl GenTask {
pub fn new(content: String) -> Self {
Self { content }
}
pub fn run(self) -> PathBuf {
let output_path = tmp_file_path().apply(|o| o.set_extension("c"));
fs::write(&output_path, &self.content).unwrap();
dbg!(fs::read_to_string(&output_path).unwrap());
output_path
}
}

View file

@ -1,29 +1,53 @@
pub fn main(_capture: bool, _files: Vec<String>, _test: Option<String>) { use std::fs;
let content = todo!();
let tests = find_tests(content); use crate::tasks::{CompileTask, GenTask, RunTask};
for test in tests {
// compile pub fn main(_capture: bool, files: Vec<String>, _test: Option<Vec<String>>) {
// run // let includes = files
// .iter()
// .cloned()
// .map(|p| PathBuf::from_str(&p).unwrap())
// .collect::<Vec<_>>();
for path in files {
let content = fs::read_to_string(&path).unwrap();
let tests = find_tests(content);
for test in tests {
let content = gen_test_main(fs::canonicalize(&path).unwrap().to_str().unwrap(), &test);
let generated_code = GenTask::new(content).run();
// compile with all files
//let files = includes.clone().apply(|v| v.insert(0, generated_code));
let generated_bin = CompileTask::new(vec![generated_code]).run().unwrap();
// run
RunTask::new(generated_bin).run().unwrap();
}
} }
} }
pub fn find_tests(source: String) -> Vec<String> { pub fn find_tests(source: String) -> Vec<String> {
source source
.split([' ', '(', ')', ';']) .split([' ', '(', ')', ';'])
.filter(|name| &name[0..5] == "test_") .filter(|name| name.starts_with("test_"))
.map(String::from) .map(String::from)
.collect() .collect()
} }
pub fn gen_test_main(test_file: &str, test: &str) -> String { pub fn gen_test_main(path: &str, test: &str) -> String {
format!( format!(
" "
#include \"{test_file}\" void ____test();
int main() {{ int main() {{
{test}(); ____test();
return 0; return 0;
}} }}
#include \"{path}\"
void ____test() {{
{test}();
}}
" "
) )
} }