{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} module Main where import Parsing ( parseStartYear ) import Path ( reldir ) import qualified Turtle hiding (switch) import Prelude hiding (putStrLn) import Options.Applicative ( auto, optional, Alternative(many, (<|>)), Parser, flag', help, long, metavar, option, short, str, switch ) import Hledger.Flow.PathHelpers (TurtlePath) import Hledger.Flow.Common ( hledgerInfoFromPath ) import Hledger.Flow.Internals (versionInfo, systemInfo) import Hledger.Flow.BaseDir ( determineBaseDir ) import qualified Hledger.Flow.RuntimeOptions as RT import Hledger.Flow.Reports ( generateReports ) import Hledger.Flow.Import.CSVImport ( importCSVs ) import qualified Data.Text.IO as T data ImportParams = ImportParams { maybeImportBaseDir :: Maybe TurtlePath , importStartYear :: Maybe String , onlyNewFiles :: Bool } deriving (Show) newtype ReportParams = ReportParams {maybeReportBaseDir :: Maybe TurtlePath} deriving Show data Command = Import ImportParams | Report ReportParams deriving (Show) data MainParams = MainParams { verbosity :: Int , hledgerPathOpt :: Maybe TurtlePath , showOpts :: Bool , batchSize :: Maybe Int , sequential :: Bool } deriving (Show) data BaseCommand = Version | Command { mainParams :: MainParams, command :: Command } deriving (Show) main :: IO () main = do cmd <- Turtle.options "An hledger workflow focusing on automated statement import and classification:\nhttps://github.com/apauley/hledger-flow#readme" baseCommandParser case cmd of Version -> do sysInfo <- systemInfo T.putStrLn $ versionInfo sysInfo Command mainParams' (Import subParams) -> toRuntimeOptionsImport mainParams' subParams >>= importCSVs Command mainParams' (Report subParams) -> toRuntimeOptionsReport mainParams' subParams >>= generateReports defaultBatchSize :: Int defaultBatchSize = 200 determineBatchSize :: MainParams -> IO Int determineBatchSize mainParams' = case (batchSize mainParams') of Nothing -> return defaultBatchSize Just size -> return size toRuntimeOptionsImport :: MainParams -> ImportParams -> IO RT.RuntimeOptions toRuntimeOptionsImport mainParams' subParams' = do startYear <- parseStartYear $ importStartYear subParams' let maybeBD = maybeImportBaseDir subParams' :: Maybe TurtlePath (bd, runDir) <- determineBaseDir maybeBD hli <- hledgerInfoFromPath $ hledgerPathOpt mainParams' size <- determineBatchSize mainParams' sysInfo <- systemInfo return RT.RuntimeOptions { RT.baseDir = bd , RT.importRunDir = runDir , RT.importStartYear = startYear , RT.onlyNewFiles = onlyNewFiles subParams' , RT.hfVersion = versionInfo sysInfo , RT.hledgerInfo = hli , RT.sysInfo = sysInfo , RT.verbose = verbosity mainParams' > 0 , RT.showOptions = showOpts mainParams' , RT.sequential = sequential mainParams' , RT.batchSize = size } toRuntimeOptionsReport :: MainParams -> ReportParams -> IO RT.RuntimeOptions toRuntimeOptionsReport mainParams' subParams' = do let maybeBD = maybeReportBaseDir subParams' :: Maybe TurtlePath (bd, _) <- determineBaseDir maybeBD hli <- hledgerInfoFromPath $ hledgerPathOpt mainParams' size <- determineBatchSize mainParams' sysInfo <- systemInfo return RT.RuntimeOptions { RT.baseDir = bd , RT.importRunDir = [reldir|.|] , RT.importStartYear = Nothing , RT.onlyNewFiles = False , RT.hfVersion = versionInfo sysInfo , RT.hledgerInfo = hli , RT.sysInfo = sysInfo , RT.verbose = verbosity mainParams' > 0 , RT.showOptions = showOpts mainParams' , RT.sequential = sequential mainParams' , RT.batchSize = size } baseCommandParser :: Parser BaseCommand baseCommandParser = (Command <$> verboseParser <*> commandParser) <|> flag' Version (long "version" <> short 'V' <> help "Display version information") commandParser :: Parser Command commandParser = fmap Import (Turtle.subcommand "import" "Uses hledger with your own rules and/or scripts to convert electronic statements into categorised journal files" subcommandParserImport) <|> fmap Report (Turtle.subcommand "report" "Generate Reports" subcommandParserReport) verboseParser :: Parser MainParams verboseParser = MainParams <$> (length <$> many (flag' () (long "verbose" <> short 'v' <> help "Print more verbose output"))) <*> optional (Turtle.optPath "hledger-path" 'H' "The full path to an hledger executable") <*> switch (long "show-options" <> help "Print the options this program will run with") <*> optional (option auto (long "batch-size" <> metavar "SIZE" <> help ("Parallel processing of files are done in batches of the specified size. Default: " <> show defaultBatchSize <> ". Ignored during sequential processing."))) <*> switch (long "sequential" <> help "Disable parallel processing") subcommandParserImport :: Parser ImportParams subcommandParserImport = ImportParams <$> optional (Turtle.argPath "dir" "The directory to import. Use the base directory for a full import or a sub-directory for a partial import. Defaults to the current directory.") <*> optional (option str (long "start-year" <> metavar "YEAR" <> help "Import only from the specified year and onwards, ignoring previous years. By default all available years are imported. Valid values include a 4-digit year or 'current' for the current year")) <*> switch (long "new-files-only" <> help "Don't regenerate transaction files if they are already present. This applies to hledger journal files as well as files produced by the preprocess and construct scripts.") subcommandParserReport :: Parser ReportParams subcommandParserReport = ReportParams <$> optional (Turtle.argPath "basedir" "The hledger-flow base directory")