truth-table 0.2.0

Generate a truth table from a formula
use std::io::Write;

use ansi_term::Colour::{Green, Red};

use crate::{args, eval, lexer};

pub fn write_as_table(
    w: &mut impl Write,
    args: args::Args,
    color: bool,
) -> Result<(), Box<dyn std::error::Error>> {
    //let args = args::Args::new()?;
    let tokens = lexer::Tokens::from_text(&args.text);
    let equation = eval::Equation::from_tokens(&tokens);
    let combinations = equation.eval_all();
    // Write the first header row
    for ident in &equation.idents {
        write!(w, "{} ", ident)?;
    }
    // Display the requested equation
    write!(w, "| {}", tokens)?;
    writeln!(w)?;
    // Display all possible combinations
    for (values, result) in combinations {
        for (_, boolean) in values {
            if color {
                write!(
                    w,
                    "{} ",
                    if boolean {
                        Green.paint("1")
                    } else {
                        Red.paint("0")
                    }
                )?;
            } else {
                write!(w, "{} ", if boolean { "1" } else { "0" })?;
            }
        }
        if color {
            writeln!(
                w,
                "| {}",
                if result {
                    Green.paint("1")
                } else {
                    Red.paint("0")
                }
            )?;
        } else {
            writeln!(w, "| {}", if result { "1" } else { "0" })?;
        }
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn format() {
        let table = "\
a b | a ∧ ¬b
0 0 | 0
0 1 | 0
1 0 | 1
1 1 | 0
";
        let mut buf = Vec::new();
        write_as_table(
            &mut buf,
            args::Args {
                text: "a and not b".to_owned(),
            },
            false,
        )
        .unwrap();
        assert_eq!(std::str::from_utf8(&buf).unwrap(), table);
    }

    #[test]
    fn format2() {
        let table = "\
x y | ¬x ∨ y
0 0 | 1
0 1 | 1
1 0 | 0
1 1 | 1
";
        let mut buf = Vec::new();
        write_as_table(
            &mut buf,
            args::Args {
                text: "not x or y".to_owned(),
            },
            false,
        )
        .unwrap();
        assert_eq!(std::str::from_utf8(&buf).unwrap(), table);
    }
}