life-sync-1.1.0.0: src/Life/Cli.hs
{-# LANGUAGE ApplicativeDo #-}
{- |
Copyright: (c) 2017-2020 Kowainik
SPDX-License-Identifier: MPL-2.0
Maintainer: Kowainik <xrom.xkov@gmail.com>
Command line options for @life@.
-}
module Life.Cli
( LifeCommand (..)
, PathOptions (..)
, PullOptions (..)
, parseCommand
) where
import Options.Applicative (Parser, ParserInfo, command, execParser, fullDesc, help, helper, info,
long, metavar, progDesc, short, strOption, subparser)
import Life.Core (LifePath (..), Owner (..))
-- | Commands to execute
data LifeCommand
= Init (Maybe Owner)
| Add PathOptions
| Remove PathOptions
| Push
| Pull PullOptions
deriving stock (Show)
---------------------------------------------------------------------------
-- Boilerplate
----------------------------------------------------------------------------
commandParser :: Parser LifeCommand
commandParser = subparser $
command "init"
(info (helper <*> fmap Init (optional ownerParser))
(fullDesc <> progDesc "Initialize GitHub repository named 'dotfiles' if you don't have one."))
<> command "add"
(info (helper <*> fmap Add pathOptionsParser)
(fullDesc <> progDesc "Add file or directory to the life configuration."))
<> command "remove"
(info (helper <*> fmap Remove pathOptionsParser)
(fullDesc <> progDesc "Remove file or directory from the life configuration."))
<> command "push"
(info (helper <*> pure Push)
(fullDesc <> progDesc "Updates GitHub repository from local state and push the latest version."))
<> command "pull"
(info (helper <*> fmap Pull pullOptionsParser)
(fullDesc <> progDesc "Updates local state of '.life' and 'dotfiles' from GitHub repository."))
optionsInfo :: ParserInfo LifeCommand
optionsInfo = info
(helper <*> commandParser)
(fullDesc <> progDesc "life-sync synchronize your personal configs")
parseCommand :: IO LifeCommand
parseCommand = execParser optionsInfo
ownerParser :: Parser Owner
ownerParser = fmap Owner
$ strOption
$ metavar "OWNER"
<> help "Your github user name"
----------------------------------------------------------------------------
-- life pull
----------------------------------------------------------------------------
data PullOptions = PullOptions
{ pullOptionsOwner :: Maybe Owner
, pullOptionsNoFiles :: [FilePath]
, pullOptionsNoDirs :: [FilePath]
} deriving stock (Show)
pullOptionsParser :: Parser PullOptions
pullOptionsParser = do
pullOptionsOwner <- optional ownerParser
-- TODO: reuse LifePath parser here?...
pullOptionsNoFiles <- many $ strOption
$ metavar "FILE_PATH"
<> long "no-file"
<> short 'f'
<> help "Excluding these specific files from copying"
pullOptionsNoDirs <- many $ strOption
$ metavar "FILE_PATH"
<> long "no-dir"
<> short 'd'
<> help "Excluding these specific directories from copying"
pure PullOptions{..}
----------------------------------------------------------------------------
-- life add and remove
----------------------------------------------------------------------------
newtype PathOptions = PathOptions
{ pathOptionsPath :: LifePath
} deriving stock (Show)
pathOptionsParser :: Parser PathOptions
pathOptionsParser = do
pathOptionsPath <- fileParser <|> dirParser
pure PathOptions{..}
where
fileParser :: Parser LifePath
fileParser = File <$> strOption
( metavar "FILE_PATH"
<> long "file"
<> short 'f'
)
dirParser :: Parser LifePath
dirParser = Dir <$> strOption
( metavar "DIRECTORY_PATH"
<> long "dir"
<> short 'd'
)