extern crate anyhow;
extern crate mallardscript;
extern crate pest_duckyscript;
use anyhow::{anyhow, Context, Result};
use mallardscript::compile;
use pest_duckyscript::duckyscript;
use std::collections::HashMap;
use std::path::PathBuf;
fn main() -> Result<()> {
let args = create_application()?.get_matches();
initialize_logger();
if let Err(e) = run(args) {
eprintln!("{:?}", e);
std::process::exit(2);
}
std::process::exit(0);
}
fn create_application() -> Result<clap::App<'static, 'static>> {
return Ok(clap::App::new(clap::crate_name!())
.bin_name(clap::crate_name!())
.version(clap::crate_version!())
.author(clap::crate_authors!())
.about(clap::crate_description!())
.setting(clap::AppSettings::ArgRequiredElseHelp)
.subcommand(
clap::SubCommand::with_name("completions")
.about("completions")
.arg(
clap::Arg::with_name("type")
.short("t")
.long("type")
.required(true)
.takes_value(true)
.possible_values(&["Bash", "Elvish", "Fish", "PowerShell", "Zsh"])
.case_insensitive(true),
),
)
.subcommand(
clap::SubCommand::with_name("build")
.about("build mallardscript input")
.arg(
clap::Arg::with_name("input")
.short("in")
.long("input")
.required(false)
.takes_value(true)
.default_value("index.ducky")
.help("entry file to compile"),
)
.arg(
clap::Arg::with_name("output")
.short("out")
.long("output")
.required(false)
.takes_value(true)
.default_value("output")
.help("out directory to build to"),
),
));
}
fn initialize_logger() {
let env = env_logger::Env::default();
return env_logger::Builder::from_env(env)
.target(env_logger::Target::Stdout)
.init();
}
fn run(args: clap::ArgMatches) -> Result<()> {
if args.subcommand_matches("completions").is_some() {
return command_completions(args);
} else if args.subcommand_matches("build").is_some() {
return command_build(args);
}
return Err(anyhow!("No supported command provided."));
}
fn command_completions(args: clap::ArgMatches) -> Result<()> {
let args_completions = args.subcommand_matches("completions").unwrap();
let completion_type = args_completions.value_of("type").unwrap();
if completion_type == "bash" {
create_application()?.gen_completions_to(
create_application()?.get_bin_name().unwrap(),
clap::Shell::Bash,
&mut std::io::stdout(),
);
} else if completion_type == "elvish" {
create_application()?.gen_completions_to(
create_application()?.get_bin_name().unwrap(),
clap::Shell::Elvish,
&mut std::io::stdout(),
);
} else if completion_type == "fish" {
create_application()?.gen_completions_to(
create_application()?.get_bin_name().unwrap(),
clap::Shell::Fish,
&mut std::io::stdout(),
);
} else if completion_type == "powershell" {
create_application()?.gen_completions_to(
create_application()?.get_bin_name().unwrap(),
clap::Shell::PowerShell,
&mut std::io::stdout(),
);
} else if completion_type == "zsh" {
create_application()?.gen_completions_to(
create_application()?.get_bin_name().unwrap(),
clap::Shell::Zsh,
&mut std::io::stdout(),
);
} else {
return Err(anyhow!(
"Completion type '{}' not supported.",
completion_type
));
}
Ok(())
}
fn command_build(args: clap::ArgMatches) -> Result<()> {
let args_build = args.subcommand_matches("build").unwrap();
let input = args_build.value_of("input").unwrap();
let output = args_build.value_of("output").unwrap();
let mut output_path = PathBuf::from(shellexpand::tilde(output).into_owned());
output_path.push("index.ducky");
let output_file_path = &output_path.clone();
let current_directory = &std::env::current_dir().unwrap();
println!("Build MallardScript.");
println!(" Current Directory: '{}'", current_directory.display());
println!(" Input: '{}'", input);
println!(" Output: '{}'", output);
let output_file = std::fs::File::create(output_file_path).context(format!(
"Failed to create output file '{}'.",
output_file_path.display()
))?;
compile(
current_directory.clone(),
input,
&output_file,
0,
&mut HashMap::new(),
)
.context(format!(
"Failed to compile to output file '{}'.",
output_file_path.display()
))?;
let output_contents = std::fs::read_to_string(output_file_path).with_context(|| {
format!(
"Unable load compiled output '{}'.",
output_file_path.display()
)
})?;
duckyscript::parser::parse_document(output_contents).with_context(|| {
format!(
"Unable to validate compiled output '{}'.",
output_file_path.display(),
)
})?;
println!("Done.");
Ok(())
}