use anyhow::Result; use std::convert::TryFrom; use std::path::{Path, PathBuf}; use structopt::StructOpt; use subplot::Document; #[derive(Debug, StructOpt)] #[structopt(name = "sp-meta", about = "Show Subplot document metadata.")] struct Opt { // Input filename. #[structopt(parse(from_os_str))] filename: PathBuf, } struct Metadata { sources: Vec, title: String, binding_files: Vec, function_files: Vec, bibliographies: Vec, scenarios: Vec, } impl TryFrom<&mut Document> for Metadata { type Error = subplot::SubplotError; fn try_from(doc: &mut Document) -> std::result::Result { let sources: Vec<_> = doc .sources() .into_iter() .map(|p| filename(Some(&p))) .collect(); let title = doc.meta().title().to_owned(); let binding_files = doc .meta() .bindings_filenames() .into_iter() .map(|p| filename(Some(&p))) .collect(); let function_files = doc .meta() .functions_filenames() .into_iter() .map(|p| filename(Some(&p))) .collect(); let bibliographies = doc .meta() .bibliographies() .into_iter() .map(|p| filename(Some(&p))) .collect(); let scenarios = doc .scenarios()? .into_iter() .map(|s| s.title().to_owned()) .collect(); Ok(Self { sources, title, binding_files, function_files, bibliographies, scenarios, }) } } impl Metadata { fn write_list(v: &[String], prefix: &str) { v.iter().for_each(|entry| println!("{}: {}", prefix, entry)) } fn write_out(&self) { Self::write_list(&self.sources, "source"); println!("title: {}", self.title); Self::write_list(&self.binding_files, "bindings"); Self::write_list(&self.function_files, "functions"); Self::write_list(&self.bibliographies, "bibliography"); Self::write_list(&self.scenarios, "scenario"); } } fn main() -> Result<()> { let opt = Opt::from_args(); let basedir = subplot::get_basedir_from(&opt.filename)?; let mut doc = Document::from_file(&basedir, &opt.filename)?; let meta = Metadata::try_from(&mut doc)?; meta.write_out(); Ok(()) } fn filename(name: Option<&Path>) -> String { let path = match name { None => return "".to_string(), Some(x) => x, }; match path.to_str() { None => "non-UTF8 filename".to_string(), Some(x) => x.to_string(), } }