crux-0.7: src/Crux/Config/Doc.hs
{-# LANGUAGE OverloadedStrings #-}
module Crux.Config.Doc (configDocs) where
import Config.Schema (sectionsSpec,generateDocs)
import Data.Function ( on )
import qualified Data.List as L
import Data.Text ( Text )
import qualified Data.Text as T
import Prettyprinter
import Prettyprinter.Util ( reflow )
import SimpleGetOpt ( OptSpec(..) )
import Crux.Config
import Crux.Config.Load (commandLineOptions)
configDocs :: Text -> Config opts -> Doc ann
configDocs nm cfg =
vcat [ heading "Command line flags:"
, indent 2 $ cmdLineDocs $ commandLineOptions cfg
, envVarDocs cfg
, heading "Configuration file format:"
, nest 2 (viaShow $ generateDocs (sectionsSpec nm (cfgFile cfg)))
]
cmdLineDocs :: OptSpec a -> Doc ann
cmdLineDocs opts =
vcat [ nest 2 $ vcat $ "Parameters:" : ppParams
, mempty
, nest 2 $ vcat $ "Flags:" : ppFlags
]
where
ppParams = let maxLen = maximum $ (length . fst) <$> progParamDocs opts
in map (ppParam maxLen) $ progParamDocs opts
ppParam l (n,d) = let pad = max 0 $ l - length d
in hcat [ pretty n
, pretty $ T.replicate (pad + 4) " "
, nest 2 $ reflow $ T.pack d ]
ppFlags = let flagset = fmap ppFlag $ L.sortBy (compare `on` optSort) $ progOptions opts
optSort o = (L.sort $ optShortFlags o <> "zzzzz", L.sort $ optLongFlags o)
lengths = fmap (maximum . fmap T.length) $ L.transpose flagset
textLen (l,t) = let f = T.replicate (max 0 $ l - T.length t) " " in t <> f
sizedCols = fmap (fmap textLen . zip lengths) $ flagset
padLast = align . reflow
prettyLine = hcat . fst . foldr (\c (p,g) -> (g c : space : p, pretty)) ([], padLast)
in fmap prettyLine sizedCols
ppFlag :: OptDescr a -> [Text]
ppFlag od = let sfs = if null (optShortFlags od) then ""
else let each =
let f = case optArgument od of
NoArg _ -> T.singleton
ReqArg a _ -> (\c -> T.singleton c <> " " <> T.pack a)
OptArg a _ -> (\c -> T.singleton c <> " [" <> T.pack a <> "]")
in f <$> optShortFlags od
in "-" <> T.intercalate ",-" each
lfs = if null (optLongFlags od) then ""
else let each =
let f = case optArgument od of
NoArg _ -> T.pack
ReqArg a _ -> (\s -> T.pack s <> "=" <> T.pack a)
OptArg a _ -> (\s -> T.pack s <> "=[" <> T.pack a <> "]")
in f <$> optLongFlags od
in "--" <> T.intercalate ",--" each
in [ sfs, lfs, T.pack $ optDescription od ]
envVarDocs :: Config a -> Doc ann
envVarDocs cfg
| null vs = mempty
| otherwise = vcat [ heading "Environment variables:"
, indent 2 (vcat (map pp vs))
]
where
vs = cfgEnv cfg
m = maximum (map (length . evName) vs)
pp v = pretty (n ++ replicate (1 + m - length n) ' ') <+> (pretty $ evDoc v)
where n = evName v
heading :: String -> Doc ann
heading x = vcat [ mempty
, pretty x
, pretty (replicate (length x) '=')
, mempty ]