module Helium.Utils.OneLiner(OneLineTree(..), showOneLine) where
import Data.List
data OneLineTree
= OneLineNode [OneLineTree]
| OneLineText String
collapseString :: String
collapseString = "..."
collapseWidth :: Int
collapseWidth = length collapseString
showOneLine :: Int -> OneLineTree -> String
showOneLine width tree =
case tree of
OneLineText s -> s
OneLineNode ts -> oneLine True width ts
oneLine :: Bool -> Int -> [OneLineTree] -> String
oneLine toplevel width trees
| not toplevel &&
thisLevel > width
= collapseString
| not toplevel &&
minSize trees > collapseWidth &&
minSize trees > width
= collapseString
| otherwise = concatMap processTree (zip childWidths trees)
where
thisLevel = countThisLevel trees
childSizes = map (\t -> case t of { OneLineText _ -> 0; OneLineNode _ -> maxSize [t]} ) trees
numberedChildren = zip [0..] childSizes
childWidths = map snd (sort (distribute (width thisLevel) numberedChildren))
processTree (_ , OneLineText s) = s
processTree (childWidth, OneLineNode ts) = oneLine False childWidth ts
maxSize :: [OneLineTree] -> Int
maxSize ts =
let
sizeOne :: OneLineTree -> Int
sizeOne (OneLineText s) = length s
sizeOne (OneLineNode subTs) = maxSize subTs
in
sum (map sizeOne ts)
minSize :: [OneLineTree] -> Int
minSize ts =
let
sizeOne :: OneLineTree -> Int
sizeOne (OneLineText s) = length s
sizeOne (OneLineNode subTs) = min (minSize subTs) collapseWidth
in
sum (map sizeOne ts)
countThisLevel :: [OneLineTree] -> Int
countThisLevel ts =
sum [ length s | OneLineText s <- ts ]
distribute :: Int -> [(Int, Int)] -> [(Int, Int)]
distribute width children
| null smallChildren = [ (nr, widthPerChild) | (nr, _) <- children ]
| otherwise =
smallChildren ++ distribute leftOvers bigChildren
where
widthPerChild = width `div` length children
(smallChildren, bigChildren) =
partition (\(_, need) -> need <= widthPerChild) children
leftOvers = width sum (map snd smallChildren)