use std::{fs::File, io::Cursor};
use clap::{CommandFactory, Parser};
use brainfuck_exe::Brainfuck;
#[derive(Parser, Debug)]
#[command(name = "Brainfuck-exe", author, version, about, arg_required_else_help = true)]
struct Args {
#[arg(value_parser, verbatim_doc_comment)]
code: Option<String>,
#[arg(short = 'f', long = "file", action)]
file: Option<String>,
#[arg(short = 'i', long, action)]
input: Option<String>,
#[arg(short = 'o', long, action)]
output: Option<String>,
#[arg(long, action, verbatim_doc_comment)]
max_cell_value: Option<u32>,
#[arg(long, action, verbatim_doc_comment)]
memory_size: Option<usize>,
#[arg(long, action, verbatim_doc_comment)]
flush_output: bool,
#[arg(long, action, verbatim_doc_comment)]
prompt_stdin_once: bool,
#[arg(long, action, verbatim_doc_comment)]
instructions_limit: Option<usize>,
#[arg(long, action)]
print_cells: bool,
}
#[allow(clippy::option_if_let_else, clippy::single_match_else)]
fn main() {
let args = Args::parse();
let mut interp =
if let Some(code) = args.code {
Brainfuck::new(code)
} else if let Some(file) = args.file {
match Brainfuck::from_file(&file) {
Ok(interp) => interp,
Err(_) => {
println!("Could not open the provided file: {file}");
std::process::exit(1);
}
}
} else {
let mut cmd = Args::command();
if cmd.print_long_help().is_err() {
println!("Something went wrong when printing the output.");
std::process::exit(1);
}
std::process::exit(0);
}
.with_flush(args.flush_output)
.prompt_stdin_once(args.prompt_stdin_once);
if let Some(input) = args.input {
let bytes = Cursor::new(
input.as_bytes().to_vec()
);
interp = interp.with_input(bytes);
}
if let Some(path) = args.output {
if let Ok(file) = File::create(&path) {
interp = interp.with_output(file);
} else {
println!("Failed to open the provided file: {path}");
std::process::exit(1);
}
}
if let Some(value) = args.max_cell_value {
interp = interp.with_max_value(value);
}
if let Some(size) = args.memory_size {
interp = interp.with_mem_size(size);
}
if let Some(limit) = args.instructions_limit {
interp = interp.with_instructions_limit(limit);
}
match interp.execute() {
Ok(cells) => if args.print_cells {
println!("\n\nCELLS: {cells:?}");
},
Err(e) => println!(
"Something went wrong: {e}"
),
}
}