| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- use std::io::{self, Write};
- use term_grid as tg;
- use crate::fs::filter::FileFilter;
- use crate::fs::File;
- use crate::output::file_name::{Classify, Options as FileStyle};
- use crate::output::file_name::{EmbedHyperlinks, ShowIcons};
- use crate::theme::Theme;
- #[derive(PartialEq, Eq, Debug, Copy, Clone)]
- pub struct Options {
- pub across: 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 theme: &'a Theme,
- pub file_style: &'a FileStyle,
- pub opts: &'a Options,
- pub console_width: usize,
- pub filter: &'a FileFilter,
- }
- impl<'a> Render<'a> {
- pub fn render<W: Write>(mut self, w: &mut W) -> io::Result<()> {
- let mut grid = tg::Grid::new(tg::GridOptions {
- direction: self.opts.direction(),
- filling: tg::Filling::Spaces(2),
- });
- grid.reserve(self.files.len());
- self.filter.sort_files(&mut self.files);
- for file in &self.files {
- let filename = self.file_style.for_file(file, self.theme);
- // Calculate classification width
- let classification_width =
- if let Classify::AddFileIndicators = filename.options.classify {
- match filename.classify_char(file) {
- Some(s) => s.len(),
- None => 0,
- }
- } else {
- 0
- };
- let space_filename_offset = if file.name.contains(' ') || file.name.contains('\'') {
- 2
- } else {
- 0
- };
- let contents = filename.paint();
- #[rustfmt::skip]
- let width = match (
- filename.options.embed_hyperlinks,
- filename.options.show_icons,
- ) {
- ( EmbedHyperlinks::On, ShowIcons::Always(spacing) | ShowIcons::Automatic(spacing) )
- => filename.bare_width() + classification_width + 1 + (spacing as usize) + space_filename_offset,
- ( EmbedHyperlinks::On, ShowIcons::Never )
- => filename.bare_width() + classification_width + space_filename_offset,
- ( EmbedHyperlinks::Off, ShowIcons::Always(spacing) | ShowIcons::Automatic(spacing) )
- => filename.bare_width() + 1 + (spacing as usize) + space_filename_offset,
- ( EmbedHyperlinks::Off, _ )
- => *contents.width(),
- };
- grid.add(tg::Cell {
- contents: contents.strings().to_string(),
- // with hyperlink escape sequences,
- // the actual *contents.width() is larger than actually needed, so we take only the filename
- width,
- });
- }
- if let Some(display) = grid.fit_into_width(self.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 {
- let name_cell = self.file_style.for_file(file, self.theme).paint();
- writeln!(w, "{}", name_cell.strings())?;
- }
- Ok(())
- }
- }
- }
|