hsenv-0.3: src/Util/Args/Usage.hs
module Util.Args.Usage (usage) where
import Util.Args.ArgDescr (ArgDescr(..), DefaultValue(..))
import Data.Function (on)
import Util.WordWrap (wordWrap)
import Data.List(sortBy)
import Util.Args.ArgArrow (ArgArrow, getKnownArgs)
import Util.String (padTo)
import System.Environment (getProgName)
-- pretty prints cli arg description for usage
-- left column contains cli arg header (e.g. '--verbose', or '--binary=PATH')
-- right column contains info messages for that argument
-- returns list of lines
showFlagDescr :: ArgDescr -> [String]
showFlagDescr argDescr = zipWith makeLine lefts helpLines
where lefts = argLine : repeat ""
argLine = case argDescr of
SwitchDescr name _ Nothing -> "--" ++ name
SwitchDescr name _ (Just c) ->
concat ["-", [c], " ", "--", name]
ValArg name tmpl _ _ -> concat ["--", name, "=", tmpl]
msgLines = wordWrap 60 $ case argDescr of
SwitchDescr _ hlp _ -> hlp
ValArg _ _ default' help ->
concat [help, "\n", defaultsLine default']
helpLines = if length argLine < 18 then
msgLines
else
"" : msgLines -- line with argument is too long
-- make more room for it
defaultsLine (ConstValue s) = concat ["(defaults to '", s, "')"]
defaultsLine (DynValue s) = concat ["(defaults to ", s, ")"]
makeLine infoLine descrLine = (infoLine `padTo` 20) ++ descrLine
-- returns string with formatted cli arg usage help message
-- argument descriptions are extracted from arg parsing computation
-- adds simple header and appends provided footer
usage :: ArgArrow a b -> String -> IO String
usage arrow outro = do
self <- getProgName
let intro = "usage: " ++ self ++ " [FLAGS]"
return $ unlines $ [intro, "", "Flags:"] ++ flagsDescr ++ [""] ++ outro'
where flagsDescr = concatMap showFlagDescr $ argDescrSort $ getKnownArgs arrow
argDescrSort = sortBy (compare `on` argName)
outro' = wordWrap 80 outro