summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPascal H <hpwxf@haveneer.com>2023-06-23 15:38:40 +0200
committerGitHub <noreply@github.com>2023-06-23 09:38:40 -0400
commitff5fd061f4dfc9b00f80aada705de192a5524ed5 (patch)
tree271d6b159cefd2b7eaf77b0d4c669e40ee28b489
parent24c29c37d3808d502eb28b376b48d2bd2932f2c3 (diff)
Fix alignment when author name contains unicode accent modifiers (#1456)
-rw-r--r--src/handlers/blame.rs53
1 files changed, 44 insertions, 9 deletions
diff --git a/src/handlers/blame.rs b/src/handlers/blame.rs
index 4aeded0f..7578a5c4 100644
--- a/src/handlers/blame.rs
+++ b/src/handlers/blame.rs
@@ -2,6 +2,7 @@ use chrono::{DateTime, FixedOffset};
use lazy_static::lazy_static;
use regex::Regex;
use std::borrow::Cow;
+use unicode_width::UnicodeWidthStr;
use crate::ansi::measure_text_width;
use crate::color;
@@ -281,9 +282,12 @@ pub fn format_blame_metadata(
_ => unreachable!("Unexpected `git blame` input"),
};
if let Some(field) = field {
+ // Unicode modifier should not be counted as character to allow a consistent padding
+ let unicode_modifier_width =
+ field.as_ref().chars().count() - UnicodeWidthStr::width(field.as_ref());
s.push_str(&format::pad(
&field,
- width,
+ width + unicode_modifier_width,
alignment_spec,
placeholder.precision,
))
@@ -411,10 +415,7 @@ mod tests {
#[test]
fn test_format_blame_metadata_with_default_timestamp_output_format() {
- let format_data = format::FormatStringPlaceholderData {
- placeholder: Some(Placeholder::Str("timestamp")),
- ..Default::default()
- };
+ let format_data = make_format_data_with_placeholder("timestamp");
let blame = make_blame_line_with_time("1996-12-19T16:39:57-08:00");
let config = integration_test_utils::make_config_from_args(&[]);
let regex = Regex::new(r"^\d+ years ago$").unwrap();
@@ -424,10 +425,7 @@ mod tests {
#[test]
fn test_format_blame_metadata_with_custom_timestamp_output_format() {
- let format_data = format::FormatStringPlaceholderData {
- placeholder: Some(Placeholder::Str("timestamp")),
- ..Default::default()
- };
+ let format_data = make_format_data_with_placeholder("timestamp");
let blame = make_blame_line_with_time("1996-12-19T16:39:57-08:00");
let config = integration_test_utils::make_config_from_args(&[
"--blame-timestamp-output-format=%Y-%m-%d %H:%M",
@@ -437,6 +435,26 @@ mod tests {
}
#[test]
+ fn test_format_blame_metadata_with_accent_in_name() {
+ let config = integration_test_utils::make_config_from_args(&[]);
+
+ let count_trailing_spaces = |s: String| s.chars().rev().filter(|&c| c == ' ').count();
+
+ let format_data1 = make_format_data_with_placeholder("author");
+ let blame1 = make_blame_line_with_author("E\u{301}dith Piaf");
+ let result1 = format_blame_metadata(&[format_data1], &blame1, &config);
+
+ let format_data2 = make_format_data_with_placeholder("author");
+ let blame2 = make_blame_line_with_author("Edith Piaf");
+ let result2 = format_blame_metadata(&[format_data2], &blame2, &config);
+
+ assert_eq!(
+ count_trailing_spaces(result1),
+ count_trailing_spaces(result2)
+ );
+ }
+
+ #[test]
fn test_color_assignment() {
let mut writer = Cursor::new(vec![0; 512]);
let config = integration_test_utils::make_config_from_args(&[
@@ -536,4 +554,21 @@ mod tests {
code: "",
}
}
+
+ fn make_format_data_with_placeholder(placeholder: &str) -> format::FormatStringPlaceholderData {
+ format::FormatStringPlaceholderData {
+ placeholder: Some(Placeholder::Str(placeholder)),
+ ..Default::default()
+ }
+ }
+
+ fn make_blame_line_with_author(author: &str) -> BlameLine {
+ BlameLine {
+ commit: "",
+ author,
+ time: chrono::DateTime::default(),
+ line_number: 0,
+ code: "",
+ }
+ }
}