1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
//! Visual styling for the output

use std::fmt::Display;

use comfy_table::{
    modifiers::UTF8_ROUND_CORNERS,
    presets::UTF8_FULL,
    Attribute,
    Cell,
    ContentArrangement,
    Table,
};
use miette::{Diagnostic, GraphicalReportHandler, Severity};
use mit_lint::Lints;
use thiserror::Error;

use crate::mit::Authors;

/// Print a advice using our error handler tool
///
/// # Panics
///
/// Panics on a format failure. This should be impossible
pub fn success(success: &str, tip: &str) {
    let mut out = String::new();
    GraphicalReportHandler::default()
        .render_report(
            &mut out,
            &Success {
                success: success.to_string(),
                help: Some(tip),
            },
        )
        .unwrap();
    println!("{}", out);
}

#[derive(Error, Debug)]
#[error("{success}")]
struct Success<'a> {
    success: String,
    help: Option<&'a str>,
}

impl Diagnostic for Success<'_> {
    fn severity(&self) -> Option<Severity> {
        Some(Severity::Advice)
    }

    fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
        self.help
            .map(|x| Box::new(x.to_string()) as Box<dyn Display>)
    }
}

#[derive(Error, Debug)]
#[error("{warning}")]
struct Warning<'a> {
    warning: String,
    help: Option<&'a str>,
}

impl Diagnostic for Warning<'_> {
    fn severity(&self) -> Option<Severity> {
        Some(Severity::Warning)
    }

    fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
        self.help
            .map(|x| Box::new(x.to_string()) as Box<dyn Display>)
    }
}

/// Print a warning using our error handler tool
///
/// # Panics
///
/// Panics on a format failure. This should be impossible
pub fn warning(warning: &str, tip: Option<&str>) {
    let mut out = String::new();
    GraphicalReportHandler::default()
        .render_report(
            &mut out,
            &Warning {
                warning: warning.to_string(),
                help: tip,
            },
        )
        .unwrap();
    eprintln!("{}", out);
}

/// Print entirely undecorated to stdout
pub fn to_be_piped(output: &str) {
    println!("{}", output);
}

/// Print a table of lints
pub fn lint_table(list: &Lints, enabled: &Lints) {
    let mut table = Table::new();
    table
        .load_preset(UTF8_FULL)
        .apply_modifier(UTF8_ROUND_CORNERS)
        .set_content_arrangement(ContentArrangement::Dynamic)
        .set_header(vec!["Lint", "Status"]);

    let rows: Table = list.clone().into_iter().fold(table, |mut table, lint| {
        table.add_row(vec![
            lint.name(),
            if enabled.clone().into_iter().any(|x| x == lint) {
                "enabled"
            } else {
                "disabled"
            },
        ]);
        table
    });

    println!("{}", rows);
}

/// Print a table of authors
#[must_use]
pub fn author_table(authors: &Authors<'_>) -> String {
    let mut table = Table::new();
    table
        .load_preset(UTF8_FULL)
        .apply_modifier(UTF8_ROUND_CORNERS)
        .set_content_arrangement(ContentArrangement::Dynamic)
        .set_header(vec!["Initial", "Name", "Email", "Signing Key"]);

    let rows: Table = authors
        .clone()
        .into_iter()
        .fold(table, |mut table, (initial, author)| {
            table.add_row(vec![
                Cell::new(initial),
                Cell::new(author.name()),
                Cell::new(author.email()),
                author.signingkey().map_or_else(
                    || Cell::new("None".to_string()).add_attributes(vec![Attribute::Italic]),
                    Cell::new,
                ),
            ]);
            table
        });

    format!("{}", rows)
}