Skip to content

Commit 895c013

Browse files
author
Stephan Dilly
committed
fixed author column width (closes #148)
1 parent 9756056 commit 895c013

File tree

2 files changed

+78
-13
lines changed

2 files changed

+78
-13
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111
- show file sizes and delta on binary files diff ([#141](https://github.com/extrawurst/gitui/issues/141))
1212

1313
### Changed
14-
- Use terminal blue as default selection background ([#129](https://github.com/extrawurst/gitui/issues/129))
14+
- use terminal blue as default selection background ([#129](https://github.com/extrawurst/gitui/issues/129))
15+
- author column in revlog is now fixed width for better alignment ([#148](https://github.com/extrawurst/gitui/issues/148))
1516

1617
### Fixed
1718
- clearer help headers ([#131](https://github.com/extrawurst/gitui/issues/131))

src/components/commitlist.rs

+76-12
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use tui::{
2222
widgets::{Block, Borders, Paragraph, Text},
2323
Frame,
2424
};
25+
use unicode_width::UnicodeWidthStr;
2526

2627
const ELEMENTS_PER_LINE: usize = 10;
2728

@@ -182,6 +183,7 @@ impl CommitList {
182183
txt: &mut Vec<Text<'a>>,
183184
tags: Option<String>,
184185
theme: &Theme,
186+
width: usize,
185187
) {
186188
txt.reserve(ELEMENTS_PER_LINE);
187189

@@ -205,9 +207,13 @@ impl CommitList {
205207

206208
txt.push(splitter.clone());
207209

210+
let author_width =
211+
(width.saturating_sub(19) / 3).max(3).min(20);
212+
let author = string_width_align(&e.author, author_width);
213+
208214
// commit author
209215
txt.push(Text::Styled(
210-
Cow::from(e.author.as_str()),
216+
author.into(),
211217
theme.commit_author(selected),
212218
));
213219

@@ -233,7 +239,7 @@ impl CommitList {
233239
txt.push(Text::Raw(Cow::from("\n")));
234240
}
235241

236-
fn get_text(&self, height: usize) -> Vec<Text> {
242+
fn get_text(&self, height: usize, width: usize) -> Vec<Text> {
237243
let selection = self.relative_selection();
238244

239245
let mut txt = Vec::with_capacity(height * ELEMENTS_PER_LINE);
@@ -259,6 +265,7 @@ impl CommitList {
259265
&mut txt,
260266
tags,
261267
&self.theme,
268+
width,
262269
);
263270
}
264271

@@ -277,10 +284,11 @@ impl DrawableComponent for CommitList {
277284
f: &mut Frame<B>,
278285
area: Rect,
279286
) -> Result<()> {
280-
self.current_size.set((
287+
let current_size = (
281288
area.width.saturating_sub(2),
282289
area.height.saturating_sub(2),
283-
));
290+
);
291+
self.current_size.set(current_size);
284292

285293
let height_in_lines = self.current_size.get().1 as usize;
286294
let selection = self.relative_selection();
@@ -303,15 +311,21 @@ impl DrawableComponent for CommitList {
303311
);
304312

305313
f.render_widget(
306-
Paragraph::new(self.get_text(height_in_lines).iter())
307-
.block(
308-
Block::default()
309-
.borders(Borders::ALL)
310-
.title(title.as_str())
311-
.border_style(self.theme.block(true))
312-
.title_style(self.theme.title(true)),
314+
Paragraph::new(
315+
self.get_text(
316+
height_in_lines,
317+
current_size.0 as usize,
313318
)
314-
.alignment(Alignment::Left),
319+
.iter(),
320+
)
321+
.block(
322+
Block::default()
323+
.borders(Borders::ALL)
324+
.title(title.as_str())
325+
.border_style(self.theme.block(true))
326+
.title_style(self.theme.title(true)),
327+
)
328+
.alignment(Alignment::Left),
315329
area,
316330
);
317331

@@ -363,3 +377,53 @@ impl Component for CommitList {
363377
CommandBlocking::PassingOn
364378
}
365379
}
380+
381+
#[inline]
382+
fn string_width_align(s: &str, width: usize) -> String {
383+
static POSTFIX: &str = "..";
384+
385+
let len = UnicodeWidthStr::width(s);
386+
let width_wo_postfix = width.saturating_sub(POSTFIX.len());
387+
388+
if (len >= width_wo_postfix && len <= width)
389+
|| (len <= width_wo_postfix)
390+
{
391+
format!("{:w$}", s, w = width)
392+
} else {
393+
let mut s = s.to_string();
394+
s.truncate(find_truncate_point(&s, width_wo_postfix));
395+
format!("{}{}", s, POSTFIX)
396+
}
397+
}
398+
399+
#[inline]
400+
fn find_truncate_point(s: &str, chars: usize) -> usize {
401+
s.chars().take(chars).map(char::len_utf8).sum()
402+
}
403+
404+
#[cfg(test)]
405+
mod tests {
406+
use super::*;
407+
408+
#[test]
409+
fn test_string_width_align() {
410+
assert_eq!(string_width_align("123", 3), "123");
411+
assert_eq!(string_width_align("123", 2), "..");
412+
assert_eq!(string_width_align("123", 3), "123");
413+
assert_eq!(string_width_align("12345", 6), "12345 ");
414+
assert_eq!(string_width_align("1234556", 4), "12..");
415+
}
416+
417+
#[test]
418+
fn test_string_width_align_unicode() {
419+
assert_eq!(string_width_align("äste", 3), "ä..");
420+
assert_eq!(
421+
string_width_align("wüsten äste", 10),
422+
"wüsten ä.."
423+
);
424+
assert_eq!(
425+
string_width_align("Jon Grythe Stødle", 19),
426+
"Jon Grythe Stødle "
427+
);
428+
}
429+
}

0 commit comments

Comments
 (0)