summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorzxlzy <31438870+zxlzy@users.noreply.github.com>2020-09-01 15:47:22 +0800
committerGitHub <noreply@github.com>2020-09-01 09:47:22 +0200
commitf4009e4c6e4198499b8642b8d6cba0b40f66da20 (patch)
treeb669137b81caa1fb21b8e4b0d2431815b040e698 /src
parent44c69f13550142bc2470d2c813d08dabd954bbbc (diff)
fix(formatting): panic when slice str (#177)
* fix panic when slice str * copy code from diskonaut * typo fix
Diffstat (limited to 'src')
-rw-r--r--src/display/components/table.rs34
1 files changed, 30 insertions, 4 deletions
diff --git a/src/display/components/table.rs b/src/display/components/table.rs
index 059b5ed..f61886c 100644
--- a/src/display/components/table.rs
+++ b/src/display/components/table.rs
@@ -1,4 +1,6 @@
use ::std::collections::{BTreeMap, HashMap};
+use ::std::iter::FromIterator;
+use ::unicode_width::UnicodeWidthChar;
use ::tui::backend::Backend;
use ::tui::layout::Rect;
@@ -51,11 +53,35 @@ pub struct Table<'a> {
breakpoints: BTreeMap<u16, ColumnData>,
}
+fn truncate_iter_to_unicode_width<Input, Collect>(iter: Input, width: usize) -> Collect
+where
+ Input: Iterator<Item = char>,
+ Collect: FromIterator<char>,
+{
+ let mut chunk_width = 0;
+ iter.take_while(|ch| {
+ chunk_width += ch.width().unwrap_or(0);
+ chunk_width <= width
+ })
+ .collect()
+}
+
fn truncate_middle(row: &str, max_length: u16) -> String {
- if row.len() as u16 > max_length {
- let first_slice = &row[0..(max_length as usize / 2) - 2];
- let second_slice = &row[(row.len() - (max_length / 2) as usize + 2)..row.len()];
- format!("{}[..]{}", first_slice, second_slice)
+ if max_length < 6 {
+ truncate_iter_to_unicode_width(row.chars(), max_length as usize)
+ } else if row.len() as u16 > max_length {
+ let split_point = (max_length as usize / 2) - 2;
+ let first_slice = truncate_iter_to_unicode_width::<_, String>(row.chars(), split_point);
+ let second_slice =
+ truncate_iter_to_unicode_width::<_, Vec<_>>(row.chars().rev(), split_point)
+ .into_iter()
+ .rev()
+ .collect::<String>();
+ if max_length % 2 == 0 {
+ format!("{}[..]{}", first_slice, second_slice)
+ } else {
+ format!("{}[..]{}", first_slice, second_slice)
+ }
} else {
row.to_string()
}