helic-0.3.2.0: lib/Helic/Cli.hs
{-# options_haddock prune #-}
-- |CLI, Internal
module Helic.Cli where
import Options.Applicative (customExecParser, fullDesc, header, helper, info, prefs, showHelpOnEmpty, showHelpOnError)
import Polysemy.Chronos (interpretTimeChronos)
import qualified Polysemy.Conc as Conc
import Polysemy.Conc (
interpretCritical,
interpretInterrupt,
interpretRace,
)
import Polysemy.Error (errorToIOFinal)
import Polysemy.Log (
Log,
LogEntry,
LogMessage,
Logger,
Severity (Info, Trace),
formatLogEntry,
interceptDataLogConc,
interpretDataLogStdoutWith,
interpretLogDataLog,
setLogLevel,
)
import qualified Polysemy.Log.Data.DataLog as DataLog
import Polysemy.Time (GhcTime, MilliSeconds (MilliSeconds), interpretTimeGhc)
import System.IO (hLookAhead)
import Helic.App (AppStack, IOStack, listApp, listenApp, loadApp, yankApp)
import Helic.Cli.Options (Command (List, Listen, Load, Yank), Conf (Conf), parser)
import Helic.Config.File (findFileConfig)
import qualified Helic.Data.Config as Config
import Helic.Data.Config (Config)
import Helic.Data.YankConfig (YankConfig (YankConfig))
logError ::
Members [Logger, GhcTime, Final IO] r =>
Sem (Error Text : r) () ->
Sem r ()
logError =
traverseLeft DataLog.error <=< errorToIOFinal
interpretLog ::
Maybe Bool ->
InterpreterFor Log IOStack
interpretLog (fromMaybe False -> verbose) =
setLogLevel (if verbose then Just Trace else Just Info) . interpretLogDataLog
runIO ::
Sem IOStack () ->
IO ()
runIO =
runFinal .
embedToFinal .
resourceToIOFinal .
asyncToIOFinal .
interpretRace .
interpretTimeGhc .
interpretTimeChronos .
interpretCritical .
interpretInterrupt .
interpretDataLogStdoutWith formatLogEntry .
interceptDataLogConc @(LogEntry LogMessage) 64 .
logError
runCommand :: Config -> Command -> Sem AppStack ()
runCommand config = \case
Listen ->
listenApp config
Yank yankConf ->
yankApp config yankConf
List showConf ->
listApp config showConf
Load loadConf ->
loadApp config loadConf
defaultCommand :: Sem IOStack Command
defaultCommand = do
Conc.timeout_ (pure Nothing) (MilliSeconds 100) (Just <$> tryAny (hLookAhead stdin)) <&> \case
Just (Right _) -> Yank (YankConfig (Just "cli"))
_ -> Listen
withCliOptions :: Conf -> Maybe Command -> IO ()
withCliOptions (Conf cliVerbose file) cmd =
runIO do
config <- interpretLog cliVerbose (findFileConfig file)
cmd' <- maybe defaultCommand pure cmd
interpretLog (cliVerbose <|> Config.verbose config) (runCommand config cmd')
app :: IO ()
app = do
(conf, cmd) <- customExecParser parserPrefs (info (parser <**> helper) desc)
withCliOptions conf cmd
where
parserPrefs =
prefs (showHelpOnEmpty <> showHelpOnError)
desc =
fullDesc <> header "Helic is a clipboard synchronization tool."