{-# LANGUAGE DerivingStrategies #-}
module Options
( Opts(..)
, NextSongFlag(..)
, execParser
, prefs
, showHelpOnEmpty
, optsParser
, optsParserInfo ) where
import Options.Applicative
( (<**>),
auto,
fullDesc,
header,
help,
info,
long,
metavar,
option,
strOption,
flag,
flag',
prefs,
progDesc,
short,
showHelpOnEmpty,
value,
execParser,
Parser,
ParserInfo,
hidden,
many,
(<|>) )
import Options.Applicative.Extra ( helperWith )
import Version ( progName )
data Opts = Opts -- ^ Custom data record for storing 'Options.Applicative.Parser' values
{ optPort :: Integer -- ^ MPD port to connect.
, optHost :: String -- ^ MPD host address to connect.
, optPass :: String -- ^ Plain text password to connect to MPD.
, optNext :: NextSongFlag -- ^ Either include in the json or print it alone.
, optVersion :: Bool
}
deriving stock (Show, Eq)
data NextSongFlag = IncludeNextSong
| OnlyNextSong
| NoNextSong
deriving stock (Show, Eq)
optsParser :: Parser Opts
optsParser
= Opts
<$> portOptParser
<*> hostOptParser
<*> passOptParser
<*> nextSongOptParser
<*> versionOptParse
where
nextSongOptParser = nextSongFlagCountOptParser
<|> nextSongOnlyOptParser
portOptParser :: Parser Integer
portOptParser
= option auto
$ long "port"
<> short 'p'
<> metavar "PORTNUM"
<> value 6600
<> help "Port number"
hostOptParser :: Parser String
hostOptParser
= strOption
$ metavar "ADDRESS"
<> long "host"
<> short 'h'
<> value "localhost"
<> help "Host address"
passOptParser :: Parser String
passOptParser
= option auto
$ metavar "PASSWORD"
<> long "password"
<> short 'P'
<> value ""
<> help "Password for connecting (will be sent as plain text)"
nextSongFlagCountOptParser :: Parser NextSongFlag
nextSongFlagCountOptParser =
fmap (intToNextSong . length) <$> many
$ flag' ()
$ short 'n'
<> long "next"
<> help
(unlines
[ "If used once (e.g. -n), include next song information in the output."
, "If used twice (e.g. -nn) it's an alias for --next-only."
])
nextSongOnlyOptParser :: Parser NextSongFlag
nextSongOnlyOptParser
= flag' OnlyNextSong
( long "next-only"
<> help "Only print next song information." )
intToNextSong :: Int -> NextSongFlag
intToNextSong count
| count == 1 = IncludeNextSong
| count > 1 = OnlyNextSong
| otherwise = NoNextSong
versionOptParse :: Parser Bool
versionOptParse =
flag False True
$ long "version"
<> short 'V'
<> help "Display the version number"
optsParserInfo :: ParserInfo Opts
optsParserInfo = info (optsParser <**> helper')
$ fullDesc
<> progDesc "Print currently playing song information as JSON"
<> header (progName ++ " - " ++ "Current MPD song information as JSON")
helper' :: Parser (a -> a)
helper' = helperWith
$ long "help"
-- <> help "Show this help text"
<> hidden -- don't show in help messages