1 {-# LANGUAGE BangPatterns #-}
2 {-# LANGUAGE FlexibleInstances #-}
3 {-# LANGUAGE MultiParamTypeClasses #-}
4 {-# LANGUAGE NamedFieldPuns #-}
5 {-# LANGUAGE OverloadedStrings #-}
6 {-# LANGUAGE ScopedTypeVariables #-}
7 {-# LANGUAGE TupleSections #-}
8 module Hcompta.CLI.Command.Journals where
10 import Control.Monad (Monad(..), forM_, liftM, mapM)
11 import Control.Monad.IO.Class (liftIO)
12 import Control.Monad.Trans.Except (runExceptT)
13 import Data.Either (Either(..), partitionEithers)
14 import Data.Foldable (Foldable(..))
15 import Data.List ((++), replicate)
16 import Data.Monoid (Monoid(..), (<>))
17 import Data.String (String)
18 import Text.Show (Show)
19 import Prelude (($), Bounded(..), FilePath, IO, flip, unlines)
20 import System.Console.GetOpt
24 import System.Environment as Env (getProgName)
25 import System.Exit (exitSuccess)
26 import qualified System.IO as IO
28 import qualified Hcompta.CLI.Args as Args
29 import Hcompta.CLI.Context (Context)
30 import qualified Hcompta.CLI.Context as Context
31 import qualified Hcompta.CLI.Format.Ledger as CLI.Ledger
32 import qualified Hcompta.CLI.Write as Write
33 import qualified Hcompta.Format.Ledger as Ledger
34 import qualified Hcompta.Format.Ledger.Journal as Ledger.Journal
35 import qualified Hcompta.Format.Ledger.Read as Ledger.Read
36 import Hcompta.Lib.Consable (Consable(..))
37 import qualified Hcompta.Lib.Leijen as W
41 { ctx_input :: [FilePath]
52 bin <- Env.getProgName
53 let pad = replicate (length bin) ' '
56 , " "++bin++" stats [-i JOURNAL_FILE]"
57 , " "++pad++" [JOURNAL_FILE] [...]"
59 , usageInfo "OPTIONS" options
62 options :: Args.Options Ctx
65 (NoArg (\_context _ctx -> do
66 usage >>= IO.hPutStr IO.stderr
69 , Option "i" ["input"]
70 (ReqArg (\s _context ctx -> do
71 return $ ctx{ctx_input=s:ctx_input ctx}) "FILE")
72 "read data from given file, multiple uses merge the data as would a concatenation do"
75 run :: Context.Context -> [String] -> IO ()
77 (ctx, inputs) <- Args.parse context usage options (nil, args)
79 liftM Data.Either.partitionEithers $ do
80 CLI.Ledger.paths context $ ctx_input ctx ++ inputs
83 liftIO $ runExceptT $ Ledger.Read.file
84 (Ledger.Read.context () Ledger.journal)
87 Left ko -> return $ Left (path, ko)
88 Right ok -> return $ Right ok
90 (errs@(_:_), _journals) ->
91 forM_ errs $ \(_path, err) -> do
92 Write.fatal context $ err
94 let files = ledger_journals ctx journals
95 style_color <- Write.with_color context IO.stdout
96 W.displayIO IO.stdout $ do
97 W.renderPretty style_color 1.0 maxBound $ do
98 doc_journals context ctx files
100 newtype Journals t = Journals ()
102 instance Monoid (Journals t) where
106 instance Consable () Journals t where
107 mcons () _t !_js = mempty
111 -> [ Ledger.Journal (Journals Ledger.Transaction) ]
113 ledger_journals _ctx =
115 (flip $ Ledger.Journal.fold
116 (\Ledger.Journal{Ledger.journal_file=f} ->
125 doc_journals _context _ctx =
127 (\file doc -> doc <> W.toDoc () file <> W.line)