rustviz_lib/svg_frontend/
code_panel.rs

1extern crate handlebars;
2
3use crate::data::{ExternalEvent, LINE_SPACE};
4use handlebars::Handlebars;
5use std::{cmp::max, collections::BTreeMap};
6use std::fs::File;
7use std::io;
8
9pub fn render_code_panel(
10    annotated_lines: io::Lines<io::BufReader<File>>,
11    lines: io::Lines<io::BufReader<File>>,
12    max_x_space: &mut i64,
13    event_line_map: &BTreeMap<usize, Vec<ExternalEvent>>,
14) -> (String, i32) {
15    /* Template creation */
16    let mut handlebars = Handlebars::new();
17    // We want to preserve the inputs `as is`, and want to make no changes based on html escape.
18    handlebars.register_escape_fn(handlebars::no_escape);
19    let line_template =
20        "        <text class=\"code\" x=\"{{X_VAL}}\" y=\"{{Y_VAL}}\"> {{LINE}} </text>\n";
21    // register the template. The template string will be verified and compiled.
22    assert!(handlebars
23        .register_template_string("code_line_template", line_template)
24        .is_ok());
25    
26    // figure out that max length
27    for line in lines {
28        if let Ok(line_string) = line {
29            *max_x_space = max(line_string.len() as i64, *max_x_space);
30        }
31    }
32    
33    /* Render the code segment of the svg to a String */
34    let x = 20;
35    let mut y = 90;
36    let mut output = String::from("    <g id=\"code\">\n");
37    let mut line_of_code = 1;
38    for line in annotated_lines {
39        if let Ok(line_string) = line {
40            let mut data = BTreeMap::new();
41            data.insert("X_VAL".to_string(), x.to_string());
42            data.insert("Y_VAL".to_string(), y.to_string());
43            /* automatically add line numbers to code */
44            let fmt_line = format!(
45                "<tspan fill=\"#AAA\">{}  </tspan>{}",
46                line_of_code, line_string
47            );
48            data.insert("LINE".to_string(), fmt_line);
49            output.push_str(&handlebars.render("code_line_template", &data).unwrap());
50            // change line spacing
51            y = y + LINE_SPACE;
52        }
53        let mut extra_line_num = 0;
54        match event_line_map.get(&(line_of_code as usize)) {
55            Some(event_vec) => extra_line_num = event_vec.len(),
56            None => (),
57        }
58        /* add empty lines for arrows */
59        while extra_line_num > 1 {
60            let mut data = BTreeMap::new();
61            data.insert("X_VAL".to_string(), x.to_string());
62            data.insert("Y_VAL".to_string(), y.to_string());
63            /* automatically add line numbers to code */
64            line_of_code = line_of_code + 1;
65            let empty_line = format!("<tspan fill=\"#AAA\">{}</tspan>", line_of_code);
66            data.insert("LINE".to_string(), empty_line);
67            output.push_str(&handlebars.render("code_line_template", &data).unwrap());
68            y = y + LINE_SPACE;
69            extra_line_num -= 1;
70        }
71        line_of_code = line_of_code + 1;
72    }
73    output.push_str("    </g>\n");
74    (output, line_of_code)
75}