module NeatInterpolation.String where
import BasePrelude
normalizeQQInput :: [Char] -> [Char]
normalizeQQInput = trim . unindent' . tabsToSpaces
where
unindent' :: [Char] -> [Char]
unindent' s =
case lines s of
head:tail ->
let
unindentedHead = dropWhile (== ' ') head
minimumTailIndent = minimumIndent . unlines $ tail
unindentedTail = case minimumTailIndent of
Just indent -> map (drop indent) tail
Nothing -> tail
in unlines $ unindentedHead : unindentedTail
[] -> []
trim :: [Char] -> [Char]
trim = dropWhileRev isSpace . dropWhile isSpace
dropWhileRev :: (a -> Bool) -> [a] -> [a]
dropWhileRev p = foldr (\x xs -> if p x && null xs then [] else x:xs) []
unindent :: [Char] -> [Char]
unindent s =
case minimumIndent s of
Just indent -> unlines . map (drop indent) . lines $ s
Nothing -> s
tabsToSpaces :: [Char] -> [Char]
tabsToSpaces ('\t':tail) = " " ++ tabsToSpaces tail
tabsToSpaces (head:tail) = head : tabsToSpaces tail
tabsToSpaces [] = []
minimumIndent :: [Char] -> Maybe Int
minimumIndent =
listToMaybe . sort . map lineIndent
. filter (not . null . dropWhile isSpace) . lines
lineIndent :: [Char] -> Int
lineIndent = length . takeWhile (== ' ')