use regex::Regex; /// Format commit message with conventional commit format pub fn format_conventional_commit( commit_type: &str, scope: Option<&str>, description: &str, body: Option<&str>, footer: Option<&str>, breaking: bool, ) -> String { let mut message = String::new(); message.push_str(commit_type); if let Some(s) = scope { message.push_str(&format!("({})", s)); } if breaking { message.push('!'); } message.push_str(&format!(": {}", description)); if let Some(b) = body { message.push_str(&format!("\n\n{}", b)); } if let Some(f) = footer { message.push_str(&format!("\n\n{}", f)); } message } /// Format commit with @commitlint format pub fn format_commitlint_commit( commit_type: &str, scope: Option<&str>, subject: &str, body: Option<&str>, footer: Option<&str>, references: Option<&[&str]>, ) -> String { let mut message = String::new(); message.push_str(commit_type); if let Some(s) = scope { message.push_str(&format!("({})", s)); } message.push_str(&format!(": {}", subject)); if let Some(refs) = references { for reference in refs { message.push_str(&format!(" #{}", reference)); } } if let Some(b) = body { message.push_str(&format!("\n\n{}", b)); } if let Some(f) = footer { message.push_str(&format!("\n\n{}", f)); } message } /// Wrap text at specified width pub fn wrap_text(text: &str, width: usize) -> String { textwrap::fill(text, width) } /// Clean commit message (remove comments, extra whitespace) pub fn clean_message(message: &str) -> String { let comment_regex = Regex::new(r"^#.*$").unwrap(); message .lines() .filter(|line| !comment_regex.is_match(line.trim())) .collect::>() .join("\n") .trim() .to_string() } #[cfg(test)] mod tests { use super::*; #[test] fn test_format_conventional_commit() { let msg = format_conventional_commit( "feat", Some("auth"), "add login functionality", Some("This adds OAuth2 login support."), Some("Closes #123"), false, ); assert!(msg.contains("feat(auth): add login functionality")); assert!(msg.contains("This adds OAuth2 login support.")); assert!(msg.contains("Closes #123")); } #[test] fn test_format_conventional_commit_breaking() { let msg = format_conventional_commit( "feat", None, "change API response format", None, Some("BREAKING CHANGE: response format changed"), true, ); assert!(msg.starts_with("feat!: change API response format")); } }