commit 8e2a03e3a7f53691ff748db00a09d1c57a324e32 Author: JOLIMAITRE Matthieu Date: Tue Sep 20 03:08:36 2022 +0200 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..b79a1b8 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,639 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bumpalo" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "time", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "clap" +version = "3.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "once_cell", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "crossbeam-channel" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "epitls-pi" +version = "0.1.0" +dependencies = [ + "chrono", + "clap", + "glob", + "notify", + "notify-debouncer-mini", + "termion", +] + +[[package]] +name = "filetime" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94a7bbaa59354bc20dd75b67f23e2797b4490e9d6928203fb105c79e448c86c" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "windows-sys", +] + +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "237a0714f28b1ee39ccec0770ccb544eb02c9ef2c82bb096230eefcffa6468b0" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "js-sys", + "once_cell", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "indexmap" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "kqueue" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d6112e8f37b59803ac47a42d14f1f3a59bbf72fc6857ffc5be455e28a691f8e" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" +dependencies = [ + "bitflags", + "libc", +] + +[[package]] +name = "libc" +version = "0.2.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "mio" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys", +] + +[[package]] +name = "notify" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2c66da08abae1c024c01d635253e402341b4060a12e99b31c7594063bf490a" +dependencies = [ + "bitflags", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "mio", + "walkdir", + "winapi", +] + +[[package]] +name = "notify-debouncer-mini" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e23e9fa24f094b143c1eb61f90ac6457de87be6987bc70746e0179f7dbc9007b" +dependencies = [ + "crossbeam-channel", + "notify", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "numtoa" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" + +[[package]] +name = "once_cell" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" + +[[package]] +name = "os_str_bytes" +version = "6.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_termios" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f" +dependencies = [ + "redox_syscall", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "termion" +version = "1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e" +dependencies = [ + "libc", + "numtoa", + "redox_syscall", + "redox_termios", +] + +[[package]] +name = "textwrap" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" + +[[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "unicode-ident" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..226c89d --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "epitls-pi" +version = "0.1.0" +edition = "2021" + +[[bin]] +name = "pi" +path = "src/main.rs" + +[dependencies] +chrono = "0.4.22" +clap = { version = "3.2.22", features = ["clap_derive", "derive"] } +glob = "0.3.0" +notify = "5.0.0" +notify-debouncer-mini = "0.2.1" +termion = "1.5.6" diff --git a/README.md b/README.md new file mode 100644 index 0000000..f5868bb --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# epitls PI + +## Description + +A little helper tool meant to ease the developpment of the C piscine at EPITA/Toulouse. + +## Usage + +```sh +USAGE: + pi + +OPTIONS: + -h, --help Print help information + +SUBCOMMANDS: + check Checks a source file for conformance with piscine limitations + help Print this message or the help of the given subcommand(s) + run Runs a file + test Runs tests contained within a particular test file or + watch Watches changes to source files and re run them +``` diff --git a/src/check.rs b/src/check.rs new file mode 100644 index 0000000..ea20cb5 --- /dev/null +++ b/src/check.rs @@ -0,0 +1,3 @@ +pub fn main(_file: String) { + todo!() +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..f3d0915 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,73 @@ +use clap::{Parser, Subcommand}; + +pub mod check; +pub mod run; +pub mod tasks; +pub mod test; +pub mod utils; +pub mod watch; + +#[derive(Parser)] +pub struct Arguments { + #[clap(subcommand)] + command: Commands, +} + +// TODO: turn files into file lists + +#[allow(non_camel_case_types)] +#[derive(Subcommand)] +pub enum Commands { + /// Checks a source file for conformance with piscine limitations. + check { + /// File to check. + /// Supports globing + #[clap(default_value_t = String::from("*"))] + file: String, + }, + + /// Runs a file + run { + /// File to run. + #[clap(default_value_t = String::from("./main.c"))] + file: String, + }, + + /// Runs tests contained within a particular test file or + test { + /// W.I.P. Wether to capture standard output or not. + #[clap(short, long)] + capture: bool, + + /// File to run tests from. + #[clap(default_value_t = String::from("./test.c"))] + file: String, + + /// Specific test to run. + test: Option, + }, + + /// Watches changes to source files and re run them + watch { + /// File to run. + #[clap(default_value_t = String::from("./main.c"))] + file: String, + }, +} + +fn main() { + let args: Arguments = Parser::parse(); + + match args.command { + Commands::check { file } => check::main(file), + Commands::run { file } => { + run::main(file); + } + Commands::test { + capture, + file, + test, + } => test::main(capture, file, test), + Commands::watch { file } => watch::main(file), + } +} diff --git a/src/run.rs b/src/run.rs new file mode 100644 index 0000000..5d8685a --- /dev/null +++ b/src/run.rs @@ -0,0 +1,28 @@ +use crate::{ + tasks::{CompileTask, RunTask}, + utils::{log_failure, log_success}, +}; + +pub fn main(file: String) -> Option<()> { + let source_file = file.into(); + let compiled = CompileTask::new(source_file) + .with_flag("-Wall") + .with_flag("-Wextra") + .with_flag("-std=c99") + .run() + .map(Option::from) + .unwrap_or_else(|_| { + log_failure("compilation failed"); + None + })?; + log_success("compilation successful"); + RunTask::new(compiled) + .run() + .map(Option::from) + .unwrap_or_else(|_| { + log_failure("process failure"); + None + })?; + log_success("process exited successfully"); + Some(()) +} diff --git a/src/tasks.rs b/src/tasks.rs new file mode 100644 index 0000000..e86e451 --- /dev/null +++ b/src/tasks.rs @@ -0,0 +1,87 @@ +use std::{ + fs, + path::PathBuf, + process::{Command, ExitStatus}, +}; + +use crate::utils::{log_command_run, log_separator, tmp_file_path, Apply}; + +pub struct CompileTask { + file: PathBuf, + addition: Vec, + flags: Vec, +} + +// TODO: split compile & compile raw + +impl CompileTask { + pub fn new(file: PathBuf) -> Self { + Self { + file, + addition: vec![], + flags: vec![], + } + } + + pub fn with_addition(mut self, code: impl ToString) -> Self { + self.addition.push(code.to_string()); + self + } + + pub fn with_flag(mut self, flag: impl ToString) -> Self { + self.flags.push(flag.to_string()); + self + } + + pub fn run(self) -> Result { + let proc_source = self.gen_source(); + let sources = vec![proc_source, self.file.clone()]; + self.compile(sources) + } + + pub fn gen_source(&self) -> PathBuf { + let mut output_path = tmp_file_path(); + // TODO: make use of supplement + output_path.set_extension("c"); + fs::write(&output_path, "").unwrap(); + output_path + } + + pub fn compile(&self, sources: Vec) -> Result { + let output_path = tmp_file_path().apply(|o| o.set_extension("b")); + let output_path_ref = output_path.to_str().unwrap(); + let mut command = Command::new("gcc"); + command + .args(["-o", output_path_ref]) + .args(self.flags.clone()) + .args(sources.iter().map(|s| s.to_str().unwrap())); + log_command_run(&command); + log_separator(); + let status = command.status().unwrap(); + log_separator(); + status.success().then_some(output_path).ok_or(status) + } +} + +pub struct RunTask { + file: PathBuf, +} + +impl RunTask { + pub fn new(file: PathBuf) -> Self { + Self { file } + } + + pub fn run(self) -> Result<(), ExitStatus> { + let mut command = Command::new(self.file); + log_command_run(&command); + log_separator(); + let status = command.status().unwrap(); + log_separator(); + if status.success() { + Ok(()) + } else { + Err(status) + } + } +} diff --git a/src/test.rs b/src/test.rs new file mode 100644 index 0000000..5b4da87 --- /dev/null +++ b/src/test.rs @@ -0,0 +1,29 @@ +pub fn main(_capture: bool, _file: String, _test: Option) { + let content = todo!(); + let tests = find_tests(content); + for test in tests { + // compile + // run + } +} + +pub fn find_tests(source: String) -> Vec { + source + .split([' ', '(', ')', ';']) + .filter(|name| &name[0..5] == "test_") + .map(String::from) + .collect() +} + +pub fn gen_test_main(test_file: &str, test: &str) -> String { + format!( + " +#include \"{test_file}\" + +int main() {{ + {test}(); + return 0; + }} +" + ) +} diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..b59b314 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,85 @@ +use std::{fs, path::PathBuf, process::Command}; + +use chrono::Utc; +use termion::color; + +pub fn tmp_file_path() -> PathBuf { + let ms = Utc::now().timestamp_millis().to_string(); + let mut path: PathBuf = ["/", "tmp", "epitls-pi"].iter().collect(); + fs::create_dir_all(&path).unwrap(); + path.push(ms); + path +} + +pub trait Apply: Sized { + fn apply(mut self, f: F) -> Self + where + F: FnOnce(&mut Self) -> O, + { + f(&mut self); + self + } +} +impl Apply for T {} + +fn log_pi_prefix() { + print!( + "{}[pi] {}", + color::Fg(color::LightBlue), + color::Fg(color::Reset) + ) +} + +pub fn log_command_run(command: &Command) { + log_pi_prefix(); + let prefix = format_process("running "); + let value = format_variable(&format!("{command:?}")); + let suffix = format_process(" ..."); + println!("{prefix}{value}{suffix}"); +} + +pub fn log_separator() { + println!("────────────────") +} + +pub fn log_failure(text: &str) { + log_pi_prefix(); + let text = format!("{}{text}{}", color::Fg(color::Red), color::Fg(color::Reset)); + println!("{text}"); +} + +pub fn log_success(text: &str) { + log_pi_prefix(); + let text = format_success(text); + println!("{text}"); +} + +pub fn log_process(text: &str) { + log_pi_prefix(); + let text = format_process(text); + println!("{text}"); +} + +fn format_process(input: &str) -> String { + format!( + "{}{input}{}", + color::Fg(color::Blue), + color::Fg(color::Reset) + ) +} + +fn format_success(input: &str) -> String { + format!( + "{}{input}{}", + color::Fg(color::Green), + color::Fg(color::Reset) + ) +} + +fn format_variable(input: &str) -> String { + format!( + "{}{input}{}", + color::Fg(color::White), + color::Fg(color::Reset), + ) +} diff --git a/src/watch.rs b/src/watch.rs new file mode 100644 index 0000000..b62d839 --- /dev/null +++ b/src/watch.rs @@ -0,0 +1,62 @@ +use std::{path::Path, sync::mpsc, time::Duration}; + +use notify::{Error, Event, Watcher}; +use notify_debouncer_mini::new_debouncer; + +use crate::{ + tasks::{CompileTask, RunTask}, + utils::{log_failure, log_process, log_success}, +}; + +pub struct Repeater { + file: String, +} + +impl Repeater { + pub fn new(file: String) -> Self { + Self { file } + } + + pub fn repeat(&self) -> Option<()> { + let source = CompileTask::new(self.file.clone().into()) + .run() + .map(Option::from) + .unwrap_or_else(|_| { + log_failure("failed compilation"); + None + })?; + + log_success("compilation successful"); + RunTask::new(source) + .run() + .map(Option::from) + .unwrap_or_else(|_| { + log_failure("task failure"); + None + })?; + + log_success("task successful"); + log_process("waiting for changes before re run"); + Some(()) + } +} + +pub fn main(file: String) { + log_process(&format!("watching file '{file}'")); + let repeater = Repeater::new(file.clone()); + repeater.repeat(); + + let (send, rec) = mpsc::channel(); + let mut debouncer = new_debouncer(Duration::from_millis(100), None, send).unwrap(); + + debouncer + .watcher() + .watch(Path::new(&file), notify::RecursiveMode::Recursive) + .unwrap(); + + for events in rec { + for _ in events.unwrap() { + repeater.repeat(); + } + } +}