1 {-|
    2 hledger - a ledger-compatible accounting tool.
    3 Copyright (c) 2007-2011 Simon Michael <simon@joyful.com>
    4 Released under GPL version 3 or later.
    5 
    6 hledger is a partial haskell clone of John Wiegley's "ledger".  It
    7 generates ledger-compatible register & balance reports from a plain text
    8 journal, and demonstrates a functional implementation of ledger.
    9 For more information, see http:\/\/hledger.org .
   10 
   11 This module provides the main function for the hledger command-line
   12 executable. It is exposed here so that it can be imported by eg benchmark
   13 scripts.
   14 
   15 You can use the command line:
   16 
   17 > $ hledger --help
   18 
   19 or ghci:
   20 
   21 > $ ghci hledger
   22 > > j <- readJournalFile "data/sample.journal"
   23 > > register [] ["income","expenses"] j
   24 > 2008/01/01 income               income:salary                   $-1          $-1
   25 > 2008/06/01 gift                 income:gifts                    $-1          $-2
   26 > 2008/06/03 eat & shop           expenses:food                    $1          $-1
   27 >                                 expenses:supplies                $1            0
   28 > > balance [Depth "1"] [] l
   29 >                  $-1  assets
   30 >                   $2  expenses
   31 >                  $-2  income
   32 >                   $1  liabilities
   33 > > l <- myLedger
   34 > > t <- myTimelog
   35 
   36 See "Hledger.Data.Ledger" for more examples.
   37 
   38 -}
   39 
   40 module Hledger.Cli.Main where
   41 
   42 import Control.Monad
   43 import Data.List
   44 import Safe
   45 import System.Environment
   46 import System.Exit
   47 import System.Process
   48 import Text.Printf
   49 
   50 import Hledger.Cli.Add
   51 import Hledger.Cli.Balance
   52 import Hledger.Cli.Convert
   53 import Hledger.Cli.Histogram
   54 import Hledger.Cli.Print
   55 import Hledger.Cli.Register
   56 import Hledger.Cli.Stats
   57 import Hledger.Cli.Options
   58 import Hledger.Cli.Tests
   59 import Hledger.Cli.Utils
   60 import Hledger.Cli.Version
   61 import Hledger.Utils
   62 
   63 main :: IO ()
   64 main = do
   65   args <- getArgs
   66   addons <- getHledgerAddonCommands
   67   opts <- getHledgerCliOpts addons
   68   when (debug_ opts) $ printf "%s\n" progversion >> printf "opts: %s\n" (show opts)
   69   run' opts addons args
   70     where
   71       run' opts@CliOpts{command_=cmd} addons args
   72        | "version" `in_` (rawopts_ opts)                 = putStrLn progversion
   73        | "binary-filename" `in_` (rawopts_ opts)         = putStrLn $ binaryfilename progname
   74        | null cmd                                        = putStr $ showModeHelp mainmode'
   75        | cmd `isPrefixOf` "add"                          = showModeHelpOr addmode      $ withJournalDo opts add
   76        | cmd `isPrefixOf` "convert"                      = showModeHelpOr convertmode  $ convert opts
   77        | cmd `isPrefixOf` "test"                         = showModeHelpOr testmode     $ runtests opts
   78        | any (cmd `isPrefixOf`) ["accounts","balance"]   = showModeHelpOr accountsmode $ withJournalDo opts balance
   79        | any (cmd `isPrefixOf`) ["entries","print"]      = showModeHelpOr entriesmode  $ withJournalDo opts print'
   80        | any (cmd `isPrefixOf`) ["postings","register"]  = showModeHelpOr postingsmode $ withJournalDo opts register
   81        | any (cmd `isPrefixOf`) ["activity","histogram"] = showModeHelpOr activitymode $ withJournalDo opts histogram
   82        | cmd `isPrefixOf` "stats"                        = showModeHelpOr statsmode    $ withJournalDo opts stats
   83        | not (null matchedaddon)                           = system shellcmd >>= exitWith
   84        | otherwise                                       = optserror ("command "++cmd++" is not recognized") >> exitFailure
   85        where
   86         mainmode' = mainmode addons
   87         showModeHelpOr mode f | "help" `in_` (rawopts_ opts) = putStr $ showModeHelp mode
   88                               | otherwise = f
   89         matchedaddon = headDef "" $ filter (cmd `isPrefixOf`) addons
   90         shellcmd = printf "%s-%s %s" progname matchedaddon (unwords' args)
   91 
   92 {- tests:
   93 
   94 hledger -> main help
   95 hledger --help -> main help
   96 hledger --help command -> command help
   97 hledger command --help -> command help
   98 hledger badcommand -> unrecognized command, try --help (non-zero exit)
   99 hledger badcommand --help -> main help
  100 hledger --help badcommand -> main help
  101 hledger --mainflag command -> works
  102 hledger command --mainflag -> works
  103 hledger command --commandflag -> works
  104 hledger command --mainflag --commandflag -> works
  105 XX hledger --mainflag command --commandflag -> works
  106 XX hledger --commandflag command -> works
  107 XX hledger --commandflag command --mainflag -> works
  108 
  109 -}