From 1bb8dde4a4f083b1d0f5dc52ed341adec8f715c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABlle=20MARTIN?= <maelle.martin@proton.me> Date: Thu, 5 Sep 2024 11:13:58 +0200 Subject: [PATCH] SCRIPT: Add ratatui Still need to think how to handle it, it seems that the flux architecture is something that can be Ok for us. The workers stores the state, and the ui handle pulls and render the thing. This is exactly what we want here. --- src/Rust/Cargo.lock | 396 +++++++++++++++++++++++++++- src/Rust/Cargo.toml | 3 +- src/Rust/vvs_cli/Cargo.toml | 1 + src/Rust/vvs_cli/src/args.rs | 17 +- src/Rust/vvs_cli/src/compiler.rs | 48 ++++ src/Rust/vvs_cli/src/config.rs | 3 +- src/Rust/vvs_cli/src/lib.rs | 1 + src/Rust/vvs_cli/src/main.rs | 62 +---- src/Rust/vvs_runtime/Cargo.toml | 1 + src/Rust/vvs_runtime/src/runtime.rs | 64 +++-- src/Rust/vvs_xdg/src/file/temp.rs | 12 + 11 files changed, 520 insertions(+), 88 deletions(-) create mode 100644 src/Rust/vvs_cli/src/compiler.rs diff --git a/src/Rust/Cargo.lock b/src/Rust/Cargo.lock index 79912599..9f75e1e9 100644 --- a/src/Rust/Cargo.lock +++ b/src/Rust/Cargo.lock @@ -106,6 +106,15 @@ version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + [[package]] name = "autocfg" version = "1.3.0" @@ -143,18 +152,39 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "by_address" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" + [[package]] name = "bytecount" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" +[[package]] +name = "cassowary" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" + [[package]] name = "cast" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" +[[package]] +name = "castaway" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5" +dependencies = [ + "rustversion", +] + [[package]] name = "cbindgen" version = "0.27.0" @@ -307,6 +337,20 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +[[package]] +name = "compact_str" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6050c3a16ddab2e412160b31f2c871015704239bca62f72f6e5f0be631d3f644" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "rustversion", + "ryu", + "static_assertions", +] + [[package]] name = "console" version = "0.15.8" @@ -340,7 +384,7 @@ dependencies = [ "clap", "criterion-plot", "is-terminal", - "itertools", + "itertools 0.10.5", "num-traits", "once_cell", "oorandom", @@ -361,7 +405,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", - "itertools", + "itertools 0.10.5", ] [[package]] @@ -389,6 +433,31 @@ version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +[[package]] +name = "crossterm" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" +dependencies = [ + "bitflags", + "crossterm_winapi", + "mio", + "parking_lot", + "rustix", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + [[package]] name = "crunchy" version = "0.2.2" @@ -445,6 +514,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "fast-srgb8" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" + [[package]] name = "fastrand" version = "2.1.1" @@ -496,6 +571,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "hermit-abi" version = "0.4.0" @@ -527,13 +608,23 @@ dependencies = [ "walkdir", ] +[[package]] +name = "instability" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" +dependencies = [ + "quote", + "syn 2.0.77", +] + [[package]] name = "is-terminal" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi", + "hermit-abi 0.4.0", "libc", "windows-sys 0.52.0", ] @@ -553,6 +644,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -606,18 +706,50 @@ dependencies = [ "semver", ] +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "lru" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +dependencies = [ + "hashbrown", +] + [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "log", + "wasi", + "windows-sys 0.52.0", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -648,12 +780,101 @@ dependencies = [ "ttf-parser", ] +[[package]] +name = "palette" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" +dependencies = [ + "approx", + "fast-srgb8", + "palette_derive", + "phf", +] + +[[package]] +name = "palette_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" +dependencies = [ + "by_address", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + [[package]] name = "paste" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + [[package]] name = "plotters" version = "0.3.6" @@ -700,6 +921,43 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "ratatui" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdef7f9be5c0122f890d58bdf4d964349ba6a6161f705907526d891efabba57d" +dependencies = [ + "bitflags", + "cassowary", + "compact_str", + "crossterm", + "instability", + "itertools 0.13.0", + "lru", + "palette", + "paste", + "strum", + "strum_macros", + "unicode-segmentation", + "unicode-truncate", + "unicode-width", +] + [[package]] name = "rayon" version = "1.10.0" @@ -720,6 +978,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "redox_syscall" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +dependencies = [ + "bitflags", +] + [[package]] name = "regex" version = "1.10.6" @@ -774,6 +1041,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + [[package]] name = "ryu" version = "1.0.18" @@ -789,6 +1062,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "semver" version = "1.0.23" @@ -843,12 +1122,54 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + [[package]] name = "similar" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "smol_str" version = "0.3.1" @@ -859,12 +1180,40 @@ dependencies = [ "serde", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.77", +] + [[package]] name = "syn" version = "1.0.109" @@ -1001,6 +1350,17 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +[[package]] +name = "unicode-truncate" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" +dependencies = [ + "itertools 0.13.0", + "unicode-segmentation", + "unicode-width", +] + [[package]] name = "unicode-width" version = "0.1.13" @@ -1048,6 +1408,7 @@ dependencies = [ "clap_complete", "clap_mangen", "log", + "ratatui", "serde", "thiserror", "toml", @@ -1173,6 +1534,7 @@ version = "0.5.0" dependencies = [ "anyhow", "log", + "ratatui", "serde", "serde_json", "vvs_ass", @@ -1235,6 +1597,12 @@ dependencies = [ "winapi-util", ] +[[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.93" @@ -1300,6 +1668,22 @@ dependencies = [ "wasm-bindgen", ] +[[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.9" @@ -1309,6 +1693,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[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.48.0" diff --git a/src/Rust/Cargo.toml b/src/Rust/Cargo.toml index 1bada05b..f5a301a4 100644 --- a/src/Rust/Cargo.toml +++ b/src/Rust/Cargo.toml @@ -91,7 +91,8 @@ ttf-parser = { version = "*" } ab_glyph = { version = "*" } # CLI -clap_mangen = "*" # Could be replace by something crafter by hand… +ratatui = { version = "*", features = [ "macros", "palette" ] } +clap_mangen = "*" # TODO: Could be replace by something crafter by hand… clap_complete = "*" clap = { version = "*", default-features = false, features = [ "usage", diff --git a/src/Rust/vvs_cli/Cargo.toml b/src/Rust/vvs_cli/Cargo.toml index a83fa5d4..dc91c6da 100644 --- a/src/Rust/vvs_cli/Cargo.toml +++ b/src/Rust/vvs_cli/Cargo.toml @@ -27,6 +27,7 @@ log.workspace = true clap_mangen.workspace = true clap_complete.workspace = true clap.workspace = true +ratatui.workspace = true [build-dependencies] anyhow.workspace = true diff --git a/src/Rust/vvs_cli/src/args.rs b/src/Rust/vvs_cli/src/args.rs index 5f74ba2f..3b1bd4d7 100644 --- a/src/Rust/vvs_cli/src/args.rs +++ b/src/Rust/vvs_cli/src/args.rs @@ -1,9 +1,8 @@ use crate::parser::FileTypeValueParser; -use clap::Parser; use clap_complete::Shell; use std::path::PathBuf; -#[derive(Parser, Debug)] +#[derive(clap::Parser, Debug)] #[command( author , version , about @@ -11,7 +10,6 @@ use std::path::PathBuf; , groups = [ clap::ArgGroup::new("action").args(["manpage", "shell", "font-file", "script.vvs"]) , clap::ArgGroup::new("ass") .args(["subtitle.ass"]).conflicts_with_all(["manpage", "font-file"]) , clap::ArgGroup::new("opts") .args(["options.ini"]) .conflicts_with_all(["shell", "manpage", "font-file"]) - , clap::ArgGroup::new("infos") .args(["info"]) .conflicts_with_all(["shell", "manpage", "font-file"]) ])] pub struct Args { /// The script to run. @@ -58,19 +56,6 @@ pub struct Args { )] pub includes: Vec<PathBuf>, - /// Shows informations about a script. - /// - /// The informations consists of the loaded modules, all the options, their possible values, - /// the order of the jobs, etc. - /// - /// When printing informations about a script you won't be able to run it. You can however - /// print the informations about a script then enter in iteractive mode. - #[arg( short = 'P' - , long = "info" - , action = clap::ArgAction::SetTrue - )] - pub info: bool, - /// Display infos about embeded fonts or external fonts. #[arg( long = "font-info" , action = clap::ArgAction::Set diff --git a/src/Rust/vvs_cli/src/compiler.rs b/src/Rust/vvs_cli/src/compiler.rs new file mode 100644 index 00000000..9fafdcc6 --- /dev/null +++ b/src/Rust/vvs_cli/src/compiler.rs @@ -0,0 +1,48 @@ +use crate::args::Args; +use anyhow::Context as _; +use clap::CommandFactory as _; +use std::path::PathBuf; +use vvs_lang::{FrontendPipeline, SearchPath, SourceCode}; +use vvs_runtime::Runtime; +use vvs_xdg::file::TempFile; + +pub struct Settings { + pub script: Option<PathBuf>, + pub ass_file: Option<PathBuf>, + pub options: Option<PathBuf>, + pub includes: Vec<PathBuf>, + pub terminal: ratatui::DefaultTerminal, +} + +pub fn run(settings: Settings) -> anyhow::Result<()> { + let script = match settings.script { + Some(script) => SourceCode::from_path(&script)?, + None => return Ok(Args::command().print_help()?), + }; + let _ = script.module().context("expected a valid module name")?; + + let Settings { ass_file, options, includes, .. } = settings; + let output = FrontendPipeline::new(&script) + .passes(&[]) + .search( + &SearchPath::from_iter(includes) + .with_script_folder(script.folder().context("expected the script to have a parent folder")?), + ) + .options(options.as_ref())? + .run()?; + + let mut file = TempFile::new("vvcc")?; + Runtime::new(move |ctx| { + Ok(vvs_codegen::lowerer::Lowerer::new(&ctx, &output.main.name)? + .declare_globals(output.declared_functions())? + .lower_module(&output.main.name, output.ast)? + .lower_modules(output.imports)? + .generate_main(output.main)? + .finished()) + })? + .with_output_file(&mut file) + .with_terminal(settings.terminal) + .run_on_file(ass_file.context("no subtitle file to run the script on")?)?; + file.leak(); + Ok(()) +} diff --git a/src/Rust/vvs_cli/src/config.rs b/src/Rust/vvs_cli/src/config.rs index 25772ae6..026ea26f 100644 --- a/src/Rust/vvs_cli/src/config.rs +++ b/src/Rust/vvs_cli/src/config.rs @@ -29,7 +29,6 @@ pub struct Config { pub script: Option<PathBuf>, pub ass_file: Option<PathBuf>, pub options: Option<PathBuf>, - pub info: bool, pub manpage: bool, pub shell: Option<Shell>, pub font_info: Option<Option<PathBuf>>, @@ -114,7 +113,7 @@ impl Config { append args => self, { includes }; set_if_not args => self, { script, ass_file, options, shell, font_info }; max args => self, { verbose }; - override args => self, { info, manpage }; + override args => self, { manpage }; } self } diff --git a/src/Rust/vvs_cli/src/lib.rs b/src/Rust/vvs_cli/src/lib.rs index 2c31f840..784888b9 100644 --- a/src/Rust/vvs_cli/src/lib.rs +++ b/src/Rust/vvs_cli/src/lib.rs @@ -1,6 +1,7 @@ #![forbid(unsafe_code)] pub mod args; +pub mod compiler; pub mod config; pub mod logger; diff --git a/src/Rust/vvs_cli/src/main.rs b/src/Rust/vvs_cli/src/main.rs index c8030eca..ddf5ca0d 100644 --- a/src/Rust/vvs_cli/src/main.rs +++ b/src/Rust/vvs_cli/src/main.rs @@ -7,11 +7,10 @@ use clap::{CommandFactory as _, Parser as _}; use std::{fs, io, path::Path}; use vvs_cli::{ args::Args, + compiler, config::{Config, ConfigFile}, }; -use vvs_lang::{FrontendPipeline, SearchPath, SourceCode}; -use vvs_runtime::Runtime; -use vvs_xdg::{file::TempFile, XDGConfig, XDGConfigMergedSilent}; +use vvs_xdg::{XDGConfig, XDGConfigMergedSilent}; fn print_font(n: impl AsRef<Path>, f: &[u8]) -> Result<()> { let f = vvs_font::Font::try_from(f).with_context(|| format!("failed to parse font {}", n.as_ref().display()))?; @@ -27,7 +26,7 @@ fn print_font(n: impl AsRef<Path>, f: &[u8]) -> Result<()> { fn main() -> Result<()> { vvs_cli::logger::init(None).context("failed to init logger")?; - let Config { script, ass_file, options, info, manpage, shell, font_info, includes, .. } = Config::default() + let Config { script, ass_file, options, manpage, shell, font_info, includes, .. } = Config::default() .with_config_file( XDGConfig::<ConfigFile, XDGConfigMergedSilent>::new("vvcc") .file("vvcc.toml") @@ -36,60 +35,21 @@ fn main() -> Result<()> { .with_args(Args::parse()) .apply_logger(); - // Handle auxiliary stuff if manpage { - return clap_mangen::Man::new(Args::command()) + clap_mangen::Man::new(Args::command()) .render(&mut io::stdout()) - .context("failed to render manpage for vvcc"); + .context("failed to render manpage for vvcc") } else if let Some(shell) = shell { clap_complete::generate(shell, &mut Args::command(), Args::command().get_name().to_string(), &mut io::stdout()); - return Ok(()); + Ok(()) } else if let Some(font_info) = font_info { - return match font_info { + match font_info { Some(p) => print_font(&p, &fs::read(&p).with_context(|| format!("failed to read font: {}", p.display()))?), None => vvs_font::embeded_fonts().try_for_each(|(n, f)| print_font(n, f)), - }; - } - - // Parse, build, execute the script. - let script = match script { - Some(script) => SourceCode::from_path(&script)?, - None => return Ok(Args::command().print_help()?), - }; - println!("main module ........ {}", script.module().context("expected a valid module name")?); - let output = FrontendPipeline::new(&script) - .passes(&[]) - .search( - &SearchPath::from_iter(includes) - .with_script_folder(script.folder().context("expected the script to have a parent folder")?), - ) - .options(options.as_ref())? - .run()?; - - if info { - match ass_file { - Some(ref path) => println!("ass file ........... {}", path.display()), - None => println!("ass file ........... ø"), } - match options { - Some(path) => println!("options file ....... {}", path.display()), - None => println!("options file ....... ø"), - } - print!("{output}"); + } else { + compiler::run(compiler::Settings { script, ass_file, options, includes, terminal: ratatui::init() })?; + ratatui::restore(); + Ok(()) } - - let mut file = TempFile::new("vvcc")?; - Runtime::new(move |ctx| { - Ok(vvs_codegen::lowerer::Lowerer::new(&ctx, &output.main.name)? - .declare_globals(output.declared_functions())? - .lower_module(&output.main.name, output.ast)? - .lower_modules(output.imports)? - .generate_main(output.main)? - .finished()) - })? - .run_on_file(ass_file.context("no subtitle file to run the script on")?)? - .write_ass_to_file(&mut file)?; - - println!("output file ........ {}", file.leak().path().display()); - Ok(()) } diff --git a/src/Rust/vvs_runtime/Cargo.toml b/src/Rust/vvs_runtime/Cargo.toml index 25ee1821..40e2e947 100644 --- a/src/Rust/vvs_runtime/Cargo.toml +++ b/src/Rust/vvs_runtime/Cargo.toml @@ -11,6 +11,7 @@ log.workspace = true anyhow.workspace = true serde.workspace = true serde_json.workspace = true +ratatui.workspace = true vvs_runtime_types.workspace = true vvs_ass.workspace = true vvs_utils.workspace = true diff --git a/src/Rust/vvs_runtime/src/runtime.rs b/src/Rust/vvs_runtime/src/runtime.rs index 3eb25e53..a1b65e9c 100644 --- a/src/Rust/vvs_runtime/src/runtime.rs +++ b/src/Rust/vvs_runtime/src/runtime.rs @@ -1,28 +1,30 @@ use crate::workers::Workers; use anyhow::{bail, Context as _}; -use std::{ - path::Path, - sync::{ - atomic::{AtomicU64, Ordering}, - Arc, - }, - thread, -}; +use std::{fs, path::Path, sync::atomic::Ordering, thread}; use vvs_ass::{ass_container_from_file, ASSContainer}; use vvs_llvm::prelude::*; use vvs_runtime_types::types::VVRTTable; +use ratatui::{ + crossterm::event::{self, Event, KeyCode, KeyEventKind}, + widgets::{Block, Paragraph}, +}; + #[allow(dead_code)] -pub struct Runtime { +pub struct Runtime<'a> { jit: JIT, workers: Workers, + output: Option<&'a mut fs::File>, + terminal: Option<ratatui::DefaultTerminal>, } -impl Runtime { - pub fn new<'a>(init: impl FnOnce(Context<'a>) -> anyhow::Result<Module<'a>>) -> anyhow::Result<Self> { +impl<'a> Runtime<'a> { + pub fn new<'ctx>(init: impl FnOnce(Context<'ctx>) -> anyhow::Result<Module<'ctx>>) -> anyhow::Result<Self> { Ok(Self { jit: JIT::init(init)?, - workers: Workers::new(|flag: Arc<AtomicU64>| loop { + output: None, + terminal: None, + workers: Workers::new(|flag| loop { match flag.load(Ordering::SeqCst) { 0 => thread::yield_now(), u64::MAX => return Ok(()), @@ -32,13 +34,45 @@ impl Runtime { }) } - pub fn run_on_container(self, ass: ASSContainer<VVRTTable>) -> anyhow::Result<ASSContainer<VVRTTable>> { - todo!("run on {ass:?}") + pub fn with_output_file(self, output: &'a mut fs::File) -> Self { + Self { output: Some(output), ..self } } - pub fn run_on_file(self, file: impl AsRef<Path>) -> anyhow::Result<ASSContainer<VVRTTable>> { + pub fn with_terminal(self, terminal: ratatui::DefaultTerminal) -> Self { + Self { terminal: Some(terminal), ..self } + } + + pub fn run_on_file(self, file: impl AsRef<Path>) -> anyhow::Result<()> { self.run_on_container( ass_container_from_file::<VVRTTable>(file.as_ref()).context("failed to parse the subtitle file")?, ) } + + pub fn run_on_container(self, ass: ASSContainer<VVRTTable>) -> anyhow::Result<()> { + let Self { output, terminal, .. } = self; + log::error!("run on {ass:?}"); + + match terminal { + None => todo!("handle the case where we don't have a terminal"), + Some(mut terminal) => loop { + terminal.draw(|frame| { + frame.render_widget( + Paragraph::new("Hello World!").block(Block::bordered().title("Greeting")), + frame.area(), + ); + })?; + if let Event::Key(key) = event::read()? { + if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') { + break; + } + } + }, + } + + if let Some(output) = output { + ass.write_ass_to_file(output)?; + } + + Ok(()) + } } diff --git a/src/Rust/vvs_xdg/src/file/temp.rs b/src/Rust/vvs_xdg/src/file/temp.rs index 34816024..38360a1e 100644 --- a/src/Rust/vvs_xdg/src/file/temp.rs +++ b/src/Rust/vvs_xdg/src/file/temp.rs @@ -49,6 +49,18 @@ impl DerefMut for TempFile { } } +impl AsRef<File> for TempFile { + fn as_ref(&self) -> &File { + self.deref() + } +} + +impl AsMut<File> for TempFile { + fn as_mut(&mut self) -> &mut File { + self.deref_mut() + } +} + impl Drop for TempFile { fn drop(&mut self) { if !self.leak { -- GitLab