module Hledger.Cli.Main where
import Control.Monad
import Data.List
import Safe
import System.Console.CmdArgs.Explicit (modeHelp)
import System.Environment
import System.Exit
import System.Process
import Text.Printf
import Hledger (ensureJournalFileExists)
import Hledger.Cli.Add
import Hledger.Cli.Balance
import Hledger.Cli.Balancesheet
import Hledger.Cli.Cashflow
import Hledger.Cli.Histogram
import Hledger.Cli.Incomestatement
import Hledger.Cli.Print
import Hledger.Cli.Register
import Hledger.Cli.Stats
import Hledger.Cli.Options
import Hledger.Cli.Tests
import Hledger.Cli.Utils
import Hledger.Cli.Version
import Hledger.Utils
import Hledger.Reports
import Hledger.Data.Dates
main :: IO ()
main = do
args <- getArgs
let
args' = moveFlagsAfterCommand args
isFlag = ("-" `isPrefixOf`)
isNonEmptyNonFlag s = not (isFlag s) && not (null s)
rawcmd = headDef "" $ takeWhile isNonEmptyNonFlag args'
isNullCommand = null rawcmd
(argsbeforecmd, argsaftercmd') = break (==rawcmd) args
argsaftercmd = drop 1 argsaftercmd'
when (debugLevel > 0) $ do
printf "running: %s\n" prognameandversion
printf "raw args: %s\n" (show args)
printf "raw args rearranged for cmdargs: %s\n" (show args')
printf "raw command might be: %s\n" (show rawcmd)
printf "raw args before command: %s\n" (show argsbeforecmd)
printf "raw args after command: %s\n" (show argsaftercmd)
addons <- getHledgerAddonCommands
opts <- argsToCliOpts args addons
let
cmd = command_ opts
isInternalCommand = not (null cmd) && not (cmd `elem` addons)
isExternalCommand = not (null cmd) && cmd `elem` addons
isBadCommand = not (null rawcmd) && null cmd
hasHelp args = any (`elem` args) ["--help","-h","-?"]
hasVersion = ("--version" `elem`)
mainmode' = mainmode addons
generalHelp = putStr $ showModeHelp mainmode'
version = putStrLn prognameandversion
badCommandError = error' ("command "++rawcmd++" is not recognized, run with no command to see a list") >> exitFailure
f `orShowHelp` mode = if hasHelp args then putStr (showModeHelp mode) else f
when (debug_ opts > 0) $ do
putStrLn $ "processed opts:\n" ++ ppShow opts
putStrLn $ "command matched: " ++ show cmd
putStrLn $ "isNullCommand: " ++ show isNullCommand
putStrLn $ "isInternalCommand: " ++ show isInternalCommand
putStrLn $ "isExternalCommand: " ++ show isExternalCommand
putStrLn $ "isBadCommand: " ++ show isBadCommand
d <- getCurrentDay
putStrLn $ "date span from opts: " ++ (show $ dateSpanFromOpts d $ reportopts_ opts)
putStrLn $ "interval from opts: " ++ (show $ intervalFromOpts $ reportopts_ opts)
putStrLn $ "query from opts & args: " ++ (show $ queryFromOpts d $ reportopts_ opts)
let
dbg s = if debug_ opts > 0 then trace s else id
runHledgerCommand
| hasHelp argsbeforecmd = dbg "--help before command, showing general help" generalHelp
| not (hasHelp argsaftercmd) && (hasVersion argsbeforecmd || (hasVersion argsaftercmd && isInternalCommand))
= version
| isNullCommand = dbg "no command, showing general help" generalHelp
| isBadCommand = badCommandError
| cmd == "activity" = withJournalDo opts histogram `orShowHelp` activitymode
| cmd == "add" = (journalFilePathFromOpts opts >>= ensureJournalFileExists >> withJournalDo opts add) `orShowHelp` addmode
| cmd == "balance" = withJournalDo opts balance `orShowHelp` balancemode
| cmd == "balancesheet" = withJournalDo opts balancesheet `orShowHelp` balancesheetmode
| cmd == "cashflow" = withJournalDo opts cashflow `orShowHelp` cashflowmode
| cmd == "incomestatement" = withJournalDo opts incomestatement `orShowHelp` incomestatementmode
| cmd == "print" = withJournalDo opts print' `orShowHelp` printmode
| cmd == "register" = withJournalDo opts register `orShowHelp` registermode
| cmd == "stats" = withJournalDo opts stats `orShowHelp` statsmode
| cmd == "test" = test' opts `orShowHelp` testmode
| isExternalCommand = do
let shellcmd = printf "%s-%s %s" progname cmd (unwords' argsaftercmd)
when (debug_ opts > 0) $ do
printf "external command selected: %s\n" cmd
printf "external command arguments: %s\n" (show argsaftercmd)
printf "running shell command: %s\n" (show shellcmd)
system shellcmd >>= exitWith
| cmd == "convert" = error' (modeHelp convertmode) >> exitFailure
| otherwise = optserror ("could not understand the arguments "++show args) >> exitFailure
runHledgerCommand