Created
October 2, 2024 14:42
-
-
Save goertzenator/f27299f6b9ba20f4206d330097ba4494 to your computer and use it in GitHub Desktop.
whitespace cleaning quasiquoter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- This is a modification of raw-strings-qq with whitespace cleanup features. | |
{- | Raw string literals, implemented using Template Haskell's quasiquotation | |
feature. | |
-} | |
module Util.QQ ( | |
w, | |
) | |
where | |
import Data.List.Extra | |
import Language.Haskell.TH | |
import Language.Haskell.TH.Quote | |
import Prelude | |
{- | |
A quasiquoter that cleans up whitespace and common indent. Example: | |
x = [w| | |
for(i=0;i<10;i++) { | |
printf("Hello, world!\n"); | |
} | |
|] | |
...gives... | |
x = "for(i=0;i<10;i++) {\n" <> | |
" printf(\"Hello, world!\\n\");\n" <> | |
"}\n" | |
-} | |
w :: QuasiQuoter | |
w = | |
QuasiQuoter | |
{ quoteExp = return . LitE . StringL . whiteSpaceSanitize | |
, quotePat = \_ -> | |
fail | |
"illegal raw string QuasiQuote \ | |
\(allowed as expression only, used as a pattern)" | |
, quoteType = \_ -> | |
fail | |
"illegal raw string QuasiQuote \ | |
\(allowed as expression only, used as a type)" | |
, quoteDec = \_ -> | |
fail | |
"illegal raw string QuasiQuote \ | |
\(allowed as expression only, used as a declaration)" | |
} | |
whiteSpaceSanitize :: String -> String | |
whiteSpaceSanitize s = | |
let | |
-- normalize newlines, remove trailing whitespace, remove leading and trailing empty lines | |
ls = (dropWhile null . dropWhileEnd null) (trimEnd <$> lines (normaliseNewlines s)) | |
minIndent = | |
( minimum | |
. map (length . takeWhile (== ' ')) -- count leading spaces | |
. filter (not . null) -- ignore empty lines | |
) | |
ls | |
in | |
unlines (drop minIndent <$> ls) | |
normaliseNewlines :: String -> String | |
normaliseNewlines [] = [] | |
normaliseNewlines ('\r' : '\n' : cs) = '\n' : normaliseNewlines cs | |
normaliseNewlines (c : cs) = c : normaliseNewlines cs |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment