{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
module Hledger.Cli.Commands.Check (
checkmode
,check
) where
import Data.Char (toLower)
import Data.Either (partitionEithers)
import Data.List (isPrefixOf, find)
import Control.Monad (forM_)
import System.Console.CmdArgs.Explicit
import Hledger
import Hledger.Cli.CliOptions
checkmode :: Mode RawOpts
checkmode :: Mode RawOpts
checkmode = String
-> [Flag RawOpts]
-> [(String, [Flag RawOpts])]
-> [Flag RawOpts]
-> ([Arg RawOpts], Maybe (Arg RawOpts))
-> Mode RawOpts
hledgerCommandMode
$(embedFileRelative "Hledger/Cli/Commands/Check.txt")
[]
[(String, [Flag RawOpts])
generalflagsgroup1]
[Flag RawOpts]
hiddenflags
([], forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ String -> Arg RawOpts
argsFlag String
"[CHECKS]")
check :: CliOpts -> Journal -> IO ()
check :: CliOpts -> Journal -> IO ()
check copts :: CliOpts
copts@CliOpts{RawOpts
rawopts_ :: CliOpts -> RawOpts
rawopts_ :: RawOpts
rawopts_} Journal
j = do
let
args :: [String]
args = String -> RawOpts -> [String]
listofstringopt String
"args" RawOpts
rawopts_
copts' :: CliOpts
copts' = (ReportOpts -> ReportOpts) -> CliOpts -> CliOpts
cliOptsUpdateReportSpecWith (\ReportOpts
ropts -> ReportOpts
ropts{querystring_ :: [Text]
querystring_=[]}) CliOpts
copts
case forall a b. [Either a b] -> ([a], [b])
partitionEithers (forall a b. (a -> b) -> [a] -> [b]
map String -> Either String (Check, [String])
parseCheckArgument [String]
args) of
(unknowns :: [String]
unknowns@(String
_:[String]
_), [(Check, [String])]
_) -> forall a. String -> a
error' forall a b. (a -> b) -> a -> b
$ String
"These checks are unknown: "forall a. [a] -> [a] -> [a]
++[String] -> String
unwords [String]
unknowns
([], [(Check, [String])]
checks) -> forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(Check, [String])]
checks forall a b. (a -> b) -> a -> b
$ CliOpts -> Journal -> (Check, [String]) -> IO ()
runCheck CliOpts
copts' Journal
j
cliOptsUpdateReportSpecWith :: (ReportOpts -> ReportOpts) -> CliOpts -> CliOpts
cliOptsUpdateReportSpecWith :: (ReportOpts -> ReportOpts) -> CliOpts -> CliOpts
cliOptsUpdateReportSpecWith ReportOpts -> ReportOpts
roptsupdate copts :: CliOpts
copts@CliOpts{ReportSpec
reportspec_ :: CliOpts -> ReportSpec
reportspec_ :: ReportSpec
reportspec_} =
case (ReportOpts -> ReportOpts)
-> ReportSpec -> Either String ReportSpec
updateReportSpecWith ReportOpts -> ReportOpts
roptsupdate ReportSpec
reportspec_ of
Left String
e -> forall a. String -> a
error' String
e
Right ReportSpec
rs -> CliOpts
copts{reportspec_ :: ReportSpec
reportspec_=ReportSpec
rs}
data Check =
Parseable
| Autobalanced
| Assertions
| Accounts
| Commodities
| Balanced
| Ordereddates
| Payees
| Recentassertions
| Tags
| Uniqueleafnames
deriving (ReadPrec [Check]
ReadPrec Check
Int -> ReadS Check
ReadS [Check]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Check]
$creadListPrec :: ReadPrec [Check]
readPrec :: ReadPrec Check
$creadPrec :: ReadPrec Check
readList :: ReadS [Check]
$creadList :: ReadS [Check]
readsPrec :: Int -> ReadS Check
$creadsPrec :: Int -> ReadS Check
Read,Int -> Check -> ShowS
[Check] -> ShowS
Check -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Check] -> ShowS
$cshowList :: [Check] -> ShowS
show :: Check -> String
$cshow :: Check -> String
showsPrec :: Int -> Check -> ShowS
$cshowsPrec :: Int -> Check -> ShowS
Show,Check -> Check -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Check -> Check -> Bool
$c/= :: Check -> Check -> Bool
== :: Check -> Check -> Bool
$c== :: Check -> Check -> Bool
Eq,Int -> Check
Check -> Int
Check -> [Check]
Check -> Check
Check -> Check -> [Check]
Check -> Check -> Check -> [Check]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Check -> Check -> Check -> [Check]
$cenumFromThenTo :: Check -> Check -> Check -> [Check]
enumFromTo :: Check -> Check -> [Check]
$cenumFromTo :: Check -> Check -> [Check]
enumFromThen :: Check -> Check -> [Check]
$cenumFromThen :: Check -> Check -> [Check]
enumFrom :: Check -> [Check]
$cenumFrom :: Check -> [Check]
fromEnum :: Check -> Int
$cfromEnum :: Check -> Int
toEnum :: Int -> Check
$ctoEnum :: Int -> Check
pred :: Check -> Check
$cpred :: Check -> Check
succ :: Check -> Check
$csucc :: Check -> Check
Enum,Check
forall a. a -> a -> Bounded a
maxBound :: Check
$cmaxBound :: Check
minBound :: Check
$cminBound :: Check
Bounded)
parseCheck :: String -> Either String Check
parseCheck :: String -> Either String Check
parseCheck String
s =
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall a b. a -> Either a b
Left String
s) (forall a b. b -> Either a b
Right forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Read a => String -> a
read) forall a b. (a -> b) -> a -> b
$
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (String
s' forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf`) forall a b. (a -> b) -> a -> b
$ [String]
checknames
where
s' :: String
s' = ShowS
capitalise forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
s
checknames :: [String]
checknames = forall a b. (a -> b) -> [a] -> [b]
map forall a. Show a => a -> String
show [forall a. Bounded a => a
minBound..forall a. Bounded a => a
maxBound::Check]
parseCheckArgument :: String -> Either String (Check,[String])
parseCheckArgument :: String -> Either String (Check, [String])
parseCheckArgument String
s =
forall a. Show a => String -> a -> a
dbg3 String
"check argument" forall a b. (a -> b) -> a -> b
$
((,[String]
checkargs)) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Either String Check
parseCheck String
checkname
where
(String
checkname:[String]
checkargs) = String -> [String]
words' String
s
runCheck :: CliOpts -> Journal -> (Check,[String]) -> IO ()
runCheck :: CliOpts -> Journal -> (Check, [String]) -> IO ()
runCheck CliOpts{reportspec_ :: CliOpts -> ReportSpec
reportspec_=ReportSpec{_rsReportOpts :: ReportSpec -> ReportOpts
_rsReportOpts=ReportOpts
ropts}} Journal
j (Check
chck,[String]
_) = do
Day
d <- IO Day
getCurrentDay
let
results :: Either String ()
results = case Check
chck of
Check
Accounts -> Journal -> Either String ()
journalCheckAccounts Journal
j
Check
Commodities -> Journal -> Either String ()
journalCheckCommodities Journal
j
Check
Ordereddates -> WhichDate -> Journal -> Either String ()
journalCheckOrdereddates (ReportOpts -> WhichDate
whichDate ReportOpts
ropts) Journal
j
Check
Payees -> Journal -> Either String ()
journalCheckPayees Journal
j
Check
Recentassertions -> Day -> Journal -> Either String ()
journalCheckRecentAssertions Day
d Journal
j
Check
Tags -> Journal -> Either String ()
journalCheckTags Journal
j
Check
Uniqueleafnames -> Journal -> Either String ()
journalCheckUniqueleafnames Journal
j
Check
_ -> forall a b. b -> Either a b
Right ()
case Either String ()
results of
Right () -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
Left String
err -> forall a. String -> a
error' String
err