From a53c268c54615dbbbb08195ab88a197bc84b21bc Mon Sep 17 00:00:00 2001 From: Benjamin Sago Date: Mon, 1 May 2017 14:11:16 +0100 Subject: [PATCH] Measure, rather than calculating, cell widths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit exa deals with cells and widths a lot: the items in a grid need to be aligned according to their *contents’* widths, rather than the length of their strings, which often included ANSI escape characters. As an optimisation, it used to calculate this separately based on the filename, and dealing with any extra characters (such as the classify ones) in that function too. Recently, though, file names have become a lot more complicated. Classification added zero to one extra characters, and now with escaped control characters in file names, it’s not so easy to calculate the display width of a filename. This commit removes the function that calculated the width, in favour of building the output string (it’s going to be displayed anyway) and just getting the width of what it displays instead. --- src/output/cell.rs | 20 +++++--------------- src/output/details.rs | 11 +++++++---- src/output/grid.rs | 5 +++-- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/output/cell.rs b/src/output/cell.rs index b446996..547e839 100644 --- a/src/output/cell.rs +++ b/src/output/cell.rs @@ -5,8 +5,6 @@ use std::ops::{Add, Deref, DerefMut}; use ansi_term::{Style, ANSIString, ANSIStrings}; use unicode_width::UnicodeWidthStr; -use fs::File; - /// An individual cell that holds text in a table, used in the details and /// lines views to store ANSI-terminal-formatted data before it is printed. @@ -161,6 +159,11 @@ impl TextCellContents { pub fn strings(&self) -> ANSIStrings { ANSIStrings(&self.0) } + + pub fn width(&self) -> DisplayWidth { + let foo = self.0.iter().map(|anstr| anstr.chars().count()).sum(); + DisplayWidth(foo) + } } @@ -180,19 +183,6 @@ impl TextCellContents { #[derive(PartialEq, Debug, Clone, Copy, Default)] pub struct DisplayWidth(usize); -impl DisplayWidth { - pub fn from_file(file: &File, classify: bool) -> DisplayWidth { - let name_width = *DisplayWidth::from(&*file.name); - if classify { - if file.is_executable_file() || file.is_directory() || - file.is_pipe() || file.is_link() || file.is_socket() { - return DisplayWidth(name_width + 1); - } - } - DisplayWidth(name_width) - } -} - impl<'a> From<&'a str> for DisplayWidth { fn from(input: &'a str) -> DisplayWidth { DisplayWidth(UnicodeWidthStr::width(input)) diff --git a/src/output/details.rs b/src/output/details.rs index d91d2f4..a9abac7 100644 --- a/src/output/details.rs +++ b/src/output/details.rs @@ -306,7 +306,9 @@ impl Details { for (index, egg) in file_eggs.into_iter().enumerate() { let mut files = Vec::new(); let mut errors = egg.errors; - let mut width = DisplayWidth::from_file(&egg.file, self.classify); + + let filename = filename(&egg.file, &self.colours, true, self.classify); + let mut width = filename.width(); if egg.file.dir.is_none() { if let Some(parent) = egg.file.path.parent() { @@ -315,7 +317,7 @@ impl Details { } let name = TextCell { - contents: filename(&egg.file, &self.colours, true, self.classify), + contents: filename, width: width, }; @@ -456,7 +458,8 @@ impl<'a, U: Users+Groups+'a> Table<'a, U> { } pub fn filename_cell(&self, file: File, links: bool) -> TextCell { - let mut width = DisplayWidth::from_file(&file, self.opts.classify); + let filename = filename(&file, &self.opts.colours, links, self.opts.classify); + let mut width = filename.width(); if file.dir.is_none() { if let Some(parent) = file.path.parent() { @@ -465,7 +468,7 @@ impl<'a, U: Users+Groups+'a> Table<'a, U> { } TextCell { - contents: filename(&file, &self.opts.colours, links, self.opts.classify), + contents: filename, width: width, } } diff --git a/src/output/grid.rs b/src/output/grid.rs index 3eec694..5456d58 100644 --- a/src/output/grid.rs +++ b/src/output/grid.rs @@ -29,8 +29,9 @@ impl Grid { grid.reserve(files.len()); for file in files.iter() { - let mut width = DisplayWidth::from_file(file, self.classify); + let filename = filename(file, &self.colours, false, self.classify); + let mut width = filename.width(); if file.dir.is_none() { if let Some(parent) = file.path.parent() { width = width + 1 + DisplayWidth::from(parent.to_string_lossy().as_ref()); @@ -38,7 +39,7 @@ impl Grid { } grid.add(grid::Cell { - contents: filename(file, &self.colours, false, self.classify).strings().to_string(), + contents: filename.strings().to_string(), width: *width, }); }