agda_tree/command/
build.rs1use html_parser::{Dom, Element};
2use std::fs::{self, create_dir_all, File};
3use std::io::{self, Read, Write};
4use std::path::{Path, PathBuf};
5
6pub fn execute(working_dir: &PathBuf, output_dir: &PathBuf) -> io::Result<()> {
7 let agda_generate_trees = fs::read_dir(working_dir.join("html"))?
8 .filter_map(Result::ok)
9 .filter_map(|f| {
10 if let Ok(ft) = f.file_type() {
11 if ft.is_file() && f.path().to_str()?.ends_with(".tree") {
12 return Some(f.path());
13 }
14 }
15 None
16 })
17 .collect::<Vec<PathBuf>>();
18
19 create_dir_all(output_dir)?;
20
21 for tree_path in agda_generate_trees {
22 let new_content = postprocess(working_dir, tree_path.clone())?;
23
24 let created_path = output_dir
25 .join(tree_path.file_stem().unwrap())
26 .with_extension("tree");
27 println!("Producing {:?}", created_path);
28 let mut out_file = File::create(created_path)?;
29 out_file.write_all(new_content.as_bytes())?;
30 }
31
32 Ok(())
33}
34
35fn postprocess(working_dir: &PathBuf, tree_path: PathBuf) -> io::Result<String> {
36 println!("Processing file: {:?}", tree_path);
37
38 let mut file = File::open(tree_path.clone())?;
39 let mut content = String::new();
40 file.read_to_string(&mut content)?;
41
42 let mut new_content = String::new();
43 let mut html = String::new();
44
45 let mut recording = false;
46 let mut line: usize = 0;
47 let mut last_col_end: usize = 0;
48
49
50 new_content.push_str("\\xmlns:html{http://www.w3.org/1999/xhtml}");
51
52 for cur_line in content.lines() {
53 if cur_line.contains("<pre class=\"Agda\">") {
54 new_content.push_str("\\<html:pre>[class]{Agda}{");
55 recording = true;
56 } else if cur_line.contains("</pre>") {
57 recording = false;
58 let dom = Dom::parse(html.as_str()).unwrap();
59 html.clear();
60
61 for node in dom.children {
62 let elem = node.element().unwrap();
63
64 if line_of_symbol(elem) > line {
65 for _ in 0..(line_of_symbol(elem) - line) {
66 new_content.push('\n');
67 }
68 last_col_end = 1;
69 }
70 if col_of_symbol(elem) > last_col_end {
71 for _ in 0..col_of_symbol(elem) - last_col_end {
72 new_content.push(' ');
73 }
74 }
75 last_col_end = end_col_of_symbol(elem);
76 line = line_of_symbol(elem);
77
78 new_content.push_str(symbol2forest(working_dir, elem).as_str());
79 }
80
81 new_content.push_str("}\n");
82 } else if recording {
83 html.push_str(cur_line);
84 html.push('\n');
85 } else {
86 new_content.push_str(cur_line);
87 new_content.push('\n');
88 }
89 }
90
91 Ok(new_content)
92}
93
94fn line_of_symbol(elem: &Element) -> usize {
95 elem.source_span.end_line
96}
97fn col_of_symbol(elem: &Element) -> usize {
98 elem.source_span.start_column
99}
100fn end_col_of_symbol(elem: &Element) -> usize {
101 elem.source_span.end_column
102}
103
104fn symbol2forest(working_dir: &PathBuf, elem: &Element) -> String {
105 let mut s = format!("\\<html:{}>", elem.name);
106
107 if elem.id.is_some() {
108 s.push_str(format!("[id]{{{}}}", elem.id.clone().unwrap().as_str()).as_str());
109 }
110 if !elem.classes.is_empty() {
111 s.push_str(format!("[class]{{{}}}", elem.classes[0]).as_str());
112 }
113 for (k, v) in &elem.attributes {
114 let value = v.clone().unwrap();
115 let value = if k == "href" {
116 let split = value.split_terminator('#').collect::<Vec<&str>>();
121 let a_link = split[0];
122 let path = Path::new(a_link);
123 if working_dir.join(path).with_extension("lagda.tree").exists() {
124 let mut s = path.with_extension("xml").to_str().unwrap().to_owned();
125 s.push('#');
126 if split.len() == 2 {
127 let id_part = split[1];
128 s.push_str(id_part);
129 }
130 s
131 } else {
132 value
133 }
134 } else {
135 value
136 };
137 s.push_str(format!("[{}]{{{}}}", k, value).as_str());
138 }
139 if elem.children.is_empty() {
140 s.push_str("{}");
141 } else {
142 let childtext = elem.children[0].text().unwrap();
143 let childtext = if childtext.contains("'") {
145 childtext.replace("'", "'")
146 } else {
147 childtext.to_owned()
148 };
149 if childtext.contains('(')
150 || childtext.contains(')')
151 || childtext.contains('{')
152 || childtext.contains('}')
153 {
154 s.push_str(format!("{{\\startverb{}\\stopverb}}", childtext).as_str());
155 } else {
156 s.push_str(format!("{{{}}}", childtext).as_str());
157 }
158 }
159
160 s
161}