summaryrefslogtreecommitdiffstats
path: root/src/output/grid.rs
blob: b560b463c0b43a6ec2f41bceb541b5deacf1bdf3 (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
use std::io::{Write, Result as IOResult};

use term_grid as tg;

use crate::fs::File;
use crate::output::cell::DisplayWidth;
use crate::output::file_name::FileStyle;
use crate::output::icons::painted_icon;
use crate::style::Colours;


#[derive(PartialEq, Debug, Copy, Clone)]
pub struct Options {
    pub across: bool,
    pub console_width: usize,
    pub icons: bool,
}

impl Options {
    pub fn direction(&self) -> tg::Direction {
        if self.across { tg::Direction::LeftToRight }
                  else { tg::Direction::TopToBottom }
    }
}


pub struct Render<'a> {
    pub files: Vec<File<'a>>,
    pub colours: &'a Colours,
    pub style: &'a FileStyle,
    pub opts: &'a Options,
}

impl<'a> Render<'a> {
    pub fn render<W: Write>(&self, w: &mut W) -> IOResult<()> {
        let mut grid = tg::Grid::new(tg::GridOptions {
            direction:  self.opts.direction(),
            filling:    tg::Filling::Spaces(2),
        });

        grid.reserve(self.files.len());

        for file in &self.files {
            let icon = if self.opts.icons { Some(painted_icon(file, self.style)) }
                                     else { None };

            let filename = self.style.for_file(file, self.colours).paint();

            let width = if self.opts.icons { DisplayWidth::from(2) + filename.width() }
                                      else { filename.width() };

            grid.add(tg::Cell {
                contents:  format!("{}{}", &icon.unwrap_or_default(), filename.strings()),
                width:     *width,
            });
        }

        if let Some(display) = grid.fit_into_width(self.opts.console_width) {
            write!(w, "{}", display)
        }
        else {
            // File names too long for a grid - drop down to just listing them!
            // This isn’t *quite* the same as the lines view, which also
            // displays full link paths.
            for file in &self.files {
                if self.opts.icons {
                    write!(w, "{}", painted_icon(file, self.style))?;
                }

                let name_cell = self.style.for_file(file, self.colours).paint();
                writeln!(w, "{}", name_cell.strings())?;
            }

            Ok(())
        }
    }
}