Skip to content

Commit

Permalink
Clean up generator (#84)
Browse files Browse the repository at this point in the history
* Now uses rust-embed (fixes #69 )
* widened bound for render_template
* de-duplicated code inside generator/common.rs by moving different cargo_/some_command/ functions to single macro cargo_command!
* calling cargo fmt should work now
  • Loading branch information
bird-dancer committed Jul 5, 2023
1 parent 30dd9f3 commit 3d36917
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 92 deletions.
103 changes: 37 additions & 66 deletions src/generator/common.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
use crate::generator::template_functions::TEMPLATE_FUNCTIONS;
use crate::{generator::template_functions::TEMPLATE_FUNCTIONS, Templates};
use crate::{template_context::TemplateContext, utils};
use gtmpl::Context;
use std::{
ffi::OsStr,
fs,
path::{Path, PathBuf},
process::{Command, Output},
};
use std::path::{Path, PathBuf};

/// runs cargo command with options
/// Example: ` cargo_command!("init","--bin","path"); `
#[macro_export]
macro_rules! cargo_command {
( $( $x:expr ),* ) => {
{
let mut command = Command::new("cargo");
$(
command.arg($x);
)*
command.output().expect("failed cargo_command")
}
};
}

pub fn check_for_overwrite(output_path: &Path, project_title: &str) {
//check if project with name already exists, if yes ask for permission to overwrite
Expand All @@ -30,54 +40,25 @@ pub fn check_for_overwrite(output_path: &Path, project_title: &str) {
}
}

/// initialize a cargo project in path
pub fn cargo_init_project(path: impl AsRef<OsStr>) -> Output {
Command::new("cargo")
.arg("init")
.arg("--bin")
.arg(path)
.output()
.expect("failed create new cargo project")
}
/// runs cargo format on path
pub fn cargo_fmt(path: impl AsRef<OsStr>) -> Output {
Command::new("cargo")
.arg("fmt")
.arg("--")
.arg(path)
.output()
.expect("failed to format")
}

/// cargo fix, mostly for cleaning unused imports
pub fn cargo_fix(path: &PathBuf) -> Output {
Command::new("cargo")
.arg("fix")
.arg("--bin")
.arg(path)
.arg("--allow-dirty")
.output()
.expect("failed to cargo fix")
}

/// reads template from path renders it with context reference and writes to output file
pub fn template_render_write(
template_path: &PathBuf,
template_path: &str,
context_ref: impl Into<gtmpl::Value>,
output_path: &PathBuf,
) {
let template = match fs::read_to_string(template_path) {
Ok(template) => template,
Err(e) => {
eprintln!(
"❌ Error reading template {:#?}: {}",
template_path.to_str(),
e
);
let template = match Templates::get(template_path) {
Some(template) => template,
None => {
eprintln!("❌ Error reading template");
std::process::exit(1);
}
};
let mut render = match render_template(&template, context_ref, TEMPLATE_FUNCTIONS) {
let template = template.data.as_ref();
let mut render = match render_template(
std::str::from_utf8(template).unwrap(),
context_ref,
TEMPLATE_FUNCTIONS,
) {
Ok(render) => render,
Err(e) => {
eprintln!("❌ Error rendering template: {}", e);
Expand All @@ -101,8 +82,8 @@ pub fn template_render_write(

/// parses templates, adds funcs so they can be executed from inside the template and renders templatey
/// just like `gtmpl::render` but supports adding template functions
fn render_template<C: Into<gtmpl::Value>, F: Into<String> + Clone>(
template_str: &str,
fn render_template<T: Into<String>, C: Into<gtmpl::Value>, F: Into<String> + Clone>(
template_str: T,
context: C,
template_functions: &[(F, gtmpl::Func)],
) -> Result<String, gtmpl::TemplateError> {
Expand All @@ -113,33 +94,23 @@ fn render_template<C: Into<gtmpl::Value>, F: Into<String> + Clone>(
}

pub fn write_multiple_templates(
template_path: &Path,
context_ref: &TemplateContext,
output_path: &Path,
endings: &[&str],
template_file_paths: &[&str],
) {
for ending in endings {
if ending.ends_with(".go") {
for template_file_path in template_file_paths {
if template_file_path.ends_with(".go") {
template_render_write(
&template_path.join(ending),
template_file_path,
context_ref,
&output_path.join(ending).with_extension("rs"),
&output_path.join(template_file_path).with_extension("rs"),
);
} else {
template_render_write(
&template_path.join(ending),
template_file_path,
context_ref,
&output_path.join(ending),
&output_path.join(template_file_path),
);
}
}
}

pub fn cargo_generate_rustdoc(path: &Path) {
Command::new("cargo")
.current_dir(path)
.arg("doc")
.arg("--no-deps")
.output()
.expect("failed to generate rustdoc");
}
9 changes: 4 additions & 5 deletions src/generator/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
mod common;
pub use common::{check_for_overwrite, template_render_write, write_multiple_templates};

mod model;
pub use common::{
cargo_fix, cargo_fmt, cargo_generate_rustdoc, cargo_init_project, check_for_overwrite,
template_render_write, write_multiple_templates,
};
mod template_functions;
pub use model::generate_models_folder;

mod template_functions;
8 changes: 2 additions & 6 deletions src/generator/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,15 @@ use crate::{parser::common::validate_identifier_string, utils::write_to_path_cre

use std::path::Path;

pub fn generate_models_folder(
async_config: &TemplateContext,
template_path: &Path,
output_path: &Path,
) {
pub fn generate_models_folder(async_config: &TemplateContext, output_path: &Path) {
async_config
.model
.message_models
.iter()
.for_each(|message_model| {
if !message_model.model_definition.is_empty() {
template_render_write(
&template_path.join("src/model.go"),
"src/model.go",
message_model.clone(),
&output_path.join(format!(
"src/model/{}.rs",
Expand Down
31 changes: 16 additions & 15 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@ mod utils;

use crate::{
asyncapi_model::AsyncAPI,
generator::{
cargo_fix, cargo_generate_rustdoc, check_for_overwrite, generate_models_folder,
write_multiple_templates,
},
generator::{check_for_overwrite, generate_models_folder, write_multiple_templates},
utils::append_file_to_file,
};

use clap::Parser;
use generator::{cargo_fmt, cargo_init_project};
use rust_embed::RustEmbed;
use std::path::Path;
use std::process::Command;

#[derive(RustEmbed)]
#[folder = "./templates"]
struct Templates;

fn main() {
let args = cli::Args::parse();
Expand Down Expand Up @@ -56,7 +57,6 @@ fn main() {
check_for_overwrite(output_path, title);

write_multiple_templates(
template_path,
&async_config,
output_path,
&[
Expand All @@ -72,24 +72,25 @@ fn main() {
],
);

generate_models_folder(&async_config, template_path, output_path);
println!("🚀 File generation finished, adding dependencies...");
generate_models_folder(&async_config, output_path);

// make output a compilable project
cargo_init_project(output_path);
println!("🚀 File generation finished, adding dependencies...");

cargo_fmt(output_path.join("src/main.rs"));
// make output a compilable project in output_path
cargo_command!("init", "--bin", output_path);
// runs cargo format on path
cargo_command!("fmt", "--", output_path.join("src/main.rs"));
// add dependencies
append_file_to_file(
template_path.join("dependencies.toml"),
output_path.join("Cargo.toml"),
)
.unwrap();

cargo_fix(output_path);
// cargo fix, mostly for cleaning unused imports
cargo_command!("fix", "--bin", output_path, "--allow-dirty");

if args.doc {
println!("📚 Generating docs...");
cargo_generate_rustdoc(output_path);
cargo_command!(output_path, "doc", "--no-deps");
}
}

0 comments on commit 3d36917

Please sign in to comment.