Change hcompta-jcc to hcompta-lcc.
[comptalang.git] / cli / Hcompta / CLI / Command / Journals.hs
index 1fdedf554cccc00ea2d5aa65df583e4f4291105d..8e883f501c9155a80bbd3d2268782b6bd8e6b755 100644 (file)
-{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TupleSections #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
 module Hcompta.CLI.Command.Journals where
 
-import           Control.Monad (Monad(..), forM_, liftM, mapM)
+import           Control.Arrow ((+++))
+import           Control.Monad (Monad(..), mapM)
 import           Control.Monad.IO.Class (liftIO)
-import           Control.Monad.Trans.Except (runExceptT)
 import           Data.Either (Either(..), partitionEithers)
 import           Data.Foldable (Foldable(..))
-import           Data.List ((++), replicate)
+import           Data.Function (($), (.), const)
+import           Data.Functor ((<$>))
+import           Data.List ((++))
+import           Data.Maybe (Maybe(..))
 import           Data.Monoid (Monoid(..), (<>))
 import           Data.String (String)
-import           Text.Show (Show)
-import           Prelude (($), Bounded(..), FilePath, IO, flip, unlines)
+import           Prelude (Bounded(..), FilePath, IO, unlines)
 import           System.Console.GetOpt
                   ( ArgDescr(..)
                   , OptDescr(..)
                   , usageInfo )
-import           System.Environment as Env (getProgName)
+import qualified System.Environment as Env
 import           System.Exit (exitSuccess)
 import qualified System.IO as IO
+import           Text.Show (Show)
 
-import           Hcompta.Chart (Chart)
 import qualified Hcompta.CLI.Args as Args
-import           Hcompta.CLI.Context (Context)
-import qualified Hcompta.CLI.Context as Context
-import qualified Hcompta.CLI.Format.Ledger as CLI.Ledger
+import qualified Hcompta.CLI.Context as C
+import qualified Hcompta.CLI.Env as CLI.Env
+
+import qualified Hcompta.CLI.Format as Format
+import           Hcompta.CLI.Format (Format(..), Formats)
+import           Hcompta.CLI.Format.Ledger ()
+import           Hcompta.CLI.Format.JCC ()
+import qualified Hcompta.CLI.Lang as Lang
 import qualified Hcompta.CLI.Write as Write
-import qualified Hcompta.Format.Ledger as Ledger
-import qualified Hcompta.Format.Ledger.Journal as Ledger.Journal
-import qualified Hcompta.Format.Ledger.Read as Ledger.Read
-import           Hcompta.Lib.Consable (Consable(..))
-import qualified Hcompta.Lib.Leijen as W
-
-data Ctx
- =   Ctx
- { ctx_input              :: [FilePath]
+
+
+-- import qualified Hcompta.Lib.Parsec as R
+import qualified Hcompta.JCC as JCC
+import qualified Hcompta.Ledger as Ledger
+import qualified Text.WalderLeijen.ANSI.Text as W
+
+data Context
+ =   Context
+ { ctx_input        :: [FilePath]
+ , ctx_input_format :: Formats
  } deriving (Show)
 
-nil :: Ctx
-nil =
-       Ctx
-        { ctx_input = []
+context :: Context
+context =
+       Context
+        { ctx_input        = []
+        , ctx_input_format = mempty
         }
 
-usage :: IO String
-usage = do
+usage :: C.Context -> IO String
+usage = do
        bin <- Env.getProgName
-       let pad = replicate (length bin) ' '
-       return $unlines $
-               [ "SYNTAX "
-               , "  "++bin++" stats [-i FILE_JOURNAL]"
-               , "  "++pad++"       [FILE_JOURNAL] [...]"
+       return $ unlines $
+               [ C.translate c Lang.Section_Description
+               , "  "++C.translate c Lang.Help_Command_Journals
                , ""
-               , usageInfo "OPTIONS" options
+               , C.translate c Lang.Section_Syntax
+               , "  "++bin++" journals ["++C.translate c Lang.Type_Option++"] [...]"++
+                                     " ["++C.translate c Lang.Type_File_Journal++"] [...]"
+               , ""
+               , usageInfo (C.translate c Lang.Section_Options) (options c)
                ]
 
-options :: Args.Options Ctx
-options =
+options :: C.Context -> Args.Options Context
+options =
        [ Option "h" ["help"]
-        (NoArg (\_context _ctx -> do
-               usage >>= IO.hPutStr IO.stderr
-               exitSuccess))
-        "show this help"
+        (NoArg (\_ctx -> do
+               usage >>= IO.hPutStr IO.stderr
+               exitSuccess)) $
+               C.translate c Lang.Help_Option_Help
        , Option "i" ["input"]
-        (ReqArg (\s _context ctx -> do
-               return $ ctx{ctx_input=s:ctx_input ctx}) "FILE")
-        "read data from given file, multiple uses merge the data as would a concatenation do"
+        (ReqArg (\s ctx ->
+               return $ ctx{ctx_input=s:ctx_input ctx}) $
+               C.translate c Lang.Type_File_Journal) $
+               C.translate c Lang.Help_Option_Input
+       , Option "f" ["input-format"]
+        (OptArg (\arg ctx -> do
+               ctx_input_format <- case arg of
+                Nothing       -> return $ Format_JCC ()
+                Just "jcc"    -> return $ Format_JCC ()
+                Just "ledger" -> return $ Format_Ledger ()
+                Just _        -> Write.fatal c $
+                       W.text "--input-format option expects \"jcc\", or \"ledger\" as value"
+               return $ ctx{ctx_input_format})
+         "[jcc|ledger]")
+         "input format"
        ]
 
-run :: Context.Context -> [String] -> IO ()
-run context args = do
-       (ctx, inputs) <- Args.parse context usage options (nil, args)
-       read_journals <-
-               liftM Data.Either.partitionEithers $ do
-               CLI.Ledger.paths context $ ctx_input ctx ++ inputs
-               >>= do
-                       mapM $ \path -> do
-                               liftIO $ runExceptT $ Ledger.Read.file
-                                (Ledger.Read.context () Ledger.journal)
-                                path
-                               >>= \x -> case x of
-                                Left  ko -> return $ Left (path, ko)
-                                Right ok -> return $ Right ok
-       case read_journals of
-        (errs@(_:_), _journals) ->
-               forM_ errs $ \(_path, err) -> do
-                       Write.fatal context $ err
+run :: C.Context -> [String] -> IO ()
+run c args = do
+       (ctx, inputs) <- Args.parse c usage options (context, args)
+       input_paths <- CLI.Env.paths c $ ctx_input ctx ++ inputs
+       read_journals <- mapM (liftIO . journal_read ctx) input_paths
+       case partitionEithers read_journals of
+        (errs@(_:_), _journals) -> Write.fatals c errs
         ([], journals) -> do
-               let files = ledger_journals ctx journals
-               style_color <- Write.with_color context IO.stdout
-               W.displayIO IO.stdout $ do
-               W.renderPretty style_color 1.0 maxBound $ do
-               doc_journals context ctx files
+               with_color <- Write.with_color c IO.stdout
+               W.displayIO IO.stdout $
+                       W.renderPretty with_color 1.0 maxBound $
+                               W.toDoc () $
+                               mconcat journals
+
+-- * Class 'Journal'
 
-newtype Journals t = Journals ()
+class
+ ( Format.Journal_Monoid (j m)
+ , Format.Journal_Read j
+ ) => Journal j m where
+       journal_files :: j m -> [FilePath]
+
+-- JCC
+instance Journal JCC.Journal Journals_JCC where
+       journal_files = JCC.journal_files
+
+-- Ledger
+instance Journal Ledger.Journal Journals_Ledger where
+       journal_files = Ledger.journal_files
+
+type Journals_JCC    = ()
+type Journals_Ledger = ()
+
+-- * Type 'Journals'
+
+newtype Journals =
+       Journals [FilePath]
  deriving (Show)
-instance Monoid (Journals t) where
-       mempty = Journals ()
-       mappend _ _ = mempty
-
-instance Consable () Journals t where
-       mcons () _t !_js = mempty
-
-ledger_journals
- :: Ctx
- -> [ Ledger.Journal (Journals (Chart, Ledger.Transaction)) ]
- -> [FilePath]
-ledger_journals _ctx =
-       Data.Foldable.foldl'
-        (flip $ Ledger.Journal.fold
-                (\Ledger.Journal{Ledger.journal_file=f} ->
-                       mappend [f]))
-        mempty
-
-doc_journals
- :: Context
- -> Ctx
- -> [FilePath]
- -> W.Doc
-doc_journals _context _ctx =
-       foldr
-        (\file doc -> doc <> W.toDoc () file <> W.line)
-        W.empty
+instance Monoid Journals where
+       mempty = Journals []
+       mappend (Journals x) (Journals y) =
+               Journals (mappend x y)
+       mconcat = foldl' mappend mempty
+instance W.ToDoc () Journals where
+       toDoc () (Journals files) =
+               foldr
+                (\file doc -> doc <> W.toDoc () file <> W.line)
+                W.empty files
+
+type Journal_Read_Cons txn = txn -> ()
+journal_read
+ :: Context -> FilePath
+ -> IO (Either (Format.Message W.Doc) Journals)
+journal_read ctx =
+       case ctx_input_format ctx of
+        Format_JCC () ->
+               let wrap (j::JCC.Journal Journals_JCC) =
+                       Format.journal_fold journals_cons j mempty in
+               let cons :: Journal_Read_Cons (JCC.Charted JCC.Transaction)
+                        = const () in
+               (((+++) Format.Message wrap) <$>) .
+               Format.journal_read cons
+        Format_Ledger () ->
+               let wrap (j::Ledger.Journal Journals_Ledger) =
+                       Format.journal_fold journals_cons j mempty in
+               let cons :: Journal_Read_Cons (Ledger.Charted Ledger.Transaction)
+                        = const () in
+               (((+++) Format.Message wrap) <$>) .
+               Format.journal_read cons
+
+journals_cons :: Journal j m => j m -> Journals -> Journals
+journals_cons j (Journals files) =
+       Journals (journal_files j ++ files)