craft-proof it — the dialogue-dash exception applies after ? and ! only, so Finì. —domani partiamo. gets its capital mark again (#496 review)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Martin BallandClaude Opus 5.5 committed 2026-11-02 23:47:08 +00:00
1 parent a8b3bb74c8
commit f3d411638d
1 file changed
+4 -2
+4 -2
View File
@@ -167,8 +167,8 @@ fn ends_sentence(gap: &str, prev: &str) -> bool {
let rest = after_marks.trim_start_matches(CLOSING);
// (Not the object placeholder `\u{1}`: `Chi era?\u{1} era Marco.` still starts a sentence.)
// `«Vai?» disse lui.` and `—Vai? —disse lui.`: the narration after a quoted question or
// exclamation, or after a dialogue dash, goes on in lower case.
if rest.contains('—') || (end != '.' && after_marks.starts_with(|c| c != '\u{1}' && CLOSING.contains(&c))) {
// exclamation (not after a period: `Finì. —domani` starts a sentence), or after a dialogue dash, goes on in lower case.
if end != '.' && (rest.contains('—') || after_marks.starts_with(|c| c != '\u{1}' && CLOSING.contains(&c))) {
return false;
}
rest.starts_with(char::is_whitespace) && rest.trim_start().chars().all(|c| matches!(c, '"' | '“' | '«' | '(' | '[' | '\'' | '—'))
@@ -417,6 +417,8 @@ mod tests {
assert!(fixes(t).is_empty(), "{t}: {:?}", fixes(t));
}
assert!(fixes("Vado a Roma? sì.").contains(&pair("sì", "Sì")), "a bare question still ends the sentence");
// After a period the dash opens the next line of speech: a sentence starts.
assert!(fixes("Finì. —domani partiamo.").contains(&pair("domani", "Domani")), "{:?}", fixes("Finì. —domani partiamo."));
// An inline object (`\u{1}`) is not a closing quote.
assert!(fixes("Chi era?\u{1} era Marco.").contains(&pair("era", "Era")), "{:?}", fixes("Chi era?\u{1} era Marco."));
}