literatex-0.1.0.0: app/LibOA.hs
------------------------------------------------------------------------------
-- |
-- Module : LibOA
-- Description : supplementary functions for optparse-applicative
-- Copyright : Copyright (c) 2019-2021 Travis Cardwell
-- License : MIT
--
-- This is a collection of functions that I often use with
-- @optparse-applicative@. I do not feel that it is worth maintaining yet
-- another helper package on Hackage, so I just copy the code to different
-- projects as required. If the library grows to a substantial size or others
-- with to use it, I will reconsider.
--
-- Revision: 2021-04-04
------------------------------------------------------------------------------
{-# LANGUAGE CPP #-}
module LibOA
( -- * Options
-- $Options
helper
, versioner
-- * Utilities
, commands
-- * Help
, (<||>)
, section
, table
, vspace
) where
-- https://hackage.haskell.org/package/ansi-wl-pprint
import qualified Text.PrettyPrint.ANSI.Leijen as Doc
import Text.PrettyPrint.ANSI.Leijen (Doc)
-- https://hackage.haskell.org/package/base
import qualified Data.List as List
#if !MIN_VERSION_base (4,11,0)
import Data.Monoid ((<>))
#endif
-- https://hackage.haskell.org/package/optparse-applicative
import qualified Options.Applicative as OA
import qualified Options.Applicative.Common as OAC
import qualified Options.Applicative.Types as OAT
------------------------------------------------------------------------------
-- $Options
--
-- Option descriptions are not capitalized.
-- | A hidden @-h@ / @--help@ option that always fails, showing the help
--
-- This is the same as 'OA.helper' except that it has a different help
-- message.
helper :: OA.Parser (a -> a)
#if MIN_VERSION_optparse_applicative (0,16,0)
helper = OA.option helpReader $ mconcat
[ OA.short 'h'
, OA.long "help"
, OA.help "show this help text"
, OA.hidden
]
where
helpReader = do
potentialCommand <- OAT.readerAsk
OA.readerAbort $ OA.ShowHelpText (Just potentialCommand)
#else
helper = OA.abortOption OA.ShowHelpText $ mconcat
[ OA.short 'h'
, OA.long "help"
, OA.help "show help and exit"
, OA.hidden
]
#endif
-- | A hidden @--version@ option that always fails, showing the version
versioner
:: String -- ^ version string
-> OA.Parser (a -> a)
versioner verStr = OA.infoOption verStr $ mconcat
[ OA.long "version"
, OA.help "show version and exit"
, OA.hidden
]
------------------------------------------------------------------------------
-- $Utilities
-- | Get a list of commands for a parser
commands :: OA.Parser a -> [String]
commands =
let go _ opt = case OAT.optMain opt of
OAT.CmdReader _ cmds _ -> reverse cmds
_otherReader -> []
in concat . OAC.mapParser go
------------------------------------------------------------------------------
-- $Help
-- | Insert a blank line between two documents
(<||>) :: Doc -> Doc -> Doc
d1 <||> d2 = d1 <> Doc.line <> Doc.line <> d2
infixr 5 <||>
-- | Create a section with a title and indented body
section :: String -> Doc -> Doc
section title = (Doc.text title Doc.<$$>) . Doc.indent 2
-- | Create a two-column table
table :: [(String, String)] -> Doc
table rows =
let width = 1 + maximum (map (length . fst) rows)
in Doc.vcat
[ Doc.fillBreak width (Doc.text l) Doc.<+> Doc.text r
| (l, r) <- rows
]
-- | Vertically space documents with blank lines between them
vspace :: [Doc] -> Doc
vspace = mconcat . List.intersperse (Doc.line <> Doc.line)