@@ -1147,13 +1147,16 @@ prettyCharacterSet characterSet expression =
1147
1147
-- >>> multilineChunks (Chunks [] "\n\NUL\b\f\t")
1148
1148
-- Chunks [("\n",TextLit (Chunks [] "\NUL\b\f"))] "\t"
1149
1149
multilineChunks :: Chunks s a -> Chunks s a
1150
- multilineChunks = escapeControlCharacters . escapeLastLineLeadingWhitespace
1150
+ multilineChunks =
1151
+ escapeTrailingSingleQuote
1152
+ . escapeControlCharacters
1153
+ . escapeLastLineLeadingWhitespace
1151
1154
1152
1155
-- | Escape leading whitespace on the last line by moving it into a string
1153
- -- string interpolation
1156
+ -- interpolation
1154
1157
--
1155
- -- Unescaped leading whitespace on the last line would otherwise be removed
1156
- -- by the parser's dedentation logic.
1158
+ -- This ensures that the parser can find the correct indentation level, no matter
1159
+ -- what the other lines contain.-
1157
1160
--
1158
1161
-- >>> escapeLastLineLeadingWhitespace (Chunks [] "\n \tx")
1159
1162
-- Chunks [("\n",TextLit (Chunks [] " \t"))] "x"
@@ -1231,6 +1234,19 @@ splitOnPredicate p t = case Text.break p t of
1231
1234
(c, d) -> case splitOnPredicate p d of
1232
1235
(e, f) -> ((a, c) : e, f)
1233
1236
1237
+ -- | Escape a trailing single quote by moving it into a string interpolation
1238
+ --
1239
+ -- Otherwise the multiline-string would end with @'''@, which would be parsed
1240
+ -- as an escaped @''@.
1241
+ --
1242
+ -- >>> escapeTrailingSingleQuote (Chunks [] "\n'")
1243
+ -- Chunks [("\n",TextLit (Chunks [] "'"))] ""
1244
+ escapeTrailingSingleQuote :: Chunks s a -> Chunks s a
1245
+ escapeTrailingSingleQuote chunks@ (Chunks as b) =
1246
+ case Text. unsnoc b of
1247
+ Just (b', ' \' ' ) -> Chunks (as ++ [(b', TextLit (Chunks [] " '" ))]) " "
1248
+ _ -> chunks
1249
+
1234
1250
-- | Pretty-print a value
1235
1251
pretty_ :: Pretty a => a -> Text
1236
1252
pretty_ = prettyToStrictText
0 commit comments