module Env.Help
( helpInfo
, helpDoc
) where
import qualified Data.List as List
import qualified Data.Map as Map
import Data.Maybe (catMaybes)
import Data.Ord (comparing)
import Env.Free
import Env.Parse
helpInfo :: Info a -> Parser b -> [Error] -> String
helpInfo Info { infoHeader, infoDesc, infoFooter } p errors =
List.intercalate "\n\n" $ catMaybes
[ infoHeader
, fmap (List.intercalate "\n" . splitWords 50) infoDesc
, Just (helpDoc p)
, fmap (List.intercalate "\n" . splitWords 50) infoFooter
] ++ helpErrors errors
helpDoc :: Parser a -> String
helpDoc p =
List.intercalate "\n" ("Available environment variables:\n" : helpParserDoc p)
helpParserDoc :: Parser a -> [String]
helpParserDoc = concat . Map.elems . foldAlt (\v -> Map.singleton (varfName v) (helpVarfDoc v)) . unParser
helpVarfDoc :: VarF a -> [String]
helpVarfDoc VarF { varfName, varfHelp, varfHelpDef } =
case varfHelp of
Nothing -> [indent 2 varfName]
Just h
| k > 15 -> indent 2 varfName : map (indent 25) (splitWords 30 t)
| otherwise ->
case zipWith indent (23 k : repeat 25) (splitWords 30 t) of
(x : xs) -> (indent 2 varfName ++ x) : xs
[] -> [indent 2 varfName]
where k = length varfName
t = maybe h (\s -> h ++ " (default: " ++ s ++")") varfHelpDef
helpErrors :: [Error] -> [String]
helpErrors [] = []
helpErrors fs =
[ "Parsing errors:"
, List.intercalate "\n" (map helpError (List.sortBy (comparing varName) fs))
]
helpError :: Error -> String
helpError (ParseError n e) = " " ++ n ++ " cannot be parsed: " ++ e
helpError (ENoExistError n) = " " ++ n ++ " is unset"
varName :: Error -> String
varName (ParseError n _) = n
varName (ENoExistError n) = n
splitWords :: Int -> String -> [String]
splitWords n = go [] 0 . words
where
go acc _ [] = prep acc
go acc k (w : ws)
| k + z < n = go (w : acc) (k + z) ws
| z > n = prep acc ++ case splitAt n w of (w', w'') -> w' : go [] 0 (w'' : ws)
| otherwise = prep acc ++ go [w] z ws
where
z = length w
prep [] = []
prep acc = [unwords (reverse acc)]
indent :: Int -> String -> String
indent n s = replicate n ' ' ++ s