packages feed

commander-0.1.0.0: examples/Example1.hs

{-# LANGUAGE DataKinds, ScopedTypeVariables #-}

module Main where

import qualified Data.Map as Map
import Commander.Params   (Flag(..), Value(..))
import Commander.Commands (Command(..), commands, command, help, run, evalCommand)

--
-- build up a Command (IO ()) object. The IO () is based
-- on the output of the functions used in the commands.
--
someCommands :: Command (IO ())
someCommands = commands $ do

    command "repeat" $ do

        help "Repeat a string n times"

        run $
            \(Value str :: Value "value to repeat" String)
             (Flag n :: Flag '["n"] "times to repeat" Int) ->
             sequence_ $ replicate n (putStrLn str)

    command "calculate" $ do

        help "perform calculations"

        command "add" $ do

            help "add two numbers"

            run $
                \(Value n1 :: Value "number 1" Int)
                 (Value n2 :: Value "number 2" Int)
                 (Flag verbose :: Flag '["v", "verbose"] "verbose mode" Bool) ->
                 if verbose
                    then putStrLn $ (show n1) ++ " + " ++ (show n2) ++ " = " ++ (show $ n1 + n2)
                    else putStrLn (show $ n1 + n2)

        command "multiply" $ do

            help "multiply two numbers"

            run $
                \(Value n1 :: Value "number 1" Int)
                 (Value n2 :: Value "number 2" Int) ->
                 putStrLn $ (show n1) ++ " x " ++ (show n2) ++ " = " ++ (show $ n1 * n2)

    command "login" $ do

        help "pretend authentication"

        run $
            \(Value username :: Value "Username" String)
             (Flag mPassword :: Flag '["p", "password"] "Password" (Maybe String)) -> do
             pass <- case mPassword of
                Just password -> return password
                Nothing -> getLine
             putStrLn $ "logging in with username=" ++ username ++ " password=" ++ pass



--
-- run an IO () command, printing the error or command output:
--
runCommand :: [String] -> [(String,String)] -> Command (IO ()) -> IO ()
runCommand vals flags cmds = case evalCommand vals (Map.fromList flags) cmds of
    Left err -> putStrLn ("Error: " ++ show err)
    Right res -> res

--
-- run some commands. Here, we basically pass in strings denoting a path and flags.
-- Commander maps these to output commands if possible, performing whatever type
-- converstion is required to conform to the flags and values these commands expect
-- in a completely safe way.
--
main :: IO ()
main = do

    putStrLn "\nRepeat Command:"
    runCommand ["repeat", "hello there"] [("n","2")] someCommands

    putStrLn "\nAdd numbers:"
    runCommand ["calculate", "add", "12", "13"] [] someCommands

    putStrLn "\nAdd numbers (verbosely):"
    runCommand ["calculate", "add", "12", "13"] [("verbose", "")] someCommands

    putStrLn "\nMultiply numbers:"
    runCommand ["calculate", "multiply", "12", "13"] [] someCommands

    putStrLn "\nPretend Auth (password provided):"
    runCommand ["login", "james"] [("p", "lemons")] someCommands

    putStrLn "\nPretend Auth (please type a random string):"
    runCommand ["login", "james"] [] someCommands