1use dialoguer::{Confirm, Editor};
2use std::fmt::{self, Display, Formatter};
3
4#[derive(Copy, Clone)]
5pub struct CommitType {
6 pub text: &'static str,
7 description: &'static str,
8}
9
10impl CommitType {
11 pub fn default_commit_types() -> [CommitType; 8] {
12 [
13 CommitType {
14 text: "feat",
15 description: "A new feature"
16 },
17 CommitType {
18 text: "fix",
19 description: "A bug fix"
20 },
21 CommitType {
22 text: "docs",
23 description: "Documentation only changes"
24 },
25 CommitType {
26 text: "style",
27 description: "Changes that do not affect the meaning of the code (white-space, fomatting, missing semi-colons, etc)"
28 },
29 CommitType {
30 text: "refactor",
31 description: "A code change that neither fixes a bug or adds a feature"
32 },
33 CommitType {
34 text: "perf",
35 description: "A code change that improves performance"
36 },
37 CommitType {
38 text: "test",
39 description: "Added, modified or removed tests"
40 },
41 CommitType {
42 text: "chore",
43 description: "Change to the build process, auxiliary tools, libraries or CI"
44 },
45 ]
46 }
47}
48
49impl Display for CommitType {
50 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
51 write!(f, "{:9}: {}", self.text, self.description)
52 }
53}
54
55pub fn get_optional_commit_body_and_footer() -> Option<String> {
56 let should_open_editor = Confirm::new()
57 .with_prompt("Do you want to write a long description?")
58 .default(false)
59 .show_default(false)
60 .interact()
61 .unwrap();
62 if should_open_editor {
63 return Editor::new().edit("").unwrap();
64 }
65 None
66}
67
68pub fn put_together_first_line(commit_type: CommitType, scope: String, subject: String) -> String {
69 let mut first_line = commit_type.text.to_string();
70 if scope.is_empty() {
71 first_line.push_str(": ");
72 } else {
73 first_line.push_str(&format!("({}): ", scope));
74 }
75 first_line.push_str(&subject.to_lowercase());
76
77 first_line
78}
79
80pub fn put_together_commit_message(
81 first_line: String,
82 optional_body_and_footer: Option<String>,
83) -> String {
84 let mut format_commit_message = first_line;
85 if let Some(text) = optional_body_and_footer {
86 format_commit_message.push_str(&format!("\n\n{}", text));
87 }
88 format_commit_message
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn test_commit_to_string() {
97 let fix = CommitType {
98 text: "fix",
99 description: "just for test",
100 };
101 assert_eq!(fix.to_string(), "fix : just for test");
102 }
103
104 #[test]
105 fn test_composite_commit() {
106 let bug = CommitType {
107 text: "bug",
108 description: "a test",
109 };
110 let scope = String::from("view");
111 let subject = String::from("test example");
112 let other: Option<String> = None;
113 let first_line = put_together_first_line(bug, scope, subject);
114 let result = put_together_commit_message(first_line, other);
115 assert_eq!(result, String::from("bug(view): test example"))
116 }
117}