{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE RecordWildCards #-}

module Emanote.CLI (
  Cli (..),
  Cmd (..),
  parseCli,
  cliParser,
) where

import Data.Text qualified as T
import Data.Version (showVersion)
import Ema.CLI qualified
import Options.Applicative hiding (action)
import Paths_emanote qualified
import Relude
import UnliftIO.Directory (getCurrentDirectory)

data Cli = Cli
  { Cli -> NonEmpty String
layers :: NonEmpty FilePath
  , Cli -> Bool
allowBrokenLinks :: Bool
  , Cli -> Cmd
cmd :: Cmd
  }

data Cmd
  = Cmd_Ema Ema.CLI.Cli
  | Cmd_Export

cliParser :: FilePath -> Parser Cli
cliParser :: String -> Parser Cli
cliParser String
cwd = do
  NonEmpty String
layers <- NonEmpty String -> Parser (NonEmpty String)
pathList (forall x. One x => OneItem x -> x
one String
cwd)
  Bool
allowBrokenLinks <- Mod FlagFields Bool -> Parser Bool
switch (forall (f :: Type -> Type) a. HasName f => String -> Mod f a
long String
"allow-broken-links" forall a. Semigroup a => a -> a -> a
<> forall (f :: Type -> Type) a. String -> Mod f a
help String
"Report but do not fail on broken links")
  Cmd
cmd <-
    forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap Cli -> Cmd
Cmd_Ema Parser Cli
Ema.CLI.cliParser
      forall (f :: Type -> Type) a. Alternative f => f a -> f a -> f a
<|> forall a. Mod CommandFields a -> Parser a
subparser (forall a. String -> ParserInfo a -> Mod CommandFields a
command String
"export" (forall a. Parser a -> InfoMod a -> ParserInfo a
info (forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Cmd
Cmd_Export) (forall a. String -> InfoMod a
progDesc String
"Export metadata JSON")))
  pure Cli {Bool
NonEmpty String
Cmd
cmd :: Cmd
allowBrokenLinks :: Bool
layers :: NonEmpty String
cmd :: Cmd
allowBrokenLinks :: Bool
layers :: NonEmpty String
..}
  where
    pathList :: NonEmpty String -> Parser (NonEmpty String)
pathList NonEmpty String
defaultPath = do
      forall a. ReadM a -> Mod OptionFields a -> Parser a
option ReadM (NonEmpty String)
pathListReader forall a b. (a -> b) -> a -> b
$
        forall a. Monoid a => [a] -> a
mconcat
          [ forall (f :: Type -> Type) a. HasName f => String -> Mod f a
long String
"layers"
          , forall (f :: Type -> Type) a. HasName f => Char -> Mod f a
short Char
'L'
          , forall (f :: Type -> Type) a. HasMetavar f => String -> Mod f a
metavar String
"LAYERS"
          , forall (f :: Type -> Type) a. HasValue f => a -> Mod f a
value NonEmpty String
defaultPath
          , forall (f :: Type -> Type) a. String -> Mod f a
help String
"List of (semicolon delimited) notebook folders to 'union mount', with the left-side folders being overlaid on top of the right-side ones. The default layer is implicitly included at the end of this list."
          ]
    pathListReader :: ReadM (NonEmpty FilePath)
    pathListReader :: ReadM (NonEmpty String)
pathListReader =
      forall a. (String -> Maybe a) -> ReadM a
maybeReader forall a b. (a -> b) -> a -> b
$ \String
paths ->
        forall a. [a] -> Maybe (NonEmpty a)
nonEmpty forall a b. (a -> b) -> a -> b
$ forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. ToString a => a -> String
toString forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> Text -> [Text]
T.split (forall a. Eq a => a -> a -> Bool
== Char
';') forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToText a => a -> Text
toText forall a b. (a -> b) -> a -> b
$ String
paths

parseCli' :: FilePath -> ParserInfo Cli
parseCli' :: String -> ParserInfo Cli
parseCli' String
cwd =
  forall a. Parser a -> InfoMod a -> ParserInfo a
info
    (forall {a}. Parser (a -> a)
versionOption forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> String -> Parser Cli
cliParser String
cwd forall (f :: Type -> Type) a b.
Applicative f =>
f a -> f (a -> b) -> f b
<**> forall {a}. Parser (a -> a)
helper)
    ( forall a. InfoMod a
fullDesc
        forall a. Semigroup a => a -> a -> a
<> forall a. String -> InfoMod a
progDesc String
"Emanote - A spiritual successor to Neuron"
        forall a. Semigroup a => a -> a -> a
<> forall a. String -> InfoMod a
header String
"Emanote"
    )
  where
    versionOption :: Parser (a -> a)
versionOption =
      forall a. String -> Mod OptionFields (a -> a) -> Parser (a -> a)
infoOption
        (Version -> String
showVersion Version
Paths_emanote.version)
        (forall (f :: Type -> Type) a. HasName f => String -> Mod f a
long String
"version" forall a. Semigroup a => a -> a -> a
<> forall (f :: Type -> Type) a. String -> Mod f a
help String
"Show version")

parseCli :: IO Cli
parseCli :: IO Cli
parseCli =
  forall a. ParserInfo a -> IO a
execParser forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ParserInfo Cli
parseCli' forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: Type -> Type). MonadIO m => m String
getCurrentDirectory