    {-|

    The help command.

    |-}
    --TODO rename manuals
    --TODO substring matching

    {-# LANGUAGE QuasiQuotes #-}
    {-# LANGUAGE PackageImports #-}

    module Hledger.Cli.Commands.Help (

       helpmode
      ,help'

      ) where

    import Prelude ()
    import "base-compat-batteries" Prelude.Compat
    import Data.Char
    import Data.List
    import Data.Maybe
    import Data.String.Here
    import Safe
    import System.Console.CmdArgs.Explicit
    import System.Environment
    import System.IO

    import Hledger.Data.RawOptions
    import Hledger.Data.Types
    import Hledger.Cli.CliOptions
    import Hledger.Cli.DocFiles
    --import Hledger.Utils.Debug

    helpmode = (defCommandMode $ ["help"] ++ aliases) {
      modeHelp = "show any of the hledger manuals, choosing the most suitable viewer (info, man, a pager, or stdout). With no argument, list the manuals." `withAliases` aliases
     ,modeGroupFlags = Group {
         groupUnnamed = [
          flagNone ["info"]  (setboolopt "info")  "show the manual with info"
         ,flagNone ["man"]   (setboolopt "man")   "show the manual with man"
         ,flagNone ["pager"] (setboolopt "pager") "show the manual with $PAGER or less"
         ,flagNone ["cat"]   (setboolopt "cat")   "show the manual on stdout"
         ,flagNone ["help","h"]  (setboolopt "help")  "show this help"
         ]
        ,groupHidden = []
        ,groupNamed = []
        }
     ,modeArgs = ([], Just $ argsFlag "[MANUAL]")
    }
      where aliases = []

    -- | List or display one of the hledger manuals in various formats.
    -- You can select a docs viewer with one of the `--info`, `--man`, `--pager`, `--cat` flags.
    -- Otherwise it will use the first available of: info, man, $PAGER, less, stdout
    -- (and always stdout if output is non-interactive).
    help' :: CliOpts -> Journal -> IO ()
    help' opts _ = do
      exes <- likelyExecutablesInPath
      pagerprog <- fromMaybe "less" <$> lookupEnv "PAGER"
      interactive <- hIsTerminalDevice stdout
      let
        args = take 1 $ listofstringopt "args" $ rawopts_ opts
        topic = case args of
                  [pat] -> headMay [t | t <- docTopics, map toLower pat `isInfixOf` t]
                  _   -> Nothing
        [info, man, pager, cat] =
          [runInfoForTopic, runManForTopic, runPagerForTopic pagerprog, printHelpForTopic]
        viewer
          | boolopt "info"  $ rawopts_ opts = info
          | boolopt "man"   $ rawopts_ opts = man
          | boolopt "pager" $ rawopts_ opts = pager
          | boolopt "cat"   $ rawopts_ opts = cat
          | not interactive                 = cat
          | "info"    `elem` exes           = info
          | "man"     `elem` exes           = man
          | pagerprog `elem` exes           = pager
          | otherwise                       = cat
      case topic of
        Nothing -> putStrLn $ [here|
    Please choose a manual by typing "hledger help MANUAL" (any substring is ok).
    A viewer (info, man, a pager, or stdout) will be auto-selected,
    or type "hledger help -h" to see options. Manuals available:
    |] ++ "\n " ++ intercalate " " docTopics
        Just t  -> viewer t