worked on config
This commit is contained in:
parent
a2868c8783
commit
37e5b5e555
9 changed files with 225 additions and 39 deletions
60
Cargo.lock
generated
60
Cargo.lock
generated
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
10
example/simple/test.c
Normal 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);
|
||||||
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
43
src/main.rs
43
src/main.rs
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
21
src/tasks.rs
21
src/tasks.rs
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
40
src/test.rs
40
src/test.rs
|
@ -1,29 +1,53 @@
|
||||||
pub fn main(_capture: bool, _files: Vec<String>, _test: Option<String>) {
|
use std::fs;
|
||||||
let content = todo!();
|
|
||||||
|
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);
|
let tests = find_tests(content);
|
||||||
for test in tests {
|
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
|
// 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}();
|
||||||
|
}}
|
||||||
"
|
"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue