module Arguments ( Arguments(..) , get ) where import Data.Monoid ((<>)) import Data.Version (showVersion) import Control.Applicative ((<|>), (<**>), optional) import Options.Applicative (Parser, ReadM, argument, auto, eitherReader, execParser, flag', fullDesc, header, help, helper, info, long, metavar, short, str, value) import qualified Options.Applicative as Optparse (option) import qualified Paths_hablo as Hablo (version) import System.FilePath (dropTrailingPathSeparator, isValid) data Arguments = BlogConfig { sourceDir :: FilePath , articlesPath :: FilePath , bannerPath :: Maybe FilePath , cardImage :: Maybe FilePath , commentsAt :: Maybe String , favicon :: Maybe FilePath , headPath :: Maybe FilePath , name :: Maybe String , pagesPath :: Maybe FilePath , previewArticlesCount :: Int , previewLinesCount :: Int , remarkableConfig :: Maybe FilePath , wording :: Maybe FilePath } | Version option :: ReadM a -> Char -> String -> String -> String -> Parser (Maybe a) option readM aShort aLong aMetavar aHelpMessage = Optparse.option (optional readM) ( metavar aMetavar <> value Nothing <> short aShort <> long aLong <> help aHelpMessage ) blogConfig :: Parser Arguments blogConfig = BlogConfig <$> argument filePath (value "." <> metavar "INPUT_DIR") <*> Optparse.option filePath ( metavar "DIRECTORY" <> value "articles" <> short 'a' <> long "articles" <> help "relative path to the directory containing the articles within INPUT_DIR" ) <*> option filePath 'b' "banner" "FILE" "path to the file to use for the blog's banner" <*> option filePath 'c' "card-image" "FILE" "relative path to the image to use for the blog's card" <*> option filePath 'C' "comments-at" "URL" "url of the instance where comments are stored" <*> option filePath 'f' "favicon" "FILE" "path to the image to use for the blog's favicon" <*> option filePath 'H' "head" "FILE" "path to the file to add in the blog's head" <*> option str 'n' "name" "BLOG_NAME" "name of the blog" <*> option filePath 'p' "pages" "DIRECTORY" "relative path to the directory containing the pages within INPUT_DIR" <*> Optparse.option auto ( metavar "INTEGER" <> value 3 <> short 'A' <> long "preview-articles" <> help "number of articles listed on the page of each category" ) <*> Optparse.option auto ( metavar "INTEGER" <> value 10 <> short 'L' <> long "preview-lines" <> help "number of lines to display in articles preview" ) <*> option filePath 'r' "remarkable-config" "FILE" "path to a file containing a custom RemarkableJS configuration" <*> option filePath 'w' "wording" "FILE" "path to the file containing the wording to use" version :: Parser Arguments version = flag' Version ( long "version" <> short 'v' <> help "print the version number" ) arguments :: Parser Arguments arguments = blogConfig <|> version filePath :: ReadM FilePath filePath = eitherReader $ \path -> if isValid path then Right $ dropTrailingPathSeparator path else Left "This string doesn't represent a valid path" get :: IO Arguments get = do execParser $ info (arguments <**> helper) (fullDesc <> header ("Hablo v" ++ showVersion Hablo.version))