med-module-0.0: example/Animate/Option.hs
module Animate.Option where
import Data.Monoid ((<>))
import qualified Options.Applicative as OP
import Control.Applicative(pure, liftA2, (<$>), (<*>))
info :: OP.Parser a -> OP.ParserInfo a
info p =
OP.info
(OP.helper <*> p)
(OP.fullDesc <>
OP.progDesc "Generate animation of playing MED/OctaMED song.")
parser :: OP.Parser (Option, [FilePath])
parser =
liftA2 (,)
oparser
(OP.many $
OP.strArgument $
OP.metavar "FILE" <>
OP.help "Input MED module")
oparser :: OP.Parser Option
oparser =
pure Option
<*> (OP.strOption $
OP.long "frame-pattern" <>
OP.metavar "PATHFMT" <>
OP.value "" <>
OP.help "Format string for frame paths")
<*> (OP.option (Just <$> readNonNeg) $
OP.long "repeat-until" <>
OP.metavar "SECONDS" <>
OP.value Nothing <>
OP.help "Loop song for a certain maximum time")
<*> (OP.option readNonNeg $
OP.long "fade-out" <>
OP.metavar "SECONDS" <>
OP.value 0 <>
OP.help "Reduce brightness for a certain duration at the end")
<*> (OP.option OP.auto $
OP.long "context-size" <>
OP.metavar "NATURAL" <>
OP.value 16 <>
OP.help "Number of lines before and after current one")
<*> (OP.option OP.auto $
OP.long "height" <>
OP.metavar "POINTS" <>
OP.value 720 <>
OP.help "Height of the paper in typographical points")
{- |
Also allow numbers like @.123@ instead of @0.123@.
-}
readNonNeg :: OP.ReadM Double
readNonNeg =
OP.eitherReader $ \arg -> case reads ('0':arg) of
[(r, "")] ->
if r<0
then Left $ "negative number `" ++ arg ++ "'"
else return r
_ -> Left $ "not a number `" ++ arg ++ "'"
data Option =
Option {
framePattern :: FilePath,
repeatUntil :: Maybe Double,
fadeOut :: Double,
contextSize :: Int,
height :: Int
}