qux-0.2.0.0: src/Qux/Commands.hs
{-|
Module : Qux.Commands
Copyright : (c) Henry J. Wylde, 2015
License : BSD3
Maintainer : public@hjwylde.com
-}
{-# OPTIONS_HADDOCK hide, prune #-}
module Qux.Commands where
import Data.Version (showVersion)
import qualified Language.Qux.Version as Qux
import Options.Applicative
import Options.Applicative.Types
import Prelude hiding (print)
import qualified Qux.Commands.Build as Build
import qualified Qux.Commands.Check as Check
import qualified Qux.Commands.Compile as Compile
import qualified Qux.Commands.Print as Print
import qualified Qux.Version as Binary
import System.FilePath
import Text.PrettyPrint (Mode(..))
-- * Optparse for Qux
quxPrefs :: ParserPrefs
quxPrefs = prefs $ columns 100
quxInfo :: ParserInfo Options
quxInfo = info (infoOptions <*> qux) (fullDesc <> noIntersperse)
where
infoOptions = helper <*> version <*> numericVersion <*> quxVersion
version = infoOption ("Version " ++ showVersion Binary.version) $ mconcat [
long "version", short 'V', hidden,
help "Show this binary's version"
]
numericVersion = infoOption (showVersion Binary.version) $ mconcat [
long "numeric-version", hidden,
help "Show this binary's version (without the prefix)"
]
quxVersion = infoOption ("Qux version " ++ showVersion Qux.version) $ mconcat [
long "qux-version", hidden,
help "Show the qux version this binary was compiled with"
]
-- * Command
data Options = Options {
argCommand :: Command
}
qux :: Parser Options
qux = Options <$> subparser (mconcat [
command "build" $ info (helper <*> build) (fullDesc <> progDesc "Build FILES using composable options"),
command "check" $ info (helper <*> check) (fullDesc <> progDesc "Check FILES for correctness" <> header "Shortcut for `qux build --type-check'"),
command "compile" $ info (helper <*> compile) (fullDesc <> progDesc "Compile FILES into the LLVM IR" <> header "Shortcut for `qux build --compile'"),
command "print" $ info (helper <*> print) (fullDesc <> progDesc "Pretty print FILE")
])
-- * Subcommands
data Command = Build Build.Options
| Check Check.Options
| Compile Compile.Options
| Print Print.Options
-- ** Build
build :: Parser Command
build = fmap Build $ Build.Options
<$> switch (mconcat [
long "compile", short 'c',
help "Enable compilation to LLVM IR"
])
<*> strOption (mconcat [
long "destination", short 'd', metavar "DIR",
value ("." ++ [pathSeparator]), showDefault,
help "Specify the output directory to put the compiled LLVM IR"
])
<*> formatOption (mconcat [
long "format", short 'f', metavar "FORMAT",
value Build.Bitcode, showDefault,
help "Specify the LLVM output format as either `bitcode' or `assembly'"
])
<*> switch (mconcat [
long "type-check",
help "Enable type checking"
])
<*> some (strArgument $ mconcat [
metavar "FILES..."
])
-- ** Check
check :: Parser Command
check = Check . Check.Options <$> some (strArgument $ mconcat [
metavar "FILES..."
])
-- ** Compile
compile :: Parser Command
compile = fmap Compile $ Compile.Options
<$> strOption (mconcat [
long "destination", short 'd', metavar "DIR",
value ("." ++ [pathSeparator]), showDefault,
help "Specify the output directory to put the compiled LLVM IR"
])
<*> formatOption (mconcat [
long "format", short 'f', metavar "FORMAT",
value Build.Bitcode, showDefault,
help "Specify the LLVM output format as either `bitcode' or `assembly'"
])
<*> some (strArgument $ mconcat [
metavar "FILES..."
])
-- ** Print
print :: Parser Command
print = fmap Print $ Print.Options
<$> option auto (mconcat [
long "line-length", short 'l', metavar "LENGTH",
value 100, showDefault,
help "Specify the maximum line length"
])
<*> modeOption (mconcat [
long "mode", short 'm', metavar "MODE",
value PageMode, showDefaultWith $ const "normal",
help "Specify the rendering mode as either `normal' or `one-line'"
])
<*> option auto (mconcat [
long "ribbons-per-line", short 'r', metavar "RIBBONS",
value 1.5, showDefault,
help "Specify the ratio of line length to ribbon length"
])
<*> strArgument (mconcat [
metavar "FILE"
])
where
modeOption = option $ readerAsk >>= \opt -> case opt of
"normal" -> return PageMode
"one-line" -> return OneLineMode
_ -> readerError $ "unrecognised mode `" ++ opt ++ "'"
-- ** Helpers
formatOption :: Mod OptionFields Build.Format -> Parser Build.Format
formatOption = option $ readerAsk >>= \opt -> case opt of
"assembly" -> return Build.Assembly
"bitcode" -> return Build.Bitcode
_ -> readerError $ "unrecognised format `" ++ opt ++ "'"