Sharing Swift code to pass punctuation test

A lot has been said in past years about gaps in punctuation documentation so I thought I’d share a bit of the code I needed to pass the punctuation_FullMontyQuotesIn test.

Not shown are the bits to shuffle around the closing quote, as indicated by the CSL, but that’s not hard.

I hope to come across the basis for these rules, to reference here, but for now it’s a bit arbitrary, just making the test pass.

// https://discourse.citationstyles.org/t/more-on-punctuation-notes/264
// https://discourse.citationstyles.org/t/english-vs-american-style-punctuation/269
// https://discourse.citationstyles.org/t/punctuation-for-quote-within-quote-where-punctuation-in-quote-true/1196

public extension Character {
    /// Whether character is a punctuation mark
    var isPunctuation: Bool { isQuotablePunctuation || ":;".contains(self) }

    /// Whether character is punctuation that may be moved within an ending quotation
    var isQuotablePunctuation: Bool { "!?.,".contains(self) }

    /// Whether this character is gramatically invalid after another character
    ///
    /// For example, two colons shouldn't appear together
    func invalidAfter(_ before: Character?) -> Bool {
        guard let before else { return false }
        switch self {
            case ":": return ":;!?".contains(before)
            case ";": return ";".contains(before)
            case ".": return ".:;!?".contains(before)
            case ",": return ",".contains(before)
            case "!": return "!:;".contains(before)
            case "?": return "?:;".contains(before)
            default: return false
        }
    }

    /// If two characters are invalid together, per `invalidAfter()`, the *latter* character is
    /// suppressed unless the first is `preferToRemove=true`, in which case *it* is suppressed
    func preferToRemove(whenNextTo other: Character) -> Bool {
        ":;".contains(self) && "!?".contains(other)
    }
}

1 Like