Skip to content

Commit 4cd4fc5

Browse files
committed
feat(utils): implement format_commit function with unit tests
1 parent c5b8b2c commit 4cd4fc5

4 files changed

Lines changed: 146 additions & 2 deletions

File tree

src/i18n/messages/en.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use phf::phf_map;
22

33
pub static MESSAGES: phf::Map<&'static str, &'static str> = phf_map! {
4-
54
// Configuration file I/O
65
"config_loaded" => "Configuration loaded successfully",
76
"config_not_found" => "Configuration file not found",
@@ -24,4 +23,13 @@ pub static MESSAGES: phf::Map<&'static str, &'static str> = phf_map! {
2423
// Keypress
2524
"wait_for_key" => "Press any key to continue...",
2625
"press_to_exit" => "Press any key to exit...",
26+
27+
// Commit categories
28+
"commit_category_features" => "Features",
29+
"commit_category_bug_fixes" => "Bug Fixes",
30+
"commit_category_docs" => "Documentation",
31+
"commit_category_style" => "Optimized Style",
32+
"commit_category_refactor" => "Refactored",
33+
"commit_category_test" => "Test Cases",
34+
"commit_category_chores" => "Chores",
2735
};

src/i18n/messages/zh.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use phf::phf_map;
22

33
pub static MESSAGES: phf::Map<&'static str, &'static str> = phf_map! {
4-
54
// Configuration file I/O
65
"config_loaded" => "配置加载成功",
76
"config_not_found" => "未找到配置文件",
@@ -24,4 +23,13 @@ pub static MESSAGES: phf::Map<&'static str, &'static str> = phf_map! {
2423
// Keypress
2524
"wait_for_key" => "按任意键继续...",
2625
"press_to_exit" => "按任意键退出...",
26+
27+
// Commit categories
28+
"commit_category_features" => "功能开发",
29+
"commit_category_bug_fixes" => "BUG修复",
30+
"commit_category_docs" => "完善文档",
31+
"commit_category_style" => "优化样式",
32+
"commit_category_refactor" => "代码重构",
33+
"commit_category_test" => "测试用例",
34+
"commit_category_chores" => "其他优化",
2735
};

src/utils/format_commit.rs

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
use crate::i18n::t;
2+
3+
/// Commit type and its category
4+
pub struct CommitInfo {
5+
pub type_name: String,
6+
pub category: String,
7+
pub message: String,
8+
}
9+
10+
/// Only used for testing
11+
#[cfg(test)]
12+
const TEST_CATEGORIES: &[(&str, &str)] = &[
13+
("feat", "Features"),
14+
("fix", "Bug Fixes"),
15+
("docs", "Documentation"),
16+
("style", "Styles"),
17+
("refactor", "Code Refactoring"),
18+
("test", "Tests"),
19+
("chore", "Chores"),
20+
];
21+
22+
#[cfg(test)]
23+
fn get_commit_type_and_category(type_name: &str) -> (&str, String) {
24+
let (t, c) = TEST_CATEGORIES
25+
.iter()
26+
.find(|(t, _)| *t == type_name)
27+
.map(|&(t, c)| (t, c))
28+
.unwrap_or(("chore", "Chores"));
29+
(t, c.to_string())
30+
}
31+
32+
#[cfg(not(test))]
33+
fn get_commit_type_and_category(type_name: &str) -> (&str, String) {
34+
match type_name {
35+
"feat" => ("feat", t("commit_category_features").to_string()),
36+
"fix" => ("fix", t("commit_category_bug_fixes").to_string()),
37+
"docs" => ("docs", t("commit_category_docs").to_string()),
38+
"style" => ("style", t("commit_category_style").to_string()),
39+
"refactor" => ("refactor", t("commit_category_refactor").to_string()),
40+
"test" => ("test", t("commit_category_test").to_string()),
41+
_ => ("chore", t("commit_category_chores").to_string()),
42+
}
43+
}
44+
45+
/// Format commit message
46+
pub fn format_commit(commit: &str) -> CommitInfo {
47+
let commit_type = if let Some(index) = commit.find(':') {
48+
&commit[..index]
49+
} else {
50+
"chore"
51+
};
52+
53+
let base_type = if let Some(scope_start) = commit_type.find('(') {
54+
&commit_type[..scope_start]
55+
} else {
56+
commit_type
57+
};
58+
59+
let (type_name, category) = get_commit_type_and_category(base_type);
60+
61+
// Extract commit message
62+
let mut message = commit.trim().to_string();
63+
64+
// Get commit message (remove type prefix)
65+
if let Some(index) = commit.find(':') {
66+
message = commit[index + 1..].trim().to_string();
67+
68+
// 提取 scope
69+
let action = &commit[..index];
70+
if let Some(scope) = action.find('(').and_then(|start| {
71+
action
72+
.find(')')
73+
.map(|end| action[start + 1..end].to_string())
74+
}) {
75+
message = format!("{}: {}", scope, message);
76+
}
77+
}
78+
79+
CommitInfo {
80+
type_name: type_name.to_string(),
81+
category,
82+
message,
83+
}
84+
}
85+
86+
#[cfg(test)]
87+
mod tests {
88+
use super::*;
89+
90+
#[test]
91+
fn test_format_basic_commit() {
92+
let commit = "feat: add new feature";
93+
let info = format_commit(commit);
94+
assert_eq!(info.type_name, "feat");
95+
assert_eq!(info.category, "Features");
96+
assert_eq!(info.message, "add new feature");
97+
}
98+
99+
#[test]
100+
fn test_format_commit_with_scope() {
101+
let commit = "feat(component): add button component";
102+
let info = format_commit(commit);
103+
assert_eq!(info.type_name, "feat");
104+
assert_eq!(info.category, "Features");
105+
assert_eq!(info.message, "component: add button component");
106+
}
107+
108+
#[test]
109+
fn test_commit_types() {
110+
let test_cases = [
111+
("feat: new", "feat", "Features"),
112+
("fix: bug", "fix", "Bug Fixes"),
113+
("docs: update", "docs", "Documentation"),
114+
("style: format", "style", "Styles"),
115+
("refactor: code", "refactor", "Code Refactoring"),
116+
("test: add", "test", "Tests"),
117+
("chore: deps", "chore", "Chores"),
118+
("unknown: something", "chore", "Chores"),
119+
];
120+
121+
for (commit, expected_type, expected_category) in test_cases {
122+
let info = format_commit(commit);
123+
assert_eq!(info.type_name, expected_type);
124+
assert_eq!(info.category, expected_category);
125+
}
126+
}
127+
}

src/utils/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
pub mod format_commit;
12
pub mod keypress;

0 commit comments

Comments
 (0)