module Imm.Options where
import Imm.Dyre as Dyre (Mode (..))
import qualified Imm.Dyre as Dyre
import Imm.Feed
import Imm.Logger as Logger
import Imm.Prelude hiding ((<>))
import Imm.Pretty
import Options.Applicative.Builder
import Options.Applicative.Extra
import Options.Applicative.Types
import URI.ByteString
data Command = Check (Maybe FeedRef)
| Import
| Read (Maybe FeedRef)
| Rebuild
| Unread (Maybe FeedRef)
| Run (Maybe FeedRef)
| Show (Maybe FeedRef)
| ShowVersion
| Subscribe URI (Maybe Text)
| Unsubscribe (Maybe FeedRef)
deriving instance Eq Command
deriving instance Show Command
instance Pretty Command where
pretty (Check f) = text "Check feed(s):" <+> pretty f
pretty Import = text "Import feeds"
pretty (Read f) = text "Mark feed(s) as read:" <+> pretty f
pretty Rebuild = text "Rebuild configuration"
pretty (Unread f) = text "Mark feed(s) as unread:" <+> pretty f
pretty (Run f) = text "Download new entries from feed(s):" <+> pretty f
pretty (Show f) = text "Show status for feed(s):" <+> pretty f
pretty ShowVersion = text "Show program version"
pretty (Subscribe f _) = text "Subscribe to feed:" <+> prettyURI f
pretty (Unsubscribe f) = text "Unsubscribe from feed(s):" <+> pretty f
defaultCommand :: Command
defaultCommand = Show Nothing
data CliOptions = CliOptions
{ optionCommand :: Command
, optionDyreMode :: Dyre.Mode
, optionLogLevel :: LogLevel
}
defaultOptions :: CliOptions
defaultOptions = CliOptions defaultCommand Dyre.defaultMode Info
parseOptions :: (MonadIO m) => m CliOptions
parseOptions = io $ customExecParser (prefs noBacktrack) (info parser $ progDesc "Convert items from RSS/Atom feeds to mails.")
where parser = helper <*> optional dyreMasterBinary *> optional dyreDebug *> cliOptions
cliOptions :: Parser CliOptions
cliOptions = CliOptions
<$> commands
<*> (vanillaFlag <|> forceReconfFlag <|> denyReconfFlag <|> pure Dyre.defaultMode)
<*> (verboseFlag <|> quietFlag <|> logLevel <|> pure Info)
commands :: Parser Command
commands = subparser $ mconcat
[ command "check" . info (Check <$> optional feedRefOption) $ progDesc "Check availability and validity of all feed sources currently configured, without writing any mail."
, command "import" . info (pure Import) $ progDesc "Import feeds list from an OPML descriptor (read from stdin)."
, command "read" . info (Read <$> optional feedRefOption) $ progDesc "Mark given feed as read."
, command "rebuild" . info (pure Rebuild) $ progDesc "Rebuild configuration file."
, command "run" . info (Run <$> optional feedRefOption) $ progDesc "Update list of feeds."
, command "show" . info (Show <$> optional feedRefOption) $ progDesc "List all feed sources currently configured, along with their status."
, command "subscribe" . info subscribeOptions $ progDesc "Subscribe to a feed."
, command "unread" . info (Unread <$> optional feedRefOption) $ progDesc "Mark given feed as unread."
, command "unsubscribe" . info unsubscribeOptions $ progDesc "Unsubscribe from a feed."
, command "version" . info (pure ShowVersion) $ progDesc "Print version."
]
vanillaFlag, forceReconfFlag, denyReconfFlag :: Parser Dyre.Mode
vanillaFlag = flag' Vanilla $ long "vanilla" <> short '1' <> help "Ignore custom configuration file."
forceReconfFlag = flag' ForceReconfiguration $ long "force-reconf" <> help "Recompile configuration file before starting the application."
denyReconfFlag = flag' IgnoreReconfiguration $ long "deny-reconf" <> help "Do not recompile configuration file even if it has changed."
dyreDebug :: Parser Bool
dyreDebug = switch $ long "dyre-debug" <> help "Use './cache/' as the cache directory and ./ as the configuration directory. Useful to debug the program."
dyreMasterBinary :: Parser String
dyreMasterBinary = strOption $ long "dyre-master-binary" <> metavar "PATH" <> hidden <> internal <> help "Internal flag used for dynamic reconfiguration."
verboseFlag, quietFlag, logLevel :: Parser LogLevel
verboseFlag = flag' Logger.Debug $ long "verbose" <> short 'v' <> help "Set log level to DEBUG."
quietFlag = flag' Logger.Error $ long "quiet" <> short 'q' <> help "Set log level to ERROR."
logLevel = option auto $ long "log-level" <> short 'l' <> metavar "LOG-LEVEL" <> value Info <> completeWith ["Debug", "Info", "Warning", "Error"] <> help "Set log level. Available values: Debug, Info, Warning, Error."
configLabelOption :: Parser Text
configLabelOption = option auto $ long "config" <> short 'C' <> metavar "CONFIG" <> help "Use the given configuration for all operations."
subscribeOptions, unsubscribeOptions :: Parser Command
subscribeOptions = Subscribe <$> uriArgument "URI to subscribe to." <*> optional configLabelOption
unsubscribeOptions = Unsubscribe <$> optional feedRefOption
uriReader :: ReadM URI
uriReader = eitherReader $ first show . parseURI laxURIParserOptions . encodeUtf8 . fromString
feedRefOption :: Parser FeedRef
feedRefOption = fmap FeedRef $ (Left <$> argument auto (metavar "ID")) <|> (Right <$> argument uriReader (metavar "URI"))
uriArgument :: String -> Parser URI
uriArgument helpText = argument uriReader $ metavar "URI" <> help helpText