diff options
author | Canop <cano.petrole@gmail.com> | 2020-11-05 17:09:18 +0100 |
---|---|---|
committer | Canop <cano.petrole@gmail.com> | 2020-11-05 17:09:18 +0100 |
commit | e47ce676b0fe285f782d3a5282b8658b9b3568e5 (patch) | |
tree | 01a4be68305fd1ab85844fe1c5b8d105fb035a3d /src/display/crop.rs | |
parent | cf6eab4a8ad7f1cd8881a9f4203bb8aaddb20e28 (diff) |
preview now supports opening zero length "files"v1.0.5
(for exemple the ones of /proc)
Diffstat (limited to 'src/display/crop.rs')
-rw-r--r-- | src/display/crop.rs | 66 |
1 files changed, 53 insertions, 13 deletions
diff --git a/src/display/crop.rs b/src/display/crop.rs index 38a1ad0..c060739 100644 --- a/src/display/crop.rs +++ b/src/display/crop.rs @@ -1,22 +1,62 @@ use { + super::TAB_REPLACEMENT, unicode_width::UnicodeWidthChar, }; -// return the counts in bytes and columns of the longest substring -// fitting the given number of columns -pub fn count_fitting(s: &str, columns_max: usize) -> (usize, usize) { - let mut count_bytes = 0; - let mut str_width = 0; - for (idx, c) in s.char_indices() { - let char_width = UnicodeWidthChar::width(c).unwrap_or(0); - let next_str_width = str_width + char_width; - if next_str_width > columns_max { - break; + +#[derive(Debug, Clone, Copy)] +pub struct StrFit { + bytes_count: usize, + cols_count: usize, + has_tab: bool, +} + +impl StrFit { + pub fn from(s: &str, cols_max: usize) -> Self { + let mut bytes_count = 0; + let mut cols_count = 0; + let mut has_tab = false; + for (idx, c) in s.char_indices() { + let char_width = if '\t' == c { + has_tab = true; + TAB_REPLACEMENT.len() + } else { + UnicodeWidthChar::width(c).unwrap_or(0) + }; + let next_str_width = cols_count + char_width; + if next_str_width > cols_max { + break; + } + cols_count = next_str_width; + bytes_count = idx + c.len_utf8(); } - str_width = next_str_width; - count_bytes = idx + c.len_utf8(); + Self { + bytes_count, + cols_count, + has_tab, + } + } +} + +/// return the counts in bytes and columns of the longest substring +/// fitting the given number of columns +pub fn count_fitting(s: &str, cols_max: usize) -> (usize, usize) { + let fit = StrFit::from(s, cols_max); + (fit.bytes_count, fit.cols_count) +} + +/// return both the longest fitting string and the number of cols +/// it takes on screen. +/// We don't build a string around the whole str, which could be costly +/// if it's very big +pub fn make_string(s: &str, cols_max: usize) -> (String, usize) { + let fit = StrFit::from(s, cols_max); + if fit.has_tab { + let string = (&s[0..fit.bytes_count]).replace('\t', TAB_REPLACEMENT); + (string, fit.cols_count) + } else { + (s[0..fit.bytes_count].to_string(), fit.cols_count) } - (count_bytes, str_width) } #[cfg(test)] |