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.
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]]
name = "android_system_properties"
version = "0.1.5"
@ -46,6 +55,12 @@ version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -144,6 +159,8 @@ dependencies = [
"ron",
"serde",
"termion",
"tree-sitter",
"tree-sitter-c",
]
[[package]]
@ -282,6 +299,12 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "mio"
version = "0.8.4"
@ -419,6 +442,23 @@ dependencies = [
"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]]
name = "ron"
version = "0.8.0"
@ -514,6 +554,26 @@ dependencies = [
"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]]
name = "unicode-ident"
version = "1.0.4"

View file

@ -16,6 +16,8 @@ notify-debouncer-mini = "0.2.1"
ron = "0.8.0"
serde = { version = "1.0.144", features = ["derive"] }
termion = "1.5.6"
tree-sitter = "0.20.9"
tree-sitter-c = "0.20.2"
[profile.release]
lto = true

View file

View file

@ -1,15 +1,6 @@
#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);
}

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 {
main_file: Option<String>,
test_file: Option<String>,
includes: Option<Vec<String>>,
}
use std::{
env, fs,
path::{Path, PathBuf},
};
use ron::ser::PrettyConfig;
use serde::{Deserialize, Serialize};
use crate::utils::Apply;
#[derive(Debug, Serialize, Deserialize)]
pub struct Config {
name: String,
main_file: String,
test_file: String,
includes: Vec<String>,
}
impl Default for Config {
fn default() -> Self {
impl Config {
const CONFIG_FILE_NAME: &'static str = "pi.ron";
pub fn new(name: String) -> Self {
Self {
name,
main_file: "main.c".into(),
test_file: "test.c".into(),
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 config::Config;
pub mod check;
pub mod config;
@ -14,8 +15,6 @@ pub struct Arguments {
command: Commands,
}
// TODO: turn files into file lists
#[allow(non_camel_case_types)]
#[derive(Subcommand)]
pub enum Commands {
@ -25,7 +24,7 @@ pub enum Commands {
files: Vec<String>,
},
/// Runs a file
/// Runs a set of files or the default target.
run {
/// Files to run.
files: Vec<String>,
@ -33,15 +32,16 @@ pub enum Commands {
/// Runs tests contained within a particular test file or
test {
/// W.I.P. Wether to capture standard output or not.
/// Wether to capture standard output or not.
#[clap(short, long)]
capture: bool,
/// Files to run tests from.
files: Vec<String>,
/// Specific test to run.
test: Option<String>,
/// Specific tests to run.
#[clap(short, long)]
tests: Vec<String>,
},
/// Watches changes to source files and re run them
@ -49,6 +49,18 @@ pub enum Commands {
/// Files to run.
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() {
@ -56,14 +68,23 @@ fn main() {
match args.command {
Commands::check { files } => check::main(files),
Commands::run { files } => {
Commands::run { mut files } => {
append_includes(&mut files);
run::main(files);
}
Commands::test {
capture,
files,
test,
} => test::main(capture, files, test),
Commands::watch { files } => watch::main(files),
mut files,
tests,
} => {
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,
path::PathBuf,
process::{Command, ExitStatus},
thread,
time::Duration,
};
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 {
@ -62,6 +64,7 @@ impl CompileTask {
log_separator_top();
let status = command.status().unwrap();
log_separator_bottom();
thread::sleep(Duration::from_millis(100));
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>) {
let content = todo!();
use std::fs;
use crate::tasks::{CompileTask, GenTask, RunTask};
pub fn main(_capture: bool, files: Vec<String>, _test: Option<Vec<String>>) {
// 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 {
// compile
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> {
source
.split([' ', '(', ')', ';'])
.filter(|name| &name[0..5] == "test_")
.filter(|name| name.starts_with("test_"))
.map(String::from)
.collect()
}
pub fn gen_test_main(test_file: &str, test: &str) -> String {
pub fn gen_test_main(path: &str, test: &str) -> String {
format!(
"
#include \"{test_file}\"
void ____test();
int main() {{
{test}();
____test();
return 0;
}}
#include \"{path}\"
void ____test() {{
{test}();
}}
"
)
}