hascard-0.1.4.0: app/Main.hs
{-# LANGUAGE TemplateHaskell #-}
module Main where
import UI
import Control.Exception (displayException, try)
import Control.Monad (void, when)
import Data.Functor (($>))
import Data.Version (showVersion)
import Lens.Micro.Platform
import Paths_hascard (version)
import Parser
import Options.Applicative
import System.Directory (makeAbsolute)
import System.FilePath (takeExtension)
import System.Process (runCommand)
import System.Random.MWC (createSystemRandom, GenIO)
data Opts = Opts
{ _optFile :: Maybe String
, _optSubset :: Int
, _optShuffle :: Bool
, _optVersion :: Bool
}
makeLenses ''Opts
main :: IO ()
main = do
useEscapeCode <- getUseEscapeCode
when useEscapeCode $ void (runCommand "echo -n \\\\e[5 q")
options <- execParser optsWithHelp
if options ^. optVersion
then putStrLn (showVersion version)
else run options
opts :: Parser Opts
opts = Opts
<$> optional (argument str (metavar "FILE" <> help "A .txt file containing flashcards"))
<*> option auto (long "amount" <> short 'a' <> metavar "n" <> help "Use the first n cards in the deck (most useful combined with shuffle)" <> value (-1))
<*> switch (long "shuffle" <> short 's' <> help "Randomize card order")
<*> switch (long "version" <> short 'v' <> help "Show version number")
optsWithHelp :: ParserInfo Opts
optsWithHelp = info (opts <**> helper) $
fullDesc <> progDesc "Run the normal application without argument, or run it directly on a deck of flashcards by providing a text file."
<> header "Hascard - a TUI for reviewing notes"
nothingIf :: (a -> Bool) -> a -> Maybe a
nothingIf p a
| p a = Nothing
| otherwise = Just a
run :: Opts -> IO ()
run opts = run' (opts ^. optFile)
where
mkGlobalState gen = GlobalState {_mwc=gen, _doShuffle=opts^.optShuffle, _subset=nothingIf (<0) (opts^.optSubset) }
run' Nothing = createSystemRandom >>= runBrickFlashcards . mkGlobalState
run' (Just file) = do
let filepath =
case takeExtension file of
"" -> Just $ file <> ".txt"
".txt" -> Just file
_ -> Nothing
case filepath of
Nothing -> putStrLn "Incorrect file type, provide a .txt file"
Just textfile -> do
valOrExc <- try (readFile textfile) :: IO (Either IOError String)
case valOrExc of
Left exc -> putStrLn (displayException exc)
Right val -> case parseCards val of
Left parseError -> print parseError
Right result ->
do gen <- createSystemRandom
(makeAbsolute textfile >>= addRecent) *> runCardsWithOptions (mkGlobalState gen) result $> ()