packages feed

opt-env-conf-0.15.0.0: src/OptEnvConf/Output.hs

{-# LANGUAGE OverloadedStrings #-}

module OptEnvConf.Output where

import Data.Char as Char
import Data.List (intercalate, intersperse)
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as NE
import Data.Maybe
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Text (Text)
import qualified Data.Text as T
import Data.Version
import GHC.Stack (SrcLoc (..), prettySrcLoc)
import OptEnvConf.Args (Dashed (..))
import qualified OptEnvConf.Args as Args
import OptEnvConf.Parser
import Text.Colour

stringLines :: String -> [[Chunk]]
stringLines s =
  let ls = T.lines (T.pack s)
   in map (pure . chunk) ls

progNameChunk :: String -> Chunk
progNameChunk = fore yellow . chunk . T.pack

versionChunk :: Version -> Chunk
versionChunk = chunk . T.pack . showVersion

usageChunk :: Chunk
usageChunk = fore cyan "Usage: "

commandChunk :: String -> Chunk
commandChunk = fore magenta . chunk . T.pack

functionChunk :: Text -> Chunk
functionChunk = fore yellow . chunk

mMetavarChunk :: Maybe Metavar -> Chunk
mMetavarChunk = metavarChunk . fromMaybe "METAVAR"

metavarChunk :: Metavar -> Chunk
metavarChunk = fore yellow . chunk . T.pack

dashedChunks :: [Dashed] -> Maybe [Chunk]
dashedChunks = fmap dashedChunksNE . NE.nonEmpty

dashedChunksNE :: NonEmpty Dashed -> [Chunk]
dashedChunksNE = intersperse (fore cyan "|") . map dashedChunk . NE.toList

dashedChunk :: Dashed -> Chunk
dashedChunk = fore white . chunk . T.pack . Args.renderDashed

envVarChunksNE :: NonEmpty String -> [Chunk]
envVarChunksNE = intersperse (fore cyan "|") . map envVarChunk . NE.toList

envVarChunk :: String -> Chunk
envVarChunk = fore white . chunk . T.pack

confValChunk :: NonEmpty String -> Chunk
confValChunk = fore white . chunk . T.pack . intercalate "." . NE.toList

defaultValueChunks :: String -> [Chunk]
defaultValueChunks val = ["default: ", fore yellow $ chunk $ T.pack val]

exampleValuesChunks :: [String] -> [Chunk]
exampleValuesChunks vals = case vals of
  [] -> []
  [val] -> ["example: ", fore yellow $ chunk $ T.pack val]
  _ -> ["examples: ", fore yellow $ chunk $ T.intercalate ", " $ map (T.pack . show) vals]

mHelpChunk :: Maybe Help -> Chunk
mHelpChunk = maybe (fore red "undocumented") helpChunk

helpChunk :: Help -> Chunk
helpChunk = fore blue . chunk . T.pack

headerChunks :: Text -> [Chunk]
headerChunks t = [fore cyan (chunk t), ":"]

syntaxChunk :: String -> Chunk
syntaxChunk = fore blue . chunk . T.pack

capabilitiesChunks :: Set Capability -> [Chunk]
capabilitiesChunks caps = case Set.toList caps of
  [] -> []
  cs -> intersperse ", " (map capabilityChunk cs)

capabilityChunk :: Capability -> Chunk
capabilityChunk = fore green . chunk . unCapability

mSrcLocChunk :: Maybe SrcLoc -> Chunk
mSrcLocChunk = maybe "without srcLoc" srcLocChunk

srcLocChunk :: SrcLoc -> Chunk
srcLocChunk = fore cyan . chunk . T.pack . prettySrcLoc . cleanSrcLoc
  where
    -- GHC puts the package hash in there, which may change accross compilation
    -- and that messes with golden tests.
    -- We try to remove the hash from the package here.
    -- The srcLocPackage looks like this:
    -- opt-env-conf-test-0.0.0.3-6OHAhVu967XFT6LS52oRkR-opt-env-conf-test
    -- which looks like:
    -- <name>-<version>-<hash>-<name>
    -- So we take every '-'-separated part until one starts with a number.
    cleanSrcLoc loc = loc {srcLocPackage = cleanPackage (srcLocPackage loc)}
    cleanPackage pkg =
      T.unpack $
        T.intercalate "-" $
          takeWhile (not . maybe False (Char.isDigit . fst) . T.uncons) $
            T.splitOn "-" (T.pack pkg)

indent :: [[Chunk]] -> [[Chunk]]
indent = map ("  " :)

parenthesise :: [Chunk] -> [Chunk]
parenthesise [c] = [c]
parenthesise cs = fore cyan "(" : cs ++ [fore cyan ")"]

bracketise :: [Chunk] -> [Chunk]
bracketise [c] = [fore cyan "[", c, fore cyan "]"]
bracketise cs = fore cyan "[" : cs ++ [fore cyan "]"]