{-# options_haddock prune #-}
-- |CLI Options, Internal
module Helic.Cli.Options where

import Options.Applicative (
  CommandFields,
  Mod,
  Parser,
  ReadM,
  command,
  help,
  hsubparser,
  info,
  long,
  option,
  progDesc,
  readerError,
  strOption,
  switch,
  )
import Options.Applicative.Types (readerAsk)
import Path (Abs, File, Path, parseAbsFile)

import Helic.Data.YankConfig (YankConfig (YankConfig))

data Conf =
  Conf {
    Conf -> Bool
verbose :: Bool,
    Conf -> Maybe (Path Abs File)
configFile :: Maybe (Path Abs File)
  }
  deriving stock (Conf -> Conf -> Bool
(Conf -> Conf -> Bool) -> (Conf -> Conf -> Bool) -> Eq Conf
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Conf -> Conf -> Bool
$c/= :: Conf -> Conf -> Bool
== :: Conf -> Conf -> Bool
$c== :: Conf -> Conf -> Bool
Eq, Int -> Conf -> ShowS
[Conf] -> ShowS
Conf -> String
(Int -> Conf -> ShowS)
-> (Conf -> String) -> ([Conf] -> ShowS) -> Show Conf
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Conf] -> ShowS
$cshowList :: [Conf] -> ShowS
show :: Conf -> String
$cshow :: Conf -> String
showsPrec :: Int -> Conf -> ShowS
$cshowsPrec :: Int -> Conf -> ShowS
Show)

data Command =
  Listen
  |
  Yank YankConfig
  deriving stock (Command -> Command -> Bool
(Command -> Command -> Bool)
-> (Command -> Command -> Bool) -> Eq Command
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Command -> Command -> Bool
$c/= :: Command -> Command -> Bool
== :: Command -> Command -> Bool
$c== :: Command -> Command -> Bool
Eq, Int -> Command -> ShowS
[Command] -> ShowS
Command -> String
(Int -> Command -> ShowS)
-> (Command -> String) -> ([Command] -> ShowS) -> Show Command
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Command] -> ShowS
$cshowList :: [Command] -> ShowS
show :: Command -> String
$cshow :: Command -> String
showsPrec :: Int -> Command -> ShowS
$cshowsPrec :: Int -> Command -> ShowS
Show)

filePathOption :: ReadM (Path Abs File)
filePathOption :: ReadM (Path Abs File)
filePathOption = do
  String
raw <- ReadM String
readerAsk
  (SomeException -> ReadM (Path Abs File))
-> (Path Abs File -> ReadM (Path Abs File))
-> Either SomeException (Path Abs File)
-> ReadM (Path Abs File)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (ReadM (Path Abs File) -> SomeException -> ReadM (Path Abs File)
forall a b. a -> b -> a
const (String -> ReadM (Path Abs File)
forall a. String -> ReadM a
readerError [exon|not an absolute file path: #{show raw}|])) Path Abs File -> ReadM (Path Abs File)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String -> Either SomeException (Path Abs File)
forall (m :: * -> *). MonadThrow m => String -> m (Path Abs File)
parseAbsFile String
raw)

confParser :: Parser Conf
confParser :: Parser Conf
confParser = do
  Bool
verbose <- Mod FlagFields Bool -> Parser Bool
switch (String -> Mod FlagFields Bool
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"verbose")
  Maybe (Path Abs File)
configFile <- Parser (Path Abs File) -> Parser (Maybe (Path Abs File))
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (ReadM (Path Abs File)
-> Mod OptionFields (Path Abs File) -> Parser (Path Abs File)
forall a. ReadM a -> Mod OptionFields a -> Parser a
option ReadM (Path Abs File)
filePathOption (String -> Mod OptionFields (Path Abs File)
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"config-file"))
  pure (Bool -> Maybe (Path Abs File) -> Conf
Conf Bool
verbose Maybe (Path Abs File)
configFile)

listenCommand :: Mod CommandFields Command
listenCommand :: Mod CommandFields Command
listenCommand =
  String -> ParserInfo Command -> Mod CommandFields Command
forall a. String -> ParserInfo a -> Mod CommandFields a
command String
"listen" (Parser Command -> InfoMod Command -> ParserInfo Command
forall a. Parser a -> InfoMod a -> ParserInfo a
info (Command -> Parser Command
forall (f :: * -> *) a. Applicative f => a -> f a
pure Command
Listen) (String -> InfoMod Command
forall a. String -> InfoMod a
progDesc String
"Run the daemon"))

yankParser :: Parser YankConfig
yankParser :: Parser YankConfig
yankParser =
  Maybe Text -> YankConfig
YankConfig (Maybe Text -> YankConfig)
-> Parser (Maybe Text) -> Parser YankConfig
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text -> Parser (Maybe Text)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Mod OptionFields Text -> Parser Text
forall s. IsString s => Mod OptionFields s -> Parser s
strOption (String -> Mod OptionFields Text
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"agent" Mod OptionFields Text
-> Mod OptionFields Text -> Mod OptionFields Text
forall a. Semigroup a => a -> a -> a
<> String -> Mod OptionFields Text
forall (f :: * -> *) a. String -> Mod f a
help String
"Source of the yank"))

yankCommand :: Mod CommandFields Command
yankCommand :: Mod CommandFields Command
yankCommand =
  String -> ParserInfo Command -> Mod CommandFields Command
forall a. String -> ParserInfo a -> Mod CommandFields a
command String
"yank" (YankConfig -> Command
Yank (YankConfig -> Command)
-> ParserInfo YankConfig -> ParserInfo Command
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser YankConfig -> InfoMod YankConfig -> ParserInfo YankConfig
forall a. Parser a -> InfoMod a -> ParserInfo a
info Parser YankConfig
yankParser (String -> InfoMod YankConfig
forall a. String -> InfoMod a
progDesc String
"Send stdin to the daemon"))

commands :: [Mod CommandFields Command]
commands :: [Mod CommandFields Command]
commands =
  [
    Item [Mod CommandFields Command]
Mod CommandFields Command
listenCommand,
    Item [Mod CommandFields Command]
Mod CommandFields Command
yankCommand
  ]

parser :: Parser (Conf, Maybe Command)
parser :: Parser (Conf, Maybe Command)
parser =
  (,) (Conf -> Maybe Command -> (Conf, Maybe Command))
-> Parser Conf -> Parser (Maybe Command -> (Conf, Maybe Command))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Conf
confParser Parser (Maybe Command -> (Conf, Maybe Command))
-> Parser (Maybe Command) -> Parser (Conf, Maybe Command)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Command -> Parser (Maybe Command)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Mod CommandFields Command -> Parser Command
forall a. Mod CommandFields a -> Parser a
hsubparser ([Mod CommandFields Command] -> Mod CommandFields Command
forall a. Monoid a => [a] -> a
mconcat [Mod CommandFields Command]
commands))