From 895c013d102306f91b1065fcb5af8ab6e9c4b2d7 Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Thu, 25 Jun 2020 10:27:07 +0200 Subject: [PATCH] fixed author column width (closes #148) --- CHANGELOG.md | 3 +- src/components/commitlist.rs | 88 +++++++++++++++++++++++++++++++----- 2 files changed, 78 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 389a0dd5..e218d77d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - show file sizes and delta on binary files diff ([#141](https://github.com/extrawurst/gitui/issues/141)) ### Changed -- Use terminal blue as default selection background ([#129](https://github.com/extrawurst/gitui/issues/129)) +- use terminal blue as default selection background ([#129](https://github.com/extrawurst/gitui/issues/129)) +- author column in revlog is now fixed width for better alignment ([#148](https://github.com/extrawurst/gitui/issues/148)) ### Fixed - clearer help headers ([#131](https://github.com/extrawurst/gitui/issues/131)) diff --git a/src/components/commitlist.rs b/src/components/commitlist.rs index a47a0198..93b2d56d 100644 --- a/src/components/commitlist.rs +++ b/src/components/commitlist.rs @@ -22,6 +22,7 @@ use tui::{ widgets::{Block, Borders, Paragraph, Text}, Frame, }; +use unicode_width::UnicodeWidthStr; const ELEMENTS_PER_LINE: usize = 10; @@ -182,6 +183,7 @@ impl CommitList { txt: &mut Vec>, tags: Option, theme: &Theme, + width: usize, ) { txt.reserve(ELEMENTS_PER_LINE); @@ -205,9 +207,13 @@ impl CommitList { txt.push(splitter.clone()); + let author_width = + (width.saturating_sub(19) / 3).max(3).min(20); + let author = string_width_align(&e.author, author_width); + // commit author txt.push(Text::Styled( - Cow::from(e.author.as_str()), + author.into(), theme.commit_author(selected), )); @@ -233,7 +239,7 @@ impl CommitList { txt.push(Text::Raw(Cow::from("\n"))); } - fn get_text(&self, height: usize) -> Vec { + fn get_text(&self, height: usize, width: usize) -> Vec { let selection = self.relative_selection(); let mut txt = Vec::with_capacity(height * ELEMENTS_PER_LINE); @@ -259,6 +265,7 @@ impl CommitList { &mut txt, tags, &self.theme, + width, ); } @@ -277,10 +284,11 @@ impl DrawableComponent for CommitList { f: &mut Frame, area: Rect, ) -> Result<()> { - self.current_size.set(( + let current_size = ( area.width.saturating_sub(2), area.height.saturating_sub(2), - )); + ); + self.current_size.set(current_size); let height_in_lines = self.current_size.get().1 as usize; let selection = self.relative_selection(); @@ -303,15 +311,21 @@ impl DrawableComponent for CommitList { ); f.render_widget( - Paragraph::new(self.get_text(height_in_lines).iter()) - .block( - Block::default() - .borders(Borders::ALL) - .title(title.as_str()) - .border_style(self.theme.block(true)) - .title_style(self.theme.title(true)), + Paragraph::new( + self.get_text( + height_in_lines, + current_size.0 as usize, ) - .alignment(Alignment::Left), + .iter(), + ) + .block( + Block::default() + .borders(Borders::ALL) + .title(title.as_str()) + .border_style(self.theme.block(true)) + .title_style(self.theme.title(true)), + ) + .alignment(Alignment::Left), area, ); @@ -363,3 +377,53 @@ impl Component for CommitList { CommandBlocking::PassingOn } } + +#[inline] +fn string_width_align(s: &str, width: usize) -> String { + static POSTFIX: &str = ".."; + + let len = UnicodeWidthStr::width(s); + let width_wo_postfix = width.saturating_sub(POSTFIX.len()); + + if (len >= width_wo_postfix && len <= width) + || (len <= width_wo_postfix) + { + format!("{:w$}", s, w = width) + } else { + let mut s = s.to_string(); + s.truncate(find_truncate_point(&s, width_wo_postfix)); + format!("{}{}", s, POSTFIX) + } +} + +#[inline] +fn find_truncate_point(s: &str, chars: usize) -> usize { + s.chars().take(chars).map(char::len_utf8).sum() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_string_width_align() { + assert_eq!(string_width_align("123", 3), "123"); + assert_eq!(string_width_align("123", 2), ".."); + assert_eq!(string_width_align("123", 3), "123"); + assert_eq!(string_width_align("12345", 6), "12345 "); + assert_eq!(string_width_align("1234556", 4), "12.."); + } + + #[test] + fn test_string_width_align_unicode() { + assert_eq!(string_width_align("äste", 3), "ä.."); + assert_eq!( + string_width_align("wüsten äste", 10), + "wüsten ä.." + ); + assert_eq!( + string_width_align("Jon Grythe Stødle", 19), + "Jon Grythe Stødle " + ); + } +}