From e773caea8010b87726ea524d31798fb2e43e12f4 Mon Sep 17 00:00:00 2001 From: Minijackson Date: Sat, 21 Dec 2019 12:13:21 +0100 Subject: newtype in types, more generator config, parsing -> parser --- src/generator/config.rs | 52 ++++++++++++++++++++++++++++++++++++------------- src/generator/mod.rs | 42 +++++++++++++++++++++++++-------------- src/generator/pandoc.rs | 19 ++++++++---------- 3 files changed, 73 insertions(+), 40 deletions(-) (limited to 'src/generator') diff --git a/src/generator/config.rs b/src/generator/config.rs index 43fee60..3057fee 100644 --- a/src/generator/config.rs +++ b/src/generator/config.rs @@ -1,40 +1,58 @@ +use crate::types::*; + use serde_derive::{Deserialize, Serialize}; use structopt::StructOpt; use std::collections::{HashMap, HashSet}; +pub(crate) type Inlines = HashMap>>; + #[derive(Debug, Clone, Serialize)] pub(crate) struct Config { + pub(super) from: String, + pub(super) to: String, + pub(super) pandoc_filters: Vec, /// Tells us in which language, which entity types should inline which children entity type in /// their documentation. /// /// e.g. in C++, classes should inline their children methods documentation. - pub(crate) inlines: HashMap>>, + pub(super) inlines: Inlines, } impl Config { - pub(crate) fn from_merge(_cli: ProvidedConfig, conf: ProvidedConfig) -> Self { + pub(crate) fn from_merge(mut cli: ProvidedConfig, mut conf: ProvidedConfig) -> Self { + conf.pandoc_filters.append(&mut cli.pandoc_filters); Self { + from: cli + .from + .or(conf.from) + .unwrap_or_else(|| String::from("markdown-raw_tex")), + to: cli.to.or(conf.to).unwrap_or_else(|| String::from("html")), + pandoc_filters: conf.pandoc_filters, inlines: conf.inlines.unwrap_or_else(default_inlines), } } } -fn default_inlines() -> HashMap>> { +fn default_inlines() -> Inlines { let mut clang = HashMap::new(); let mut clang_inline_children = HashSet::new(); - // TODO: this is not great: no differences between variable/field for children, but differences - // as a parent... - clang_inline_children.insert(String::from("variable")); - //classes.insert(String::from("field")); - clang_inline_children.insert(String::from("function")); - //classes.insert(String::from("method")); - clang.insert(String::from("struct"), clang_inline_children.clone()); - clang.insert(String::from("class"), clang_inline_children.clone()); - clang.insert(String::from("namespace"), clang_inline_children); + clang_inline_children.insert(ChildrenKind(String::from("variables"))); + clang_inline_children.insert(ChildrenKind(String::from("fields"))); + clang_inline_children.insert(ChildrenKind(String::from("functions"))); + clang_inline_children.insert(ChildrenKind(String::from("methods"))); + clang.insert( + EntityKind(String::from("struct")), + clang_inline_children.clone(), + ); + clang.insert( + EntityKind(String::from("class")), + clang_inline_children.clone(), + ); + clang.insert(EntityKind(String::from("namespace")), clang_inline_children); let mut inlines = HashMap::new(); - inlines.insert(String::from("clang"), clang); + inlines.insert(Language::Clang, clang); inlines } @@ -48,6 +66,12 @@ impl Default for Config { #[derive(Debug, Clone, Default, StructOpt, Deserialize, Serialize)] #[serde(rename_all = "kebab-case")] pub(crate) struct ProvidedConfig { + #[structopt(long = "generator-from")] + pub(super) from: Option, + #[structopt(long = "generator-to")] + pub(super) to: Option, + #[structopt(long = "generator-pandoc-filters", number_of_values = 1)] + pub(super) pandoc_filters: Vec, #[structopt(skip)] - pub(crate) inlines: Option>>>, + pub(super) inlines: Option, } diff --git a/src/generator/mod.rs b/src/generator/mod.rs index b4e1c94..3f62779 100644 --- a/src/generator/mod.rs +++ b/src/generator/mod.rs @@ -2,11 +2,8 @@ pub(crate) mod config; mod pandoc; use self::config::Config; -//use crate::entities::{ -// Description, DynEntity, EntitiesManager, EntitiesManagerComponents, Usr, -//}; use self::pandoc::into_pandoc; -use crate::types::Entity; +use crate::types::*; use anyhow::{ensure, Context, Result}; use rayon::Scope; @@ -18,7 +15,11 @@ use std::path::Path; const DEFAULT_CSS: &[u8] = include_bytes!("../../res/style.css"); -pub(crate) fn generate(base_dir: &Path, entities: BTreeMap, config: &Config) -> Result<()> { +pub(crate) fn generate( + base_dir: &Path, + entities: BTreeMap, + config: &Config, +) -> Result<()> { let md_output_dir = base_dir.join("markdown"); let html_output_dir = base_dir.join("html"); @@ -54,7 +55,7 @@ pub(crate) fn generate(base_dir: &Path, entities: BTreeMap, conf } fn generate_recursively<'a>( - id: String, + id: EntityId, entity: Entity, pool: &Scope<'a>, md_output_dir: &'a Path, @@ -63,7 +64,7 @@ fn generate_recursively<'a>( config: &'a Config, ) { pool.spawn(move |pool| { - trace!("Trying to generate {}", id); + trace!("Trying to generate {}", id.0); let leftovers = generate_single( &id, @@ -90,18 +91,18 @@ fn generate_recursively<'a>( } fn generate_single( - id: &str, + id: &EntityId, entity: Entity, md_output_dir: impl AsRef, html_output_dir: impl AsRef, css_path: impl AsRef, - config: &Config -) -> Result> { + config: &Config, +) -> Result> { use std::io::prelude::*; use std::process::{Command, Stdio}; - let md_output_file = md_output_dir.as_ref().join(id); - let html_output_file = html_output_dir.as_ref().join(id); + let md_output_file = md_output_dir.as_ref().join(&id.0); + let html_output_file = html_output_dir.as_ref().join(&id.0); let mut command = Command::new("pandoc"); @@ -111,7 +112,10 @@ fn generate_single( .stderr(Stdio::piped()) .args(&[ "--from=json", - "--to=markdown", + // standalone keeps the sent metadat + "--standalone", + "--to", + &config.from, "--output", md_output_file .to_str() @@ -165,8 +169,10 @@ fn generate_single( .stdout(Stdio::piped()) .stderr(Stdio::piped()) .args(&[ - "--from=markdown-raw_tex", - "--to=html", + "--from", + &config.from, + "--to", + &config.to, "--css", css_path .as_ref() @@ -183,6 +189,10 @@ fn generate_single( .context("Entity name is not valid UTF-8")?, ]); + for filter in &config.pandoc_filters { + command.args(&["--filter", filter]); + } + let command_str = format!("{:?}", command); debug!("Launching command: {}", command_str); @@ -190,6 +200,8 @@ fn generate_single( .output() .context("Failed to execute Pandoc command")?; + std::io::stderr().lock().write_all(&output.stderr)?; + ensure!( output.status.success(), CommandError { diff --git a/src/generator/pandoc.rs b/src/generator/pandoc.rs index 1753d34..035acab 100644 --- a/src/generator/pandoc.rs +++ b/src/generator/pandoc.rs @@ -1,14 +1,11 @@ use super::config::Config; -use crate::types::Entity; +use crate::types::*; use pandoc_types::definition::{Attr, Block, Inline, Meta, MetaValue, Pandoc}; use std::collections::BTreeMap; -pub(crate) fn into_pandoc( - entity: Entity, - config: &Config, -) -> (Pandoc, BTreeMap) { +pub(crate) fn into_pandoc(entity: Entity, config: &Config) -> (Pandoc, BTreeMap) { let mut meta = Meta::null(); let title = vec![Inline::Code(Attr::null(), entity.name.clone())]; @@ -57,7 +54,7 @@ pub(crate) fn into_pandoc( content.push(Block::Header( 2, Attr::null(), - vec![Inline::Str(String::from(section_name))], + vec![Inline::Str(section_name.0.clone())], )); content.push(members_list); @@ -71,7 +68,7 @@ pub(crate) fn into_pandoc( content.push(Block::Header( 2, Attr::null(), - vec![Inline::Str(section_name.clone())], + vec![Inline::Str(section_name.0.clone())], )); content.push(members_list); @@ -79,7 +76,7 @@ pub(crate) fn into_pandoc( embedded_documentation.push(Block::Header( 2, Attr::null(), - vec![Inline::Str(section_name + " Documentation")], + vec![Inline::Str(section_name.0 + " Documentation")], )); for (_id, child) in children { @@ -112,7 +109,7 @@ fn str_block(content: String) -> Block { Block::Plain(vec![Inline::Str(content)]) } -fn entity_link(id: &str, name: String) -> Inline { +fn entity_link(id: &EntityId, name: String) -> Inline { use pandoc_types::definition::Target; use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS}; @@ -135,7 +132,7 @@ fn entity_link(id: &str, name: String) -> Inline { vec![Inline::Code(Attr::null(), name)], Target( once("./") - .chain(utf8_percent_encode(id, FRAGMENT)) + .chain(utf8_percent_encode(&id.0, FRAGMENT)) .collect(), String::new(), ), @@ -147,7 +144,7 @@ fn raw_markdown(text: String) -> Block { Block::RawBlock(Format(String::from("markdown")), text) } -fn member_list<'a>(members: impl IntoIterator) -> Option { +fn member_list<'a>(members: impl IntoIterator) -> Option { let definitions: Vec<(Vec, Vec>)> = members .into_iter() .map(|(id, entity)| { -- cgit v1.2.3