fn plot_graph()

in resctl-demo/src/graph.rs [125:219]


fn plot_graph(
    data: &str,
    size: (usize, usize),
    span_len: u64,
    g1: &PlotSpec,
    g2: Option<&PlotSpec>,
    g3: Option<&PlotSpec>,
) -> Result<StyledString> {
    let bin = match find_bin("gnuplot", Option::<&str>::None) {
        Some(v) => v,
        None => bail!("Failed to find \"gnuplot\""),
    };

    let mut cmd = format!(
        "set term dumb size {xsize}, {ysize};\n\
                       set xrange [{xmin}:0];\n\
                       set xtics out nomirror;\n\
                       set ytics out nomirror;\n\
                       set key left top;\n",
        xsize = size.0,
        ysize = size.1,
        xmin = -(span_len as i64),
    );
    let (ymin, ymax) = ((g1.min)(), (g1.max)());
    if ymax > ymin {
        cmd += &format!("set yrange [{ymin}:{ymax}];\n", ymin = ymin, ymax = ymax,);
    } else if ymin >= 0.0 {
        cmd += "set yrange [0:];\n";
    } else {
        cmd += "set yrange [:];\n";
    }
    if let Some(g2) = &g2 {
        cmd += "set y2tics out;\n";
        let (ymin, ymax) = ((g2.min)(), (g2.max)());
        if ymax > ymin {
            cmd += &format!("set y2range [{ymin}:{ymax}];\n", ymin = ymin, ymax = ymax);
        } else if ymin >= 0.0 {
            cmd += "set y2range [0:];\n";
        } else {
            cmd += "set y2range [:];\n";
        }
    }
    cmd += &format!(
        "plot \"{data}\" using 1:{idx} with lines axis x1y1 title \"{title}\"",
        data = data,
        idx = 2,
        title = (g1.title)()
    );

    let y2 = if let Some(_) = &g3 { "y1" } else { "y2" };

    if let Some(g2) = &g2 {
        cmd += &format!(
            ", \"{data}\" using 1:{idx} with lines axis x1{y2} title \"{title}\"\n",
            data = data,
            idx = 3,
            y2 = y2,
            title = (g2.title)()
        );
    }
    if let Some(g3) = &g3 {
        let title = (g3.title)();
        if title.len() > 0 {
            cmd += &format!(
                ", \"{data}\" using 1:{idx} with lines axis x1{y2} title \"{title}\"\n",
                data = data,
                idx = 4,
                y2 = y2,
                title = title,
            );
        }
    }

    let output = Command::new(&bin).arg("-e").arg(cmd).output()?;
    if !output.status.success() {
        bail!("gnuplot failed with {:?}", &output);
    }

    let mut graph = StyledString::new();
    for line in String::from_utf8(output.stdout).unwrap().lines() {
        if line.trim().len() == 0 {
            continue;
        }
        for c in line.chars() {
            match c {
                '*' => graph.append_styled("*", *COLOR_GRAPH_1),
                '#' => graph.append_styled("+", *COLOR_GRAPH_2),
                '$' => graph.append_styled(".", *COLOR_GRAPH_3),
                v => graph.append_plain(&format!("{}", v)),
            }
        }
        graph.append_plain("\n");
    }
    Ok(graph)
}