From ad640926629ccaed164c65e63d19c07827aab2c9 Mon Sep 17 00:00:00 2001 From: jiyinyiyong Date: Fri, 21 May 2021 20:32:44 +0800 Subject: [PATCH] add a bundle_calcit command; bump 0.3.19 --- .github/workflows/publish.yaml | 6 +- .github/workflows/test.yaml | 6 +- Cargo.lock | 3 +- Cargo.toml | 10 ++- README.md | 30 +++++++ package.json | 2 +- src/bin/bundle_calcit.rs | 148 +++++++++++++++++++++++++++++++++ src/{main.rs => bin/cr.rs} | 0 8 files changed, 195 insertions(+), 10 deletions(-) create mode 100644 src/bin/bundle_calcit.rs rename src/{main.rs => bin/cr.rs} (100%) diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index ef436a8e..3b8dd629 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -15,14 +15,14 @@ jobs: toolchain: stable - run: cargo test - - run: cargo run calcit/compact.cirru --once - - run: cargo run calcit/snapshots/test.cirru --once + - run: cargo run --bin cr calcit/compact.cirru --once + - run: cargo run --bin cr calcit/snapshots/test.cirru --once - name: "try js" run: > yarn && yarn tsc - && cargo run calcit/snapshots/test.cirru --emit-js --once + && cargo run --bin cr calcit/snapshots/test.cirru --emit-js --once && ln -s ../../ node_modules/@calcit/procs && cp -v scripts/main.js js-out/ && target=node yarn webpack && node js-out/bundle.js diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 8312a9c9..e90c31e6 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -18,14 +18,14 @@ jobs: toolchain: stable - run: cargo test - - run: cargo run calcit/compact.cirru --once - - run: cargo run calcit/snapshots/test.cirru --once + - run: cargo run --bin cr calcit/compact.cirru --once + - run: cargo run --bin cr calcit/snapshots/test.cirru --once - name: "try js" run: > yarn && yarn tsc - && cargo run calcit/snapshots/test.cirru --emit-js --once + && cargo run --bin cr calcit/snapshots/test.cirru --emit-js --once && ln -s ../../ node_modules/@calcit/procs && cp -v scripts/main.js js-out/ && target=node yarn webpack && node js-out/bundle.js diff --git a/Cargo.lock b/Cargo.lock index 9e7b9905..4a1ccfb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -81,7 +81,7 @@ dependencies = [ [[package]] name = "calcit_runner" -version = "0.3.18" +version = "0.3.19" dependencies = [ "chrono", "cirru_edn", @@ -96,6 +96,7 @@ dependencies = [ "regex", "serde", "serde_json", + "walkdir", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index e25fd5fd..80776aef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "calcit_runner" -version = "0.3.18" +version = "0.3.19" authors = ["jiyinyiyong "] edition = "2018" license = "MIT" @@ -33,6 +33,8 @@ rand = "0.8.3" regex = "1.4.5" serde = { version = "1.0.125", features = ["derive"] } serde_json = "1.0.64" +walkdir = "2" + [lib] name = "calcit_runner" @@ -40,4 +42,8 @@ path = "src/lib.rs" [[bin]] name = "cr" -path = "src/main.rs" +path = "src/bin/cr.rs" + +[[bin]] +name = "bundle_calcit" +path = "src/bin/bundle_calcit.rs" diff --git a/README.md b/README.md index e43ed271..665b8e6c 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,36 @@ cr compact.cirru --emit-js --mjs # TODO compile to mjs For linux users, download pre-built binaries from http://bin.calcit-lang.org/linux/ . +### Bundler + +There's also another command for bundling `compact.cirru` from separated files: + +```bash +package.cirru +src/ + app.main.cirru + app.lib.cirru +``` + +`package.cirru` should contain fields like. + +```cirru +{} + :package |app + :modules $ [] + :init-fn |app.main/main! + :reload-fn |app.main/reload! + :version |0.0.1 +``` + +and files in `src/` are source files of namespace form and definitions. Ny running: + +```bash +bundle_calcit --src ./src --out ./compact.cirru +``` + +a bundled `compact.cirru` file will be included. + ### Development - [Cirru Parser](https://github.com/Cirru/parser.rs) for indentation-based syntax parsing. diff --git a/package.json b/package.json index 9ecb9fa0..4bdf7bfd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@calcit/procs", - "version": "0.3.18", + "version": "0.3.19", "main": "./lib/calcit.procs.js", "devDependencies": { "@types/node": "^15.0.1", diff --git a/src/bin/bundle_calcit.rs b/src/bin/bundle_calcit.rs new file mode 100644 index 00000000..7f067518 --- /dev/null +++ b/src/bin/bundle_calcit.rs @@ -0,0 +1,148 @@ +use cirru_edn::Edn; +use cirru_parser::Cirru; +use std::collections::HashMap; +use std::env; +use std::fs::{read_to_string, write}; +use std::io; +use std::path::Path; +use walkdir::WalkDir; + +pub fn main() -> io::Result<()> { + let cli_matches = parse_cli(); + let base_dir = Path::new(cli_matches.value_of("src").unwrap()); + let out_path = Path::new(cli_matches.value_of("out").unwrap()); + let out_file = match out_path.extension() { + Some(ext) => { + let ext_str = ext.to_str().unwrap(); + if ext_str == "cirru" { + out_path.to_path_buf() + } else { + return Err(io_err(format!("expected *.cirru file, got {}", ext_str))); + } + } + None => out_path.join("compact.cirru").to_path_buf(), + }; + + println!("reading from {}", base_dir.display()); + + let mut dict: HashMap = HashMap::new(); + let mut a: Vec = vec![]; + let package_file = Path::new(cli_matches.value_of("src").unwrap()) + .parent() + .unwrap() + .join("package.cirru"); + + let content = read_to_string(package_file)?; + let package_data = cirru_edn::parse(&content).map_err(|e| io_err(e))?; + + let pkg = package_data + .map_get("package") + .map_err(|e| io_err(e))? + .read_string() + .map_err(|e| io_err(e))?; + + dict.insert(Edn::Keyword(String::from("package")), Edn::Str(pkg)); + dict.insert(Edn::Keyword(String::from("configs")), package_data); + + let mut files: HashMap = HashMap::new(); + + for dir_entry in WalkDir::new(base_dir) { + let entry = dir_entry.unwrap(); + + if let Some(ext) = entry.path().extension() { + if ext.to_str().unwrap() == "cirru" { + let content = read_to_string(entry.path())?; + let file_data = cirru_parser::parse(&content).map_err(|e| io_err(e))?; + if let Cirru::List(xs) = file_data { + let mut file: HashMap = HashMap::new(); + let (ns_name, ns_code) = if let Some(Cirru::List(ns_form)) = xs.get(0) { + match (ns_form.get(0), ns_form.get(1)) { + (Some(Cirru::Leaf(x0)), Some(Cirru::Leaf(x1))) if x0.as_str() == "ns" => (x1.to_string(), ns_form), + (a, b) => return Err(io_err(format!("in valid ns starts {:?} {:?}", a, b))), + } + } else { + return Err(io_err(format!( + "first expression of file should be a ns form, got: {:?}", + xs.get(0) + ))); + }; + file.insert( + Edn::Keyword(String::from("ns")), + Edn::Quote(Cirru::List(ns_code.to_owned())), + ); + + let mut defs: HashMap = HashMap::new(); + for (idx, line) in xs.iter().enumerate() { + if idx > 0 { + if let Cirru::List(ys) = line { + match (ys.get(0), ys.get(1)) { + (Some(Cirru::Leaf(x0)), Some(Cirru::Leaf(x1))) => { + if x0 == "def" || x0 == "defn" || x0 == "defmacro" || x0 == "defatom" { + defs.insert(Edn::Str(x1.to_owned()), Edn::Quote(line.to_owned())); + } else { + return Err(io_err(format!("invalid def op: {}", x0))); + } + } + (a, b) => { + return Err(io_err(format!("invalid def code {:?} {:?}", a, b))); + } + } + } else { + return Err(io_err(format!("file line not an expr {}", line))); + } + } else { + () + } + } + + file.insert(Edn::Keyword(String::from("defs")), Edn::Map(defs)); + files.insert(Edn::Str(ns_name.to_owned()), Edn::Map(file)); + } else { + return Err(io_err(format!("file should be expressions, molformed, {}", file_data))); + } + // println!("bunding {}", entry.path().display()); + a.push(entry.path().to_str().unwrap().to_string()); + } + } + } + + dict.insert(Edn::Keyword(String::from("files")), Edn::Map(files)); + + // println!("data {}", Edn::Map(dict)); + + write(&out_file, cirru_edn::format(&Edn::Map(dict.clone()), true).unwrap())?; + println!("\nfile created. you can run it with:\n\ncr -1 {}\n", out_file.display()); + + Ok(()) +} + +pub const CALCIT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +fn parse_cli<'a>() -> clap::ArgMatches<'a> { + clap::App::new("Calcit Runner") + .version(CALCIT_VERSION) + .author("Jon. ") + .about("Calcit Runner Bundler") + .arg( + clap::Arg::with_name("src") + .help("source folder") + .default_value("src/") + .short("s") + .long("src") + .takes_value(true), + ) + .arg( + clap::Arg::with_name("out") + .help("output folder") + .default_value("./") // TODO a better default value + .short("o") + .long("out") + .takes_value(true), + ) + .get_matches() +} + +// simulate an IO error with String +fn io_err(e: String) -> io::Error { + io::Error::new(io::ErrorKind::InvalidData, e) +} diff --git a/src/main.rs b/src/bin/cr.rs similarity index 100% rename from src/main.rs rename to src/bin/cr.rs