cxx2flow 0.6.2

Convert your C/C++ code to control flow chart
Documentation
use cxx2flow::{
    cli::Args,
    display::{d2::D2, dot::Dot, tikz::Tikz},
    dump,
    error::Error,
};
use std::{
    io::{Read, Write},
    process::{self, Stdio},
};
use tree_sitter::Parser;

use itertools::Itertools;

use cxx2flow::generate;
use miette::IntoDiagnostic;

fn main() -> miette::Result<()> {
    miette::set_panic_hook();
    let args = <Args as clap::Parser>::parse();
    let mut content: Vec<u8> = Vec::new();
    match args.input {
        Some(ref file_name) => {
            content = std::fs::read(file_name).into_diagnostic()?;
        }
        None => {
            std::io::stdin()
                .read_to_end(&mut content)
                .into_diagnostic()?;
        }
    };
    let content = if args.cpp {
        let mut cpp = process::Command::new("cpp")
            .stdin(Stdio::piped())
            .stdout(Stdio::piped())
            .spawn()
            .into_diagnostic()?;
        if let Some(mut child_stdin) = cpp.stdin.take() {
            child_stdin.write_all(&content).into_diagnostic()?;
        }
        cpp.wait_with_output().into_diagnostic()?.stdout
    } else {
        content
    };
    let content = Itertools::intersperse(
        String::from_utf8(content)
            .unwrap()
            .lines()
            .filter(|x| !x.starts_with('#')),
        "\n",
    )
    .collect::<String>()
    .into_bytes();
    if args.dump_ast {
        let mut parser = Parser::new();
        let language = tree_sitter_cpp::language();
        parser
            .set_language(&language)
            .map_err(|_| Error::TreesitterParseFailed)?;
        let tree = parser
            .parse(&content, None)
            .ok_or(Error::TreesitterParseFailed)?;
        dump::dump_node(&tree.root_node(), &content);
        return Ok(());
    }
    let backend = if args.tikz {
        Tikz::new().into()
    } else if args.d2 {
        D2::new().into()
    } else {
        Dot::new(args.curly).into()
    };
    let res = generate(
        &content,
        &args.input.unwrap_or_else(|| "stdin".to_owned()),
        Some(args.function),
        backend,
    )?;
    if let Some(output) = args.output {
        std::fs::write(output, res).into_diagnostic()?;
    } else {
        print!("{}", res);
    }
    Ok(())
}