module Stack2nix.PP
   (ppIndented, ppSingletons) where

import           Text.PrettyPrint (Doc, Mode(..), TextDetails(..), fullRender, render)

-- | Formats the derivation doc with indentation and lines wrapped at 100 chars.
ppIndented :: Doc -> String
ppIndented = render

-- | Formats the derivation doc without indentation and with each list
-- element and function argument on its own line.
-- We go to this effort to "ugly-print" so that the resulting file is
-- less susceptible to merge conflicts when checked into git.
ppSingletons :: Doc -> String
ppSingletons doc = fixSpace . snd $ fullRender LeftMode 80 1.5 printer (0, "") doc
  where
    printer :: TextDetails -> (Int, String) -> (Int, String)
    printer (Chr c) (n, s) = ppChar n s c
    printer (Str s1) s2    = fmap (s1 ++) s2
    printer (PStr s1) s2   = fmap (s1 ++) s2

    ppChar :: Int -> String -> Char -> (Int, String)
    ppChar n s c = (n', s')
      where
        s' = case c of
               ',' -> "\n," ++ s
               ' ' -> (if n /= 0 then '\n' else ' '):s
               '{' -> "{\n " ++ s
               '}' -> "\n}" ++ s
               _   -> c:s
        n' = case c of
               '[' -> n - 1  -- PrettyPrint works backwards
               ']' -> n + 1
               _   -> n

    -- remove single trailing spaces
    fixSpace :: String -> String
    fixSpace (' ':'\n':s) = '\n':fixSpace s
    fixSpace (c:s) = c:fixSpace s
    fixSpace [] = []