1use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5use std::fmt::Write;
6use textwrap;
7
8#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone)]
10pub struct GeneratedMessage {
11 pub emoji: Option<String>,
13 pub title: String,
15 pub message: String,
17 #[serde(default)]
19 pub completion_message: Option<String>,
20}
21
22impl GeneratedMessage {
23 pub(crate) fn subject(&self) -> String {
24 let title = self.title_without_repeated_emoji();
25
26 match self
27 .emoji
28 .as_deref()
29 .map(str::trim)
30 .filter(|emoji| !emoji.is_empty())
31 {
32 Some(emoji) => format!("{emoji} {title}"),
33 None => title.to_string(),
34 }
35 }
36
37 pub(crate) fn title_without_repeated_emoji(&self) -> &str {
38 let mut title = self.title.trim_start();
39
40 let Some(emoji) = self
41 .emoji
42 .as_deref()
43 .map(str::trim)
44 .filter(|emoji| !emoji.is_empty())
45 else {
46 return title;
47 };
48
49 while let Some(rest) = title.strip_prefix(emoji) {
50 title = rest.trim_start();
51 }
52
53 title
54 }
55}
56
57#[must_use]
59pub fn format_commit_message(response: &GeneratedMessage) -> String {
60 let mut message = String::new();
61
62 write!(&mut message, "{}", response.subject()).expect("write to string should not fail");
63 message.push_str("\n\n");
64
65 let wrapped_message = textwrap::wrap(&response.message, 78);
66 for line in wrapped_message {
67 message.push_str(&line);
68 message.push('\n');
69 }
70
71 message
72}