Extract the first sentence from a block of text. Splits on sentence-ending punctuation (`.`, `!`, `?`) followed by whitespace or end-of-string. Also splits on `\n\n` (paragraph break) and `:` followed by a newline (list introductions like "Here's what I did:"). Returns the full text if no sentence boundary is found.
(text: &str)
| 137 | /// |
| 138 | /// Returns the full text if no sentence boundary is found. |
| 139 | pub(crate) fn extract_first_sentence(text: &str) -> String { |
| 140 | // Collapse leading whitespace / blank lines |
| 141 | let text = text.trim_start(); |
| 142 | |
| 143 | // Split on paragraph break FIRST — this scopes all subsequent checks |
| 144 | // to the first paragraph only, preventing cross-paragraph matches |
| 145 | // (e.g., a ":\n" in the second paragraph shouldn't affect the first). |
| 146 | let first_para = if let Some(idx) = text.find("\n\n") { |
| 147 | let para = text[..idx].trim(); |
| 148 | if para.len() > 10 { |
| 149 | para |
| 150 | } else { |
| 151 | text |
| 152 | } |
| 153 | } else { |
| 154 | text |
| 155 | }; |
| 156 | |
| 157 | // Check for colon-then-newline pattern ("Here's what I did:\n") |
| 158 | // within the first paragraph — take the part before the colon |
| 159 | if let Some(idx) = first_para.find(":\n") { |
| 160 | let before = first_para[..idx].trim(); |
| 161 | if before.len() > 10 { |
| 162 | return before.to_string(); |
| 163 | } |
| 164 | } |
| 165 | |
| 166 | // If the first paragraph ends with a colon (list introduction that |
| 167 | // was split at \n\n), strip the colon and use the rest as the summary. |
| 168 | let first_para = first_para.strip_suffix(':').unwrap_or(first_para); |
| 169 | |
| 170 | extract_first_sentence_from_paragraph(first_para) |
| 171 | } |
| 172 | |
| 173 | /// Common abbreviations that end with a period but aren't sentence endings. |
| 174 | const ABBREVIATIONS: &[&str] = &[ |