fix(message): use unicode char count for text width
Some checks failed
Publish Docker Images / coverage-and-sonar (push) Failing after 6m54s

This commit is contained in:
2026-03-09 22:57:35 +01:00
parent 8a61d6b2dd
commit bd1f194547
4 changed files with 30 additions and 9 deletions

View File

@@ -61,6 +61,15 @@ impl CommitType {
Self::Revert => "revert", Self::Revert => "revert",
} }
} }
/// Returns the length in characters
///
/// `is_empty()` is intentionally absent: `CommitType` is
/// guaranteed non-empty, so the concept does not apply.
#[allow(clippy::len_without_is_empty)]
pub fn len(&self) -> usize {
self.as_str().chars().count()
}
} }
impl std::fmt::Display for CommitType { impl std::fmt::Display for CommitType {

View File

@@ -39,7 +39,7 @@ impl Description {
/// non-empty by its constructor, so the concept does not apply. /// non-empty by its constructor, so the concept does not apply.
#[allow(clippy::len_without_is_empty)] #[allow(clippy::len_without_is_empty)]
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.0.len() self.0.chars().count()
} }
} }

View File

@@ -70,13 +70,10 @@ impl ConventionalCommit {
/// - Without scope: `len(type) + 2 + len(description)` /// - Without scope: `len(type) + 2 + len(description)`
/// (the 2 accounts for colon and space: ": ") /// (the 2 accounts for colon and space: ": ")
pub fn first_line_len(&self) -> usize { pub fn first_line_len(&self) -> usize {
if self.scope.is_empty() { self.commit_type.len()
// type: description + self.scope.header_segment_len()
self.commit_type.as_str().len() + 2 + self.description.len() + 2 // ": "
} else { + self.description.len()
// type(scope): description
self.commit_type.as_str().len() + self.scope.as_str().len() + 4 + self.description.len()
}
} }
/// Format the complete commit messsage /// Format the complete commit messsage

View File

@@ -25,8 +25,13 @@ impl Scope {
}); });
} }
match lazy_regex::regex_find!(r"[^-a-zA-Z0-9_/]", &value) { match lazy_regex::regex_find!(r"[^-a-zA-Z0-9_/]", &value) {
Some(val) => Err(ScopeError::InvalidCharacter(val.chars().next().unwrap())),
None => Ok(Self(value)), None => Ok(Self(value)),
Some(val) => val
.chars()
.next()
.map(ScopeError::InvalidCharacter)
.map(Err)
.unwrap_or_else(|| unreachable!("regex match is always non-empty")),
} }
} }
@@ -44,6 +49,16 @@ impl Scope {
pub fn as_str(&self) -> &str { pub fn as_str(&self) -> &str {
self.0.as_str() self.0.as_str()
} }
/// Returns itself as a formatted header segment
pub fn header_segment(&self) -> String {
format!("({self})")
}
/// Returns the visible length of the header segment
pub fn header_segment_len(&self) -> usize {
self.header_segment().chars().count()
}
} }
impl std::fmt::Display for Scope { impl std::fmt::Display for Scope {