module Stackctl.Subcommand ( Subcommand(..) , subcommand , runSubcommand , runSubcommand' , runAppSubcommand ) where import Stackctl.Prelude import qualified Env import Options.Applicative import Stackctl.AutoSSO import Stackctl.CLI import Stackctl.ColorOption import Stackctl.Options import Stackctl.VerboseOption data Subcommand options subOptions = Subcommand { name :: Text , description :: Text , parse :: Parser subOptions , run :: subOptions -> options -> IO () } subcommand :: Subcommand options subOptions -> Mod CommandFields (options -> IO ()) subcommand Subcommand {..} = command (unpack name) (run <$> withInfo description parse) runSubcommand :: Mod CommandFields (Options -> IO a) -> IO a runSubcommand = runSubcommand' "Work with Stack specifications" envParser optionsParser -- brittany-disable-next-binding runSubcommand' :: Semigroup options => Text -> Env.Parser Env.Error options -> Parser options -> Mod CommandFields (options -> IO a) -> IO a runSubcommand' title parseEnv parseCLI sp = do (options, act) <- applyEnv <$> Env.parse (Env.header $ unpack title) parseEnv <*> execParser (withInfo title $ (,) <$> parseCLI <*> subparser sp) act options where applyEnv env = first (env <>) -- | Use this in the 'run' member of a 'Subcommand' that wants 'AppT' -- -- @ -- -- ... -- , parse = parseFooOptions -- , run = 'runAppSubcommand' runFoo -- } -- -- runFoo :: (MonadReader env m, HasAws env) => FooOptions -> m () -- runFoo = undefined -- @ -- runAppSubcommand :: ( HasColorOption options , HasVerboseOption options , HasAutoSSOOption options ) => (subOptions -> AppT (App options) IO a) -> subOptions -> options -> IO a runAppSubcommand f subOptions options = runAppT options $ f subOptions withInfo :: Text -> Parser a -> ParserInfo a withInfo d p = info (p <**> helper) $ progDesc (unpack d) <> fullDesc