{-# options_haddock prune #-}

-- |CLI Options, Internal
module Helic.Cli.Options where

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

import Helic.Data.ListConfig (ListConfig (ListConfig))
import Helic.Data.LoadConfig (LoadConfig (LoadConfig))
import qualified Helic.Data.YankConfig
import Helic.Data.YankConfig (YankConfig (YankConfig))

data Conf =
  Conf {
    Conf -> Maybe Bool
verbose :: Maybe Bool,
    Conf -> Maybe (Path Abs File)
configFile :: Maybe (Path Abs File)
  }
  deriving stock (Conf -> Conf -> Bool
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
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
  |
  List ListConfig
  |
  Load LoadConfig
  deriving stock (Command -> Command -> Bool
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
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
  forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall a b. a -> b -> a
const (forall a. String -> ReadM a
readerError [exon|not an absolute file path: #{show raw}|])) forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall (m :: * -> *). MonadThrow m => String -> m (Path Abs File)
parseAbsFile String
raw)

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

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

yankParser :: Parser YankConfig
yankParser :: Parser YankConfig
yankParser = do
  Maybe Text
agent <- forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (forall s. IsString s => Mod OptionFields s -> Parser s
strOption (forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"agent" forall a. Semigroup a => a -> a -> a
<> forall (f :: * -> *) a. String -> Mod f a
help String
"Source of the yank"))
  Maybe Text
text <- forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (forall s. IsString s => Mod OptionFields s -> Parser s
strOption (forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"text" forall a. Semigroup a => a -> a -> a
<> forall (f :: * -> *) a. String -> Mod f a
help String
"Yank text, uses stdin if not specified"))
  pure YankConfig {Maybe Text
$sel:text:YankConfig :: Maybe Text
$sel:agent:YankConfig :: Maybe Text
text :: Maybe Text
agent :: Maybe Text
..}

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

listParser :: Parser ListConfig
listParser :: Parser ListConfig
listParser =
  Maybe Int -> ListConfig
ListConfig forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (forall a. ReadM a -> Mod ArgumentFields a -> Parser a
argument forall a. Read a => ReadM a
auto (forall (f :: * -> *) a. String -> Mod f a
help String
"Maximum number of events to list"))

listCommand :: Mod CommandFields Command
listCommand :: Mod CommandFields Command
listCommand =
  forall a. String -> ParserInfo a -> Mod CommandFields a
command String
"list" (ListConfig -> Command
List forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Parser a -> InfoMod a -> ParserInfo a
info Parser ListConfig
listParser (forall a. String -> InfoMod a
progDesc String
"List clipboard events"))

loadParser :: Parser LoadConfig
loadParser :: Parser LoadConfig
loadParser =
  Int -> LoadConfig
LoadConfig forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. ReadM a -> Mod ArgumentFields a -> Parser a
argument forall a. Read a => ReadM a
auto (forall (f :: * -> *) a. String -> Mod f a
help String
"Index of the event")

loadCommand :: Mod CommandFields Command
loadCommand :: Mod CommandFields Command
loadCommand =
  forall a. String -> ParserInfo a -> Mod CommandFields a
command String
"load" (LoadConfig -> Command
Load forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Parser a -> InfoMod a -> ParserInfo a
info Parser LoadConfig
loadParser (forall a. String -> InfoMod a
progDesc String
"Load a history event"))

commands :: [Mod CommandFields Command]
commands :: [Mod CommandFields Command]
commands =
  [
    Mod CommandFields Command
listenCommand,
    Mod CommandFields Command
yankCommand,
    Mod CommandFields Command
listCommand,
    Mod CommandFields Command
loadCommand
  ]

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