#[cfg(feature = "cli")]
use clap::Parser;
#[cfg(feature = "cli")]
use jumpcut::parse;
#[cfg(feature = "cli")]
use serde_json;
#[cfg(feature = "cli")]
use std::fs;
#[cfg(feature = "cli")]
use std::io::{self, Read, Write};
#[cfg(feature = "cli")]
use std::path::PathBuf;
#[cfg(feature = "cli")]
#[derive(Parser)]
#[command(
name = "JumpCut",
about = "A tool for converting Fountain screenplay documents into Final Draft (FDX) and HTML formats.",
version
)]
#[cfg(feature = "cli")]
struct Args {
#[arg(short, long, default_value = "fdx")]
format: String,
input: PathBuf,
output: Option<PathBuf>,
#[arg(short, long, value_name = "FILE", num_args = 0..=1, default_missing_value = "metadata.fountain")]
metadata: Option<PathBuf>,
}
#[cfg(feature = "cli")]
fn main() {
let opt = Args::parse();
let mut content = String::new();
if let Some(metadata_arg_path) = opt.metadata {
let mut actual_metadata_file_path = metadata_arg_path.clone();
if metadata_arg_path.to_str() == Some("metadata.fountain") {
if opt.input.is_file() {
if let Some(parent) = opt.input.parent() {
actual_metadata_file_path = parent.join("metadata.fountain");
} else {
actual_metadata_file_path = PathBuf::from("metadata.fountain");
}
} else {
actual_metadata_file_path = PathBuf::from("metadata.fountain");
}
}
match fs::read_to_string(&actual_metadata_file_path) {
Ok(metadata_content) => {
content.push_str(&metadata_content);
content.push_str("\n"); }
Err(e) => {
eprintln!(
"Error reading metadata file '{}': {}",
actual_metadata_file_path.display(),
e
);
std::process::exit(1);
}
}
}
if opt.input.is_file() {
content.push_str(&std::fs::read_to_string(&opt.input).expect("Could not read file."));
} else {
if opt.input.to_str() == Some("-") {
let mut buffer = String::new();
let stdin = io::stdin().read_to_string(&mut buffer);
match stdin {
Err(_) => panic!("Invalid text piped to function."),
Ok(_) => content.push_str(&buffer),
}
} else {
eprintln!("Error: Did not receive a valid file.");
std::process::exit(1);
}
}
let mut screenplay = parse(&content);
let mut output_text = String::new();
match opt.format {
x if x.to_lowercase() == "json" => {
let j = serde_json::to_string_pretty(&screenplay);
match j {
Ok(json) => output_text = json,
Err(e) => eprintln!("{}", e),
}
}
x if x.to_lowercase() == "fdx" => {
output_text = screenplay.to_final_draft();
}
x if x.to_lowercase() == "html" => {
output_text = screenplay.to_html(true);
}
_ => output_text = "nothing".to_string(),
}
match opt.output {
Some(outfile) => fs::write(outfile, output_text).expect("Unable to write file."),
None => {
let stdout = io::stdout();
let mut handle = io::BufWriter::new(stdout);
writeln!(handle, "{}", output_text).expect("Unable to write to buffer.");
}
}
}