diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/generator/pandoc.rs | 64 | ||||
-rw-r--r-- | src/parser/clang/entities.rs | 61 | ||||
-rw-r--r-- | src/types.rs | 4 |
3 files changed, 72 insertions, 57 deletions
diff --git a/src/generator/pandoc.rs b/src/generator/pandoc.rs index 035acab..fe2e2f0 100644 --- a/src/generator/pandoc.rs +++ b/src/generator/pandoc.rs | |||
@@ -35,13 +35,7 @@ pub(crate) fn into_pandoc(entity: Entity, config: &Config) -> (Pandoc, BTreeMap< | |||
35 | 35 | ||
36 | let entity_kind = entity.kind; | 36 | let entity_kind = entity.kind; |
37 | for (children_kind, children) in entity.children { | 37 | for (children_kind, children) in entity.children { |
38 | if config | 38 | if is_inline(config, entity.language, &entity_kind, &children_kind) { |
39 | .inlines | ||
40 | .get(&entity.language) | ||
41 | .and_then(|lang_inlines| lang_inlines.get(&entity_kind)) | ||
42 | .map(|children_inlines| children_inlines.contains(&children_kind)) | ||
43 | == Some(true) | ||
44 | { | ||
45 | inline_children.insert(children_kind, children); | 39 | inline_children.insert(children_kind, children); |
46 | } else { | 40 | } else { |
47 | // By default, do not inline | 41 | // By default, do not inline |
@@ -50,7 +44,7 @@ pub(crate) fn into_pandoc(entity: Entity, config: &Config) -> (Pandoc, BTreeMap< | |||
50 | } | 44 | } |
51 | 45 | ||
52 | for (section_name, children) in &separate_children { | 46 | for (section_name, children) in &separate_children { |
53 | if let Some(members_list) = member_list(children) { | 47 | if let Some(members_list) = member_list(children, LinkType::External) { |
54 | content.push(Block::Header( | 48 | content.push(Block::Header( |
55 | 2, | 49 | 2, |
56 | Attr::null(), | 50 | Attr::null(), |
@@ -61,10 +55,10 @@ pub(crate) fn into_pandoc(entity: Entity, config: &Config) -> (Pandoc, BTreeMap< | |||
61 | } | 55 | } |
62 | } | 56 | } |
63 | 57 | ||
64 | let mut embedded_documentation = Vec::new(); | 58 | let mut inline_documentation = Vec::new(); |
65 | 59 | ||
66 | for (section_name, children) in inline_children { | 60 | for (section_name, children) in inline_children { |
67 | if let Some(members_list) = member_list(&children) { | 61 | if let Some(members_list) = member_list(&children, LinkType::Anchor) { |
68 | content.push(Block::Header( | 62 | content.push(Block::Header( |
69 | 2, | 63 | 2, |
70 | Attr::null(), | 64 | Attr::null(), |
@@ -73,20 +67,20 @@ pub(crate) fn into_pandoc(entity: Entity, config: &Config) -> (Pandoc, BTreeMap< | |||
73 | 67 | ||
74 | content.push(members_list); | 68 | content.push(members_list); |
75 | 69 | ||
76 | embedded_documentation.push(Block::Header( | 70 | inline_documentation.push(Block::Header( |
77 | 2, | 71 | 2, |
78 | Attr::null(), | 72 | Attr::null(), |
79 | vec![Inline::Str(section_name.0 + " Documentation")], | 73 | vec![Inline::Str(section_name.0 + " Documentation")], |
80 | )); | 74 | )); |
81 | 75 | ||
82 | for (_id, child) in children { | 76 | for (id, child) in children { |
83 | embedded_documentation.push(Block::Header( | 77 | inline_documentation.push(Block::Header( |
84 | 3, | 78 | 3, |
85 | Attr::null(), | 79 | Attr(id.0, vec![], vec![]), |
86 | vec![Inline::Code(Attr::null(), child.name)], | 80 | vec![Inline::Code(Attr::null(), child.name)], |
87 | )); | 81 | )); |
88 | 82 | ||
89 | embedded_documentation.push(Block::Div( | 83 | inline_documentation.push(Block::Div( |
90 | Attr(String::new(), vec![String::from("doc")], vec![]), | 84 | Attr(String::new(), vec![String::from("doc")], vec![]), |
91 | vec![raw_markdown(child.documentation)], | 85 | vec![raw_markdown(child.documentation)], |
92 | )); | 86 | )); |
@@ -94,7 +88,7 @@ pub(crate) fn into_pandoc(entity: Entity, config: &Config) -> (Pandoc, BTreeMap< | |||
94 | } | 88 | } |
95 | } | 89 | } |
96 | 90 | ||
97 | content.append(&mut embedded_documentation); | 91 | content.append(&mut inline_documentation); |
98 | 92 | ||
99 | let leftovers = separate_children | 93 | let leftovers = separate_children |
100 | .into_iter() | 94 | .into_iter() |
@@ -105,11 +99,25 @@ pub(crate) fn into_pandoc(entity: Entity, config: &Config) -> (Pandoc, BTreeMap< | |||
105 | (Pandoc(meta, content), leftovers) | 99 | (Pandoc(meta, content), leftovers) |
106 | } | 100 | } |
107 | 101 | ||
102 | fn is_inline( | ||
103 | config: &Config, | ||
104 | language: Language, | ||
105 | parent_kind: &EntityKind, | ||
106 | children_kind: &ChildrenKind, | ||
107 | ) -> bool { | ||
108 | config | ||
109 | .inlines | ||
110 | .get(&language) | ||
111 | .and_then(|lang_inlines| lang_inlines.get(parent_kind)) | ||
112 | .map(|children_inlines| children_inlines.contains(children_kind)) | ||
113 | == Some(true) | ||
114 | } | ||
115 | |||
108 | fn str_block(content: String) -> Block { | 116 | fn str_block(content: String) -> Block { |
109 | Block::Plain(vec![Inline::Str(content)]) | 117 | Block::Plain(vec![Inline::Str(content)]) |
110 | } | 118 | } |
111 | 119 | ||
112 | fn entity_link(id: &EntityId, name: String) -> Inline { | 120 | fn entity_link(id: &EntityId, name: String, link_type: LinkType) -> Inline { |
113 | use pandoc_types::definition::Target; | 121 | use pandoc_types::definition::Target; |
114 | use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS}; | 122 | use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS}; |
115 | 123 | ||
@@ -131,9 +139,12 @@ fn entity_link(id: &EntityId, name: String) -> Inline { | |||
131 | Attr::null(), | 139 | Attr::null(), |
132 | vec![Inline::Code(Attr::null(), name)], | 140 | vec![Inline::Code(Attr::null(), name)], |
133 | Target( | 141 | Target( |
134 | once("./") | 142 | once(match link_type { |
135 | .chain(utf8_percent_encode(&id.0, FRAGMENT)) | 143 | LinkType::External => "./", |
136 | .collect(), | 144 | LinkType::Anchor => "#", |
145 | }) | ||
146 | .chain(utf8_percent_encode(&id.0, FRAGMENT)) | ||
147 | .collect(), | ||
137 | String::new(), | 148 | String::new(), |
138 | ), | 149 | ), |
139 | ) | 150 | ) |
@@ -144,12 +155,21 @@ fn raw_markdown(text: String) -> Block { | |||
144 | Block::RawBlock(Format(String::from("markdown")), text) | 155 | Block::RawBlock(Format(String::from("markdown")), text) |
145 | } | 156 | } |
146 | 157 | ||
147 | fn member_list<'a>(members: impl IntoIterator<Item = (&'a EntityId, &'a Entity)>) -> Option<Block> { | 158 | #[derive(Debug, Clone, Copy)] |
159 | enum LinkType { | ||
160 | Anchor, | ||
161 | External, | ||
162 | } | ||
163 | |||
164 | fn member_list<'a>( | ||
165 | members: impl IntoIterator<Item = (&'a EntityId, &'a Entity)>, | ||
166 | link_type: LinkType, | ||
167 | ) -> Option<Block> { | ||
148 | let definitions: Vec<(Vec<Inline>, Vec<Vec<Block>>)> = members | 168 | let definitions: Vec<(Vec<Inline>, Vec<Vec<Block>>)> = members |
149 | .into_iter() | 169 | .into_iter() |
150 | .map(|(id, entity)| { | 170 | .map(|(id, entity)| { |
151 | ( | 171 | ( |
152 | vec![entity_link(id, entity.name.clone())], | 172 | vec![entity_link(id, entity.name.clone(), link_type)], |
153 | vec![vec![str_block(entity.brief_description.clone())]], | 173 | vec![vec![str_block(entity.brief_description.clone())]], |
154 | ) | 174 | ) |
155 | }) | 175 | }) |
diff --git a/src/parser/clang/entities.rs b/src/parser/clang/entities.rs index 41fe061..cbc17b7 100644 --- a/src/parser/clang/entities.rs +++ b/src/parser/clang/entities.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use crate::types::*; | 1 | use crate::types::{self, *}; |
2 | 2 | ||
3 | use clang::{EntityKind, Usr}; | 3 | use clang::{EntityKind, Usr}; |
4 | use thiserror::Error; | 4 | use thiserror::Error; |
@@ -169,55 +169,48 @@ where | |||
169 | } | 169 | } |
170 | } | 170 | } |
171 | 171 | ||
172 | fn entity_id(usr: Usr) -> EntityId { | ||
173 | // This is a somewhat ugly workaround, because Pandoc parses markdown identifiers as alphanum | ||
174 | // or one of "-_:.", which means Pandoc can't parse libclang's USRs in title ids and related. | ||
175 | // | ||
176 | // <https://github.com/jgm/pandoc/blob/2.9/src/Text/Pandoc/Readers/Markdown.hs#L581> | ||
177 | EntityId(usr.0.replace("@", "::").replace("#", ".").replace("$", "-")) | ||
178 | } | ||
179 | |||
180 | fn append_children<T: ClangEntity>( | ||
181 | acc: &mut types::Children, | ||
182 | to_insert: BTreeMap<Usr, Described<T>>, | ||
183 | ) { | ||
184 | for (usr, child) in to_insert { | ||
185 | acc.entry(ChildrenKind(String::from( | ||
186 | child.entity.kind().to_str_plural(), | ||
187 | ))) | ||
188 | .or_default() | ||
189 | .insert(entity_id(usr), child.into()); | ||
190 | } | ||
191 | } | ||
192 | |||
172 | impl<T: ClangEntity> From<Described<T>> for Entity { | 193 | impl<T: ClangEntity> From<Described<T>> for Entity { |
173 | fn from(entity: Described<T>) -> Self { | 194 | fn from(entity: Described<T>) -> Self { |
174 | let mut children: BTreeMap<ChildrenKind, BTreeMap<EntityId, Entity>> = BTreeMap::new(); | 195 | let mut children: types::Children = BTreeMap::new(); |
175 | 196 | ||
176 | let kind = EntityKind(String::from(entity.entity.kind().to_str_singular())); | 197 | let kind = EntityKind(String::from(entity.entity.kind().to_str_singular())); |
177 | let clang_children = entity.entity.into_children(); | 198 | let clang_children = entity.entity.into_children(); |
178 | 199 | ||
179 | if let Some(namespaces) = clang_children.namespaces { | 200 | if let Some(namespaces) = clang_children.namespaces { |
180 | for (usr, namespace) in namespaces { | 201 | append_children(&mut children, namespaces); |
181 | children | ||
182 | .entry(ChildrenKind(String::from( | ||
183 | namespace.entity.kind().to_str_plural(), | ||
184 | ))) | ||
185 | .or_default() | ||
186 | .insert(EntityId(usr.0), namespace.into()); | ||
187 | } | ||
188 | } | 202 | } |
189 | 203 | ||
190 | if let Some(variables) = clang_children.variables { | 204 | if let Some(variables) = clang_children.variables { |
191 | for (usr, variable) in variables { | 205 | append_children(&mut children, variables); |
192 | children | ||
193 | .entry(ChildrenKind(String::from( | ||
194 | variable.entity.kind().to_str_plural(), | ||
195 | ))) | ||
196 | .or_default() | ||
197 | .insert(EntityId(usr.0), variable.into()); | ||
198 | } | ||
199 | } | 206 | } |
200 | 207 | ||
201 | if let Some(structs) = clang_children.structs { | 208 | if let Some(structs) = clang_children.structs { |
202 | for (usr, r#struct) in structs { | 209 | append_children(&mut children, structs); |
203 | children | ||
204 | .entry(ChildrenKind(String::from( | ||
205 | r#struct.entity.kind().to_str_plural(), | ||
206 | ))) | ||
207 | .or_default() | ||
208 | .insert(EntityId(usr.0), r#struct.into()); | ||
209 | } | ||
210 | } | 210 | } |
211 | 211 | ||
212 | if let Some(functions) = clang_children.functions { | 212 | if let Some(functions) = clang_children.functions { |
213 | for (usr, function) in functions { | 213 | append_children(&mut children, functions); |
214 | children | ||
215 | .entry(ChildrenKind(String::from( | ||
216 | function.entity.kind().to_str_plural(), | ||
217 | ))) | ||
218 | .or_default() | ||
219 | .insert(EntityId(usr.0), function.into()); | ||
220 | } | ||
221 | } | 214 | } |
222 | 215 | ||
223 | Entity { | 216 | Entity { |
diff --git a/src/types.rs b/src/types.rs index f378f8b..d192ab5 100644 --- a/src/types.rs +++ b/src/types.rs | |||
@@ -18,9 +18,11 @@ pub struct Entity { | |||
18 | pub kind: EntityKind, | 18 | pub kind: EntityKind, |
19 | pub brief_description: String, | 19 | pub brief_description: String, |
20 | pub documentation: String, | 20 | pub documentation: String, |
21 | pub children: BTreeMap<ChildrenKind, BTreeMap<EntityId, Entity>>, | 21 | pub children: Children, |
22 | } | 22 | } |
23 | 23 | ||
24 | pub type Children = BTreeMap<ChildrenKind, BTreeMap<EntityId, Entity>>; | ||
25 | |||
24 | // TODO: use newtype for entity kind, entity ID | 26 | // TODO: use newtype for entity kind, entity ID |
25 | 27 | ||
26 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] | 28 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] |