commit 79f214478cb2c969a713b514eaef9496ab501490 from: Benjamin Stürz date: Wed Jun 26 22:15:02 2024 UTC improve commit - c5de16c57b82f6abd2a6ebbe2cbed524347bac05 commit + 79f214478cb2c969a713b514eaef9496ab501490 blob - ea8c4bf7f35f6f77f75d92ad8ce8349f6e81ddba blob + fe6bb941ff7e1fb38488bb5c42014a9aeb8f961f --- .gitignore +++ .gitignore @@ -1 +1,3 @@ -/target +target +*.dv +*.gif blob - 1a84a0966df721c2c027591b4b9ac8d6913f5d73 blob + 6050ffabec52b70b71a6b0baef7e71a114a1bb4f --- Cargo.lock +++ Cargo.lock @@ -3,6 +3,71 @@ version = 3 [[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "autovis" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "pest", + "pest_derive", +] + +[[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -16,6 +81,52 @@ name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "cpufeatures" @@ -47,14 +158,6 @@ dependencies = [ ] [[package]] -name = "dotvis" -version = "0.1.0" -dependencies = [ - "pest", - "pest_derive", -] - -[[package]] name = "generic-array" version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -65,6 +168,18 @@ dependencies = [ ] [[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] name = "libc" version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -157,6 +272,12 @@ dependencies = [ ] [[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] name = "syn" version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -206,7 +327,86 @@ source = "registry+https://github.com/rust-lang/crates checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" blob - 38731a70a889e12000e18791b8a66394d668c4c6 blob + 0b42331bd0da0d8281ec5a68155484dc0a78672c --- Cargo.toml +++ Cargo.toml @@ -1,8 +1,10 @@ [package] -name = "dotvis" +name = "autovis" version = "0.1.0" edition = "2021" [dependencies] +anyhow = "1.0.86" +clap = { version = "4.5.7", features = ["derive"] } pest = "2.7.10" pest_derive = "2.7.10" blob - /dev/null blob + 1f763def82bb7b3655169f50f4d8aba37aa0abd4 (mode 644) --- /dev/null +++ src/cli.rs @@ -0,0 +1,15 @@ +use std::path::PathBuf; + +use clap::Parser; + +#[derive(Parser)] +pub struct Cli { + pub rules: PathBuf, + pub input: String, + + #[arg(short, long)] + pub output: Option, + + #[arg(short, long, default_value_t = 100)] + pub delay: u32, +} blob - dc25e626edaf9acb9c66b01542810d85de4a6932 blob + 5f1f8388cc24ea4e6eb173bbbb53c067d47f1fa7 --- src/main.rs +++ src/main.rs @@ -1,75 +1,112 @@ -use std::{path::Path, process::{Command, Stdio}, io::Write}; +use std::{io::{ErrorKind, Write}, path::Path, process::{Command, Stdio}}; +use anyhow::{bail, Context, Result}; +use clap::Parser; +use crate::{ast::Machine, cli::Cli}; -use ast::Machine; - mod ast; +mod cli; mod parser; -fn write(mach: &Machine, tmpdir: &Path, id: usize) { +fn write(mach: &Machine, tmpdir: &Path, id: usize) -> Result<()> { let path = tmpdir.join(format!("{id}.png")); + let mut cmd = Command::new("dot") .args(&["-Tpng", "-o"]) .arg(path) .stdin(Stdio::piped()) .spawn() - .unwrap(); + .context("failed to spawn dot")?; - let mut stdin = cmd.stdin.take().unwrap(); + let mut stdin = cmd + .stdin + .take() + .context("failed to take stdin")?; - writeln!(&mut stdin, "{mach}").unwrap(); + writeln!(&mut stdin, "{mach}") + .context("failed to print machine")?; + drop(stdin); - cmd.wait().unwrap(); + cmd + .wait() + .context("failed to wait for completion")?; + + Ok(()) } -fn compile(out: &Path, tmpdir: &Path, num: usize) { - let size = imgsize(&tmpdir.join(format!("{}.png", num - 1))); +fn imgsize(path: &Path) -> Result { + let data = Command::new("identify") + .args(&["-format", "%wx%h"]) + .arg(path) + .output() + .context("failed to spawn identify")? + .stdout; + let s = String::from_utf8(data) + .context("failed to parse output of identify")?; + Ok(s) +} + +fn compile(out: &Path, tmpdir: &Path, num: usize, delay: u32) -> Result<()> { + let size = imgsize(&tmpdir.join(format!("{}.png", num - 1))) + .context("failed to determine gif dimensions")?; + let mut cmd = Command::new("convert"); + let delay = delay.to_string(); + for i in 0..num { let path = tmpdir.join(format!("{i}.png")); - cmd.args(&["-delay", "100"]).arg(path); + cmd.args(&["-delay", &delay]).arg(path); } let st = cmd .args(&["-extent", &size]) .arg(out) .status() - .unwrap() + .context("failed to spawn convert")? .success(); if !st { - panic!("not ok"); + bail!("convert failed"); } -} -fn imgsize(path: &Path) -> String { - let data = Command::new("identify") - .args(&["-format", "%wx%h"]) - .arg(path) - .output() - .unwrap() - .stdout; - String::from_utf8(data).unwrap() + Ok(()) } -fn main() { - let tmpdir = std::env::temp_dir(); - let input = "011"; - let s = std::fs::read_to_string("test.dv").expect("failed to read"); - let mut mach = crate::parser::parse(&s).expect("failed to parse"); +fn main() -> Result<()> { + let cli = Cli::parse(); + + let tmpdir = std::env::temp_dir() + .join("autovis"); - write(&mach, &tmpdir, 0); + std::fs::create_dir_all(&tmpdir) + .or_else(|e| match e.kind() { + ErrorKind::AlreadyExists => Ok(()), + _ => Err(e), + }) + .context("failed to create temporary directory")?; + + let mach = std::fs::read_to_string(&cli.rules) + .context("faile to read automaton")?; + let mut mach = crate::parser::parse(&mach) + .context("failed to parse automaton")?; + + write(&mach, &tmpdir, 0)?; + let mut id = 1; - for ch in input.chars() { + for ch in cli.input.chars() { if !mach.feed(ch) { break; } - write(&mach, &tmpdir, id); + write(&mach, &tmpdir, id)?; id = id + 1; } - let out = Path::new("test.gif"); - compile(out, &tmpdir, id); + let out = cli + .output + .as_deref() + .unwrap_or(Path::new("a.gif")); + compile(out, &tmpdir, id, cli.delay)?; + Ok(()) } blob - 71fd85b7c74a163cd6f80dacc8695839566c9c77 blob + 02b1288f3b75a0ed3978c9abda3ef8d4308494b8 --- src/parser.rs +++ src/parser.rs @@ -1,8 +1,6 @@ use std::collections::BTreeMap; - use pest::{error::Error, iterators::Pair, Parser}; use pest_derive::Parser; - use crate::ast::{Edge, Machine, Node}; #[derive(Parser)]