packages feed

morfette-0.2: GramLab/Commands.hs

module GramLab.Commands ( Command
                        , CommandName
                        , Help
                        , CommandSpec (..)
                        , module System.Console.GetOpt
                        , defaultMain
)
where
import Text.PrettyPrint(renderStyle,render,nest,vcat,hsep,style,Mode(..),mode,text,(<>),($$),($+$),(<+>))
import System.Console.GetOpt
import System
import System.IO (stderr)
import System.IO.UTF8 (hPutStr)
import qualified Data.List as List


type Command a = ([a] -> [String] -> IO ())
type CLArgName   = String
type CommandName = String
type Help        = String
data CommandSpec a =  CommandSpec (Command a)
                                  Help     
                                  [OptDescr a]
                                  [CLArgName]

defaultMain commands header = do
  args <- getArgs
  let theUsage = usage commands header
  case args of
    []           -> theUsage []
    command:opts -> case List.lookup command commands of
                      Nothing   -> theUsage  ["Invalid command: " ++ command]
                      Just spec -> runCommand theUsage spec opts

runCommand theUsage (CommandSpec command help optDesc argnames) args =             
    case getOpt Permute optDesc args of
          (o,n,[]  ) ->  command o n
          (_,_,errs) -> theUsage errs


usage commands header errs = hPutStr stderr . render 
                             $  vcat (List.map text errs)
                             $$ usageMsg commands header

usageMsg commands header = 
        text header
    $+$ (vcat (List.map commandUsage commands))

commandUsage (name , CommandSpec command help optionDesc args) = 
    text name <> text ":"
    $$ (nest 10 (text help))
    $$ (text name <+> text "[OPTION...]" <+> hsep (map text args))
    <+>  (nest 10 (text $ usageInfo "" optionDesc))