1 {-# LANGUAGE ConstraintKinds #-}
2 {-# LANGUAGE ExistentialQuantification #-}
3 {-# LANGUAGE FlexibleContexts #-}
4 {-# LANGUAGE FlexibleInstances #-}
5 {-# LANGUAGE MultiParamTypeClasses #-}
6 {-# LANGUAGE NamedFieldPuns #-}
7 {-# LANGUAGE OverloadedStrings #-}
8 {-# LANGUAGE Rank2Types #-}
9 {-# LANGUAGE ScopedTypeVariables #-}
10 {-# LANGUAGE TupleSections #-}
11 {-# LANGUAGE TypeFamilies #-}
12 {-# OPTIONS_GHC -fno-warn-orphans #-}
13 module Hcompta.CLI.Command.Journals where
15 import Control.Arrow ((+++))
16 import Control.Monad (Monad(..), mapM)
17 import Control.Monad.IO.Class (liftIO)
18 import Data.Either (Either(..), partitionEithers)
19 import Data.Foldable (Foldable(..))
20 import Data.Function (($), (.), const)
21 import Data.Functor ((<$>))
22 import Data.List ((++))
23 import Data.Maybe (Maybe(..))
24 import Data.Monoid (Monoid(..), (<>))
25 import Data.String (String)
26 import Prelude (Bounded(..), FilePath, IO, unlines)
27 import System.Console.GetOpt
31 import qualified System.Environment as Env
32 import System.Exit (exitSuccess)
33 import qualified System.IO as IO
34 import Text.Show (Show)
36 import qualified Hcompta.CLI.Args as Args
37 import qualified Hcompta.CLI.Context as C
38 import qualified Hcompta.CLI.Env as CLI.Env
40 import qualified Hcompta.CLI.Format as Format
41 import Hcompta.CLI.Format (Format(..), Formats)
42 import Hcompta.CLI.Format.Ledger ()
43 import Hcompta.CLI.Format.JCC ()
44 import qualified Hcompta.CLI.Lang as Lang
45 import qualified Hcompta.CLI.Write as Write
48 -- import qualified Hcompta.Lib.Parsec as R
49 import qualified Hcompta.JCC as JCC
50 import qualified Hcompta.Ledger as Ledger
51 import qualified Text.WalderLeijen.ANSI.Text as W
55 { ctx_input :: [FilePath]
56 , ctx_input_format :: Formats
63 , ctx_input_format = mempty
66 usage :: C.Context -> IO String
68 bin <- Env.getProgName
70 [ C.translate c Lang.Section_Description
71 , " "++C.translate c Lang.Help_Command_Journals
73 , C.translate c Lang.Section_Syntax
74 , " "++bin++" journals ["++C.translate c Lang.Type_Option++"] [...]"++
75 " ["++C.translate c Lang.Type_File_Journal++"] [...]"
77 , usageInfo (C.translate c Lang.Section_Options) (options c)
80 options :: C.Context -> Args.Options Context
84 usage c >>= IO.hPutStr IO.stderr
86 C.translate c Lang.Help_Option_Help
87 , Option "i" ["input"]
89 return $ ctx{ctx_input=s:ctx_input ctx}) $
90 C.translate c Lang.Type_File_Journal) $
91 C.translate c Lang.Help_Option_Input
92 , Option "f" ["input-format"]
93 (OptArg (\arg ctx -> do
94 ctx_input_format <- case arg of
95 Nothing -> return $ Format_JCC ()
96 Just "jcc" -> return $ Format_JCC ()
97 Just "ledger" -> return $ Format_Ledger ()
98 Just _ -> Write.fatal c $
99 W.text "--input-format option expects \"jcc\", or \"ledger\" as value"
100 return $ ctx{ctx_input_format})
105 run :: C.Context -> [String] -> IO ()
107 (ctx, inputs) <- Args.parse c usage options (context, args)
108 input_paths <- CLI.Env.paths c $ ctx_input ctx ++ inputs
109 read_journals <- mapM (liftIO . journal_read ctx) input_paths
110 case partitionEithers read_journals of
111 (errs@(_:_), _journals) -> Write.fatals c errs
113 with_color <- Write.with_color c IO.stdout
114 W.displayIO IO.stdout $
115 W.renderPretty with_color 1.0 maxBound $
122 ( Format.Journal_Monoid (j m)
123 , Format.Journal_Read j
124 ) => Journal j m where
125 journal_files :: j m -> [FilePath]
128 instance Journal JCC.Journal Journals_JCC where
129 journal_files = JCC.journal_files
132 instance Journal Ledger.Journal Journals_Ledger where
133 journal_files = Ledger.journal_files
135 type Journals_JCC = ()
136 type Journals_Ledger = ()
143 instance Monoid Journals where
145 mappend (Journals x) (Journals y) =
146 Journals (mappend x y)
147 mconcat = foldl' mappend mempty
148 instance W.ToDoc () Journals where
149 toDoc () (Journals files) =
151 (\file doc -> doc <> W.toDoc () file <> W.line)
154 type Journal_Read_Cons txn = txn -> ()
156 :: Context -> FilePath
157 -> IO (Either (Format.Message W.Doc) Journals)
159 case ctx_input_format ctx of
161 let wrap (j::JCC.Journal Journals_JCC) =
162 Format.journal_fold journals_cons j mempty in
163 let cons :: Journal_Read_Cons (JCC.Charted JCC.Transaction)
165 (((+++) Format.Message wrap) <$>) .
166 Format.journal_read cons
168 let wrap (j::Ledger.Journal Journals_Ledger) =
169 Format.journal_fold journals_cons j mempty in
170 let cons :: Journal_Read_Cons (Ledger.Charted Ledger.Transaction)
172 (((+++) Format.Message wrap) <$>) .
173 Format.journal_read cons
175 journals_cons :: Journal j m => j m -> Journals -> Journals
176 journals_cons j (Journals files) =
177 Journals (journal_files j ++ files)