module NeatInterpolation.String where

import NeatInterpolation.Prelude

unindent :: [Char] -> [Char]
unindent :: [Char] -> [Char]
unindent [Char]
s =
  case [Char] -> [[Char]]
lines [Char]
s of
    [Char]
head : [[Char]]
tail ->
      let unindentedHead :: [Char]
unindentedHead = forall a. (a -> Bool) -> [a] -> [a]
dropWhile (forall a. Eq a => a -> a -> Bool
== Char
' ') [Char]
head
          minimumTailIndent :: Maybe Int
minimumTailIndent = [Char] -> Maybe Int
minimumIndent forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. [[Char]] -> [Char]
unlines forall a b. (a -> b) -> a -> b
$ [[Char]]
tail
          unindentedTail :: [[Char]]
unindentedTail = case Maybe Int
minimumTailIndent of
            Just Int
indent -> forall a b. (a -> b) -> [a] -> [b]
map (forall a. Int -> [a] -> [a]
drop Int
indent) [[Char]]
tail
            Maybe Int
Nothing -> [[Char]]
tail
       in [[Char]] -> [Char]
unlines forall a b. (a -> b) -> a -> b
$ [Char]
unindentedHead forall a. a -> [a] -> [a]
: [[Char]]
unindentedTail
    [] -> []

trim :: [Char] -> [Char]
trim :: [Char] -> [Char]
trim = forall a. (a -> Bool) -> [a] -> [a]
dropWhileRev Char -> Bool
isSpace forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace

dropWhileRev :: (a -> Bool) -> [a] -> [a]
dropWhileRev :: forall a. (a -> Bool) -> [a] -> [a]
dropWhileRev a -> Bool
p = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\a
x [a]
xs -> if a -> Bool
p a
x Bool -> Bool -> Bool
&& forall (t :: * -> *) a. Foldable t => t a -> Bool
null [a]
xs then [] else a
x forall a. a -> [a] -> [a]
: [a]
xs) []

tabsToSpaces :: [Char] -> [Char]
tabsToSpaces :: [Char] -> [Char]
tabsToSpaces (Char
'\t' : [Char]
tail) = [Char]
"    " forall a. [a] -> [a] -> [a]
++ [Char] -> [Char]
tabsToSpaces [Char]
tail
tabsToSpaces (Char
head : [Char]
tail) = Char
head forall a. a -> [a] -> [a]
: [Char] -> [Char]
tabsToSpaces [Char]
tail
tabsToSpaces [] = []

minimumIndent :: [Char] -> Maybe Int
minimumIndent :: [Char] -> Maybe Int
minimumIndent =
  forall a. [a] -> Maybe a
listToMaybe
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a. Ord a => [a] -> [a]
sort
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a b. (a -> b) -> [a] -> [b]
map [Char] -> Int
lineIndent
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace)
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. [Char] -> [[Char]]
lines

-- | Amount of preceding spaces on first line
lineIndent :: [Char] -> Int
lineIndent :: [Char] -> Int
lineIndent = forall (t :: * -> *) a. Foldable t => t a -> Int
length forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall a. (a -> Bool) -> [a] -> [a]
takeWhile (forall a. Eq a => a -> a -> Bool
== Char
' ')