elm-package-0.5: src/CommandLine/Arguments.hs
module CommandLine.Arguments (parse) where
import Control.Applicative (pure, optional, (<$>), (<*>), (<|>))
import Control.Monad.Error (throwError)
import Data.Monoid ((<>), mconcat, mempty)
import Data.Version (showVersion)
import qualified Options.Applicative as Opt
import qualified Text.PrettyPrint.ANSI.Leijen as PP
import qualified Bump
import qualified Diff
import qualified Install
import qualified Manager
import qualified Publish
import qualified Paths_elm_package as This
import qualified Elm.Compiler as Compiler
import qualified Elm.Package.Name as N
import qualified Elm.Package.Paths as Path
import qualified Elm.Package.Version as V
parse :: IO (Manager.Manager ())
parse =
Opt.customExecParser preferences parser
preferences :: Opt.ParserPrefs
preferences =
Opt.prefs (mempty <> Opt.showHelpOnError)
parser :: Opt.ParserInfo (Manager.Manager ())
parser =
Opt.info (Opt.helper <*> commands) infoModifier
-- GENERAL HELP
infoModifier :: Opt.InfoMod (Manager.Manager ())
infoModifier =
mconcat
[ Opt.fullDesc
, Opt.header top
, Opt.progDesc "install and publish elm libraries"
, Opt.footerDoc (Just moreHelp)
]
where
top =
"Elm Package Manager " ++ showVersion This.version
++ " (Elm Platform " ++ Compiler.version ++ ")\n"
moreHelp =
linesToDoc
[ "To learn more about a particular command run:"
, " elm-package COMMAND --help"
]
linesToDoc :: [String] -> PP.Doc
linesToDoc lines =
PP.vcat (map PP.text lines)
-- COMMANDS
commands :: Opt.Parser (Manager.Manager ())
commands =
Opt.hsubparser commandOptions
where
version =
Opt.flag' (error "temporarily out of order")
(Opt.long "version" <> Opt.short 'v' <> Opt.hidden)
commandOptions =
mconcat
[ Opt.command "install" installInfo
, Opt.command "publish" publishInfo
, Opt.command "bump" bumpInfo
, Opt.command "diff" diffInfo
]
-- BUMP
bumpInfo :: Opt.ParserInfo (Manager.Manager ())
bumpInfo =
Opt.info (pure Bump.bump) $
mconcat
[ Opt.fullDesc
, Opt.progDesc "Bump version numbers based on API changes"
]
-- DIFF
diffInfo :: Opt.ParserInfo (Manager.Manager ())
diffInfo =
Opt.info (Diff.diff <$> range) $
mconcat
[ Opt.fullDesc
, Opt.progDesc "Get differences between two APIs"
]
where
range =
(Diff.Between <$> package <*> version <*> version)
<|> (Diff.Since <$> version)
<|> (pure Diff.LatestVsActual)
-- PUBLISH
publishInfo :: Opt.ParserInfo (Manager.Manager ())
publishInfo =
Opt.info (pure Publish.publish) $
mconcat
[ Opt.fullDesc
, Opt.progDesc "Publish your package to the central catalog"
]
-- INSTALL
installInfo :: Opt.ParserInfo (Manager.Manager ())
installInfo =
Opt.info args infoModifier
where
args =
installWith <$> optional package <*> optional version <*> yes
installWith maybeName maybeVersion autoYes =
case (maybeName, maybeVersion) of
(Nothing, Nothing) ->
Install.install autoYes Install.Everything
(Just name, Nothing) ->
Install.install autoYes (Install.Latest name)
(Just name, Just version) ->
Install.install autoYes (Install.Exactly name version)
(Nothing, Just version) ->
throwError $
"You specified a version number, but not a package!\nVersion "
++ V.toString version ++ " of what?"
infoModifier =
mconcat
[ Opt.fullDesc
, Opt.progDesc "Install packages to use locally"
, Opt.footerDoc (Just examples)
]
examples =
linesToDoc
[ "Examples:"
, " elm-package install # everything needed by " ++ Path.description
, " elm-package install evancz/elm-html # any version"
, " elm-package install evancz/elm-html 1.2.0 # specific version"
]
-- ARGUMENT PARSERS
package :: Opt.Parser N.Name
package =
Opt.argument N.fromString $
mconcat
[ Opt.metavar "PACKAGE"
, Opt.help "A specific package name (e.g. evancz/automaton)"
]
version :: Opt.Parser V.Version
version =
Opt.argument V.fromString $
mconcat
[ Opt.metavar "VERSION"
, Opt.help "Specific version of a package (e.g. 1.2.0)"
]
yes :: Opt.Parser Bool
yes =
Opt.switch $
mconcat
[ Opt.long "yes"
, Opt.short 'y'
, Opt.help "Reply 'yes' to all automated prompts."
]