{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE StandaloneDeriving #-} module Imm.Options where -- {{{ Imports 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 -- }}} -- | Available commands. 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 -- | Available commandline options. data CliOptions = CliOptions { optionCommand :: Command , optionDyreMode :: Dyre.Mode , optionLogLevel :: LogLevel } -- deriving instance Eq CliOptions defaultOptions :: CliOptions defaultOptions = CliOptions defaultCommand Dyre.defaultMode Info -- instance Pretty CliOptions where -- pretty opts = text "ACTION" <> equals <> $ opts^.command_ -- , ("RECONFIGURATION_MODE=" ++) . show $ opts^.dyreMode_ -- ] -- ++ catMaybes [("CONFIG=" ++) <$> opts^.configurationLabel_] 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." ] -- {{{ Dynamic reconfiguration options 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." -- }}} -- {{{ Log level options 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." -- }}} -- {{{ Other options 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 -- }}} -- {{{ Util 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 -- }}}