dash-haskell-1.1.0.0: src/Options/Documentation.hs
{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
module Options.Documentation where
import qualified Data.Set as S
import qualified Data.List as L
import qualified Data.Map as M
import Data.String.Util
data Topic = Topic { title :: String, content :: String }
instance Eq Topic where
l == r = title l == title r
instance Ord Topic where
compare l r = compare (title l) (title r)
type Tag = String
type Documentation = M.Map Tag Topic
tags :: Documentation -> [String]
tags = M.keys
cabalSourcingTopic =
Topic "cabal sourcing" $
listing [
"This command pulls package selections from a cabal file",
" e.g. -c <project.cabal>\n",
"Note:",
"This command is not the same as a db provider.",
"Note:",
"If the package occurs more than once in the cabal file",
"with different range, neither package is taken.\n",
"Pulled packages can be constrained, see: cabal-constraints."
]
outputTopic =
Topic "output" $ listing [
"For each package sourced by dash-haskell, a matching docset"
, "will be written under this directory in its version, e.g:"
, " \"output/package-1.2.3.docset\""
]
nouserTopic =
Topic "no-user" $ listing [
"the no-user flag removes the user package db, e.g. :"
, "~/.ghc/x86_64-linux-7.10.1/package.conf.d/"
, "from db consideration"
]
dbTopic =
Topic "package database directory" $ listing [
"a db directory to directly use as the package database,",
"this is ordered as a \'dir\' in the db stack"
]
orderingTopic =
Topic "ordering" $ listing [
"an ordering of package db's, in that this is the order in which",
"dbs are examined for packages to use for documentation conversion",
"\n",
"Note: The global db must always appear, and it always first. This",
"is due to upstream constraints in ghc right now. (05/30/205)."
]
packageTopic =
Topic "package" $ "a ghc package, e.g. either, or either-4.1.0"
toEntry :: S.Set String -> Topic -> Documentation -> Documentation
toEntry s t doc = L.foldl (\m' k -> M.insert k t m') doc $ S.toList s
docs :: Documentation
docs =
let fromListing m (t,l) = toEntry (S.fromList l) t m in
L.foldl fromListing M.empty [
(cabalSourcingTopic , ["c", "cabal"]),
(outputTopic , ["o", "outputdir", "output", "docset"]),
(packageTopic , ["packages", "package"]),
(nouserTopic , ["n", "no-user", "user"]),
(dbTopic , ["db", "dir"]),
(orderingTopic , ["d", "ordering"])
]
-- | Given an arbitrary stream of options,
-- convert to possible topic indexes for documentation look-up.
toIndexes :: [String] -> [String]
toIndexes = S.toList . S.fromList . map toTopic
where
toTopic :: String -> String
toTopic [] = []
toTopic ('-':rest) = toTopic rest
toTopic remainder = remainder
toHelp :: Documentation -> [String] -> IO ()
toHelp d [] =
putStrLn $ "available help topics:\n" ++ L.intercalate ", " (tags d)
toHelp d args =
-- fold over each index, producing a list of docs to display
let topic_set = L.foldl folded S.empty $ toIndexes args in
if S.null topic_set then do
putStrLn "Sorry, no documentation available for expressions given.\n"
toHelp docs []
else do
putStrLn "accessing help on topics,"
putStrLn $ indenting 2 (listing . L.map headed $ S.toList topic_set)
where
headed :: Topic -> String
headed topic =
' ':title topic ++ ':':'\n':'\n': indenting 2 (content topic)
folded :: S.Set Topic -> String -> S.Set Topic
folded s index = maybe s (`S.insert` s) $ M.lookup index d