summaryrefslogtreecommitdiff
path: root/src/bin/cli/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/cli/mod.rs')
-rw-r--r--src/bin/cli/mod.rs133
1 files changed, 133 insertions, 0 deletions
diff --git a/src/bin/cli/mod.rs b/src/bin/cli/mod.rs
new file mode 100644
index 0000000..f3225db
--- /dev/null
+++ b/src/bin/cli/mod.rs
@@ -0,0 +1,133 @@
+//! CLI Functionality abstractions
+
+#![allow(unused)]
+
+use anyhow::Result;
+use serde::Serialize;
+use subplot::{DataFile, Document, Style, SubplotError};
+
+use std::convert::TryFrom;
+use std::path::Path;
+use std::str::FromStr;
+
+pub fn load_document<P: AsRef<Path>>(filename: P, style: Style) -> Result<Document> {
+ let filename = filename.as_ref();
+ let base_path = subplot::get_basedir_from(filename)?;
+ let doc = Document::from_file(&base_path, filename, style)?;
+
+ Ok(doc)
+}
+
+pub fn extract_file<'a>(doc: &'a Document, filename: &str) -> Result<&'a DataFile> {
+ for file in doc.files() {
+ if file.filename() == filename {
+ return Ok(file);
+ }
+ }
+ Err(SubplotError::EmbeddedFileNotFound(filename.to_owned()).into())
+}
+
+#[derive(Serialize)]
+pub struct Metadata {
+ sources: Vec<String>,
+ title: String,
+ binding_files: Vec<String>,
+ function_files: Vec<String>,
+ bibliographies: Vec<String>,
+ scenarios: Vec<String>,
+ files: Vec<String>,
+}
+
+impl TryFrom<&mut Document> for Metadata {
+ type Error = subplot::SubplotError;
+ fn try_from(doc: &mut Document) -> std::result::Result<Self, Self::Error> {
+ 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();
+ let files = doc
+ .files()
+ .iter()
+ .map(|f| f.filename().to_owned())
+ .collect();
+ Ok(Self {
+ sources,
+ title,
+ binding_files,
+ function_files,
+ bibliographies,
+ scenarios,
+ files,
+ })
+ }
+}
+
+impl Metadata {
+ fn write_list(v: &[String], prefix: &str) {
+ v.iter().for_each(|entry| println!("{}: {}", prefix, entry))
+ }
+
+ pub 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.files, "file");
+ Self::write_list(&self.scenarios, "scenario");
+ }
+}
+
+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(),
+ }
+}
+
+#[derive(Debug)]
+pub enum OutputFormat {
+ Plain,
+ Json,
+}
+
+impl FromStr for OutputFormat {
+ type Err = String;
+
+ fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
+ match s.to_ascii_lowercase().as_ref() {
+ "plain" => Ok(OutputFormat::Plain),
+ "json" => Ok(OutputFormat::Json),
+ _ => Err(format!("Unknown output format: `{}`", s)),
+ }
+ }
+}