summaryrefslogtreecommitdiffstats
path: root/src/draw.rs
blob: 7fe54e1daf79ba4fb113884ee486c89303142b87 (plain)
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
use std::io::Write;

use ansi_term::Style;
use box_drawing;
use console::strip_ansi_codes;
use unicode_segmentation::UnicodeSegmentation;

/// Write text to stream, surrounded by a box, leaving the cursor just
/// beyond the bottom right corner.
pub fn write_boxed(
    writer: &mut Write,
    text: &str,
    _line_width: usize, // ignored
    line_style: Style,
    heavy: bool,
) -> std::io::Result<()> {
    let up_left = if heavy {
        box_drawing::heavy::UP_LEFT
    } else {
        box_drawing::light::UP_LEFT
    };
    let box_width = strip_ansi_codes(text).graphemes(true).count() + 1;
    write_boxed_partial(writer, text, box_width, line_style, heavy)?;
    write!(writer, "{}", line_style.paint(up_left))?;
    Ok(())
}

/// Write text to stream, surrounded by a box, and extend a line from
/// the bottom right corner.
pub fn write_boxed_with_line(
    writer: &mut Write,
    text: &str,
    line_width: usize,
    line_style: Style,
    heavy: bool,
) -> std::io::Result<()> {
    let box_width = strip_ansi_codes(text).graphemes(true).count() + 1;
    write_boxed_with_horizontal_whisker(writer, text, box_width, line_style, heavy)?;
    write_horizontal_line(writer, line_width - box_width - 1, line_style, heavy)?;
    Ok(())
}

pub fn write_underlined(
    writer: &mut Write,
    text: &str,
    line_width: usize,
    line_style: Style,
    heavy: bool,
) -> std::io::Result<()> {
    writeln!(writer, "{}", text)?;
    write_horizontal_line(writer, line_width, line_style, heavy)?;
    Ok(())
}

fn write_horizontal_line(
    writer: &mut Write,
    line_width: usize,
    line_style: Style,
    heavy: bool,
) -> std::io::Result<()> {
    let horizontal = if heavy {
        box_drawing::heavy::HORIZONTAL
    } else {
        box_drawing::light::HORIZONTAL
    };
    write!(
        writer,
        "{}",
        line_style.paint(horizontal.repeat(line_width),)
    )
}

pub fn write_boxed_with_horizontal_whisker(
    writer: &mut Write,
    text: &str,
    box_width: usize,
    line_style: Style,
    heavy: bool,
) -> std::io::Result<()> {
    let up_horizontal = if heavy {
        box_drawing::heavy::UP_HORIZONTAL
    } else {
        box_drawing::light::UP_HORIZONTAL
    };
    write_boxed_partial(writer, text, box_width, line_style, heavy)?;
    write!(writer, "{}", line_style.paint(up_horizontal))?;
    Ok(())
}

fn write_boxed_partial(
    writer: &mut Write,
    text: &str,
    box_width: usize,
    line_style: Style,
    heavy: bool,
) -> std::io::Result<()> {
    let horizontal = if heavy {
        box_drawing::heavy::HORIZONTAL
    } else {
        box_drawing::light::HORIZONTAL
    };
    let down_left = if heavy {
        box_drawing::heavy::DOWN_LEFT
    } else {
        box_drawing::light::DOWN_LEFT
    };
    let vertical = if heavy {
        box_drawing::heavy::VERTICAL
    } else {
        box_drawing::light::VERTICAL
    };

    let horizontal_edge = horizontal.repeat(box_width);
    write!(
        writer,
        "{}{}\n{} {}\n{}",
        line_style.paint(&horizontal_edge),
        line_style.paint(down_left),
        text,
        line_style.paint(vertical),
        line_style.paint(&horizontal_edge),
    )
}