ref: consolidate most checks under Hledger.Read.Checks

and error message helpers in Hledger.Read.Error.
This commit is contained in:
Simon Michael 2022-05-08 22:56:47 -10:00
parent 211680da86
commit 810a868c88
11 changed files with 239 additions and 187 deletions

View File

@ -42,6 +42,7 @@ module Hledger.Read (
findReader, findReader,
splitReaderPrefix, splitReaderPrefix,
runJournalParser, runJournalParser,
module Hledger.Read.Checks,
module Hledger.Read.Common, module Hledger.Read.Common,
module Hledger.Read.InputOptions, module Hledger.Read.InputOptions,
@ -75,6 +76,7 @@ import System.IO (hPutStr, stderr)
import Hledger.Data.Dates (getCurrentDay, parsedateM, showDate) import Hledger.Data.Dates (getCurrentDay, parsedateM, showDate)
import Hledger.Data.Types import Hledger.Data.Types
import Hledger.Read.Checks
import Hledger.Read.Common import Hledger.Read.Common
import Hledger.Read.InputOptions import Hledger.Read.InputOptions
import Hledger.Read.JournalReader as JournalReader import Hledger.Read.JournalReader as JournalReader

View File

@ -0,0 +1,125 @@
{-|
Various additional validation checks that can be performed on a Journal.
Some are called as part of reading a file in strict mode,
others can be called only via the check command.
-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NamedFieldPuns #-}
module Hledger.Read.Checks (
journalCheckAccountsDeclared,
journalCheckCommoditiesDeclared,
journalCheckPayeesDeclared,
module Hledger.Read.Checks.Uniqueleafnames,
)
where
import Data.Char (isSpace)
import Data.List (find)
import Data.Maybe
import qualified Data.Map.Strict as M
import qualified Data.Text as T
import Safe (atMay)
import Text.Printf (printf)
import Hledger.Data
import Hledger.Read.Checks.Uniqueleafnames
import Hledger.Read.Error
-- | Check that all the journal's postings are to accounts declared with
-- account directives, returning an error message otherwise.
journalCheckAccountsDeclared :: Journal -> Either String ()
journalCheckAccountsDeclared j = mapM_ checkacct (journalPostings j)
where
checkacct p@Posting{paccount=a}
| a `elem` journalAccountNamesDeclared j = Right ()
| otherwise = Left $
printf "%s:%d:%d-%d:\n%sundeclared account \"%s\"\n" f l col col2 ex a
where
(f,l,mcols,ex) = makePostingErrorExcerpt p finderrcols
col = maybe 0 fst mcols
col2 = maybe 0 (fromMaybe 0 . snd) mcols
finderrcols p _ _ = Just (col, Just col2)
where
col = 5 + if isVirtual p then 1 else 0
col2 = col + T.length a - 1
-- | Check that all the commodities used in this journal's postings have been declared
-- by commodity directives, returning an error message otherwise.
journalCheckCommoditiesDeclared :: Journal -> Either String ()
journalCheckCommoditiesDeclared j = mapM_ checkcommodities (journalPostings j)
where
checkcommodities p =
case findundeclaredcomm p of
Nothing -> Right ()
Just (comm, _) ->
Left $ printf "%s:%d:%d-%d:\n%sundeclared commodity \"%s\"\n" f l col col2 ex comm
where
(f,l,mcols,ex) = makePostingErrorExcerpt p finderrcols
col = maybe 0 fst mcols
col2 = maybe 0 (fromMaybe 0 . snd) mcols
where
-- Find the first undeclared commodity symbol in this posting's amount
-- or balance assertion amount, if any. The boolean will be true if
-- the undeclared symbol was in the posting amount.
findundeclaredcomm :: Posting -> Maybe (CommoditySymbol, Bool)
findundeclaredcomm Posting{pamount=amt,pbalanceassertion} =
case (findundeclared postingcomms, findundeclared assertioncomms) of
(Just c, _) -> Just (c, True)
(_, Just c) -> Just (c, False)
_ -> Nothing
where
postingcomms = map acommodity $ filter (not . isIgnorable) $ amountsRaw amt
where
-- Ignore missing amounts and zero amounts without commodity (#1767)
isIgnorable a = (T.null (acommodity a) && amountIsZero a) || a == missingamt
assertioncomms = [acommodity a | Just a <- [baamount <$> pbalanceassertion]]
findundeclared = find (`M.notMember` jcommodities j)
-- Find the best position for an error column marker when this posting
-- is rendered by showTransaction.
-- Reliably locating a problem commodity symbol in showTransaction output
-- is really tricky. Some examples:
--
-- assets "C $" -1 @ $ 2
-- ^
-- assets $1 = $$1
-- ^
-- assets [ANSI RED]$-1[ANSI RESET]
-- ^
--
-- To simplify, we will mark the whole amount + balance assertion region, like:
-- assets "C $" -1 @ $ 2
-- ^^^^^^^^^^^^^^
-- XXX refine this region when it's easy
finderrcols p t txntxt =
case transactionFindPostingIndex (==p) t of
Nothing -> Nothing
Just pindex -> Just (amtstart, Just amtend)
where
tcommentlines = max 0 (length (T.lines $ tcomment t) - 1)
errrelline = 1 + tcommentlines + pindex -- XXX doesn't count posting coment lines
errline = fromMaybe "" (T.lines txntxt `atMay` (errrelline-1))
acctend = 4 + T.length (paccount p) + if isVirtual p then 2 else 0
amtstart = acctend + (T.length $ T.takeWhile isSpace $ T.drop acctend errline) + 1
amtend = amtstart + (T.length $ T.stripEnd $ T.takeWhile (/=';') $ T.drop amtstart errline)
-- | Check that all the journal's transactions have payees declared with
-- payee directives, returning an error message otherwise.
journalCheckPayeesDeclared :: Journal -> Either String ()
journalCheckPayeesDeclared j = mapM_ checkpayee (jtxns j)
where
checkpayee t
| payee `elem` journalPayeesDeclared j = Right ()
| otherwise = Left $
printf "%s:%d:%d-%d:\n%sundeclared payee \"%s\"\n" f l col col2 ex payee
where
payee = transactionPayee t
(f,l,mcols,ex) = makeTransactionErrorExcerpt t finderrcols
col = maybe 0 fst mcols
col2 = maybe 0 (fromMaybe 0 . snd) mcols
finderrcols t = Just (col, Just col2)
where
col = T.length (showTransactionLineFirstPart t) + 2
col2 = col + T.length (transactionPayee t) - 1

View File

@ -1,7 +1,7 @@
{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
module Hledger.Cli.Commands.Check.Uniqueleafnames ( module Hledger.Read.Checks.Uniqueleafnames (
journalCheckUniqueleafnames journalCheckUniqueleafnames
) )
where where
@ -10,10 +10,12 @@ import Data.Function (on)
import Data.List (groupBy, sortBy) import Data.List (groupBy, sortBy)
import Data.Text (Text) import Data.Text (Text)
import qualified Data.Text as T import qualified Data.Text as T
import Hledger
import Text.Printf (printf) import Text.Printf (printf)
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
import Hledger.Data
import Hledger.Read.Error
-- | Check that all the journal's postings are to accounts with a unique leaf name. -- | Check that all the journal's postings are to accounts with a unique leaf name.
-- Otherwise, return an error message for the first offending posting. -- Otherwise, return an error message for the first offending posting.
journalCheckUniqueleafnames :: Journal -> Either String () journalCheckUniqueleafnames :: Journal -> Either String ()

View File

@ -37,9 +37,6 @@ module Hledger.Read.Common (
parseAndFinaliseJournal, parseAndFinaliseJournal,
initialiseAndParseJournal, initialiseAndParseJournal,
journalFinalise, journalFinalise,
journalCheckAccountsDeclared,
journalCheckCommoditiesDeclared,
journalCheckPayeesDeclared,
journalAddForecast, journalAddForecast,
journalAddAutoPostings, journalAddAutoPostings,
setYear, setYear,
@ -112,8 +109,6 @@ module Hledger.Read.Common (
skipNonNewlineSpaces, skipNonNewlineSpaces,
skipNonNewlineSpaces1, skipNonNewlineSpaces1,
aliasesFromOpts, aliasesFromOpts,
makeTransactionErrorExcerpt,
makePostingErrorExcerpt,
-- * tests -- * tests
tests_Common, tests_Common,
@ -152,9 +147,8 @@ import Hledger.Data
import Hledger.Query (Query(..), filterQuery, parseQueryTerm, queryEndDate, queryStartDate, queryIsDate, simplifyQuery) import Hledger.Query (Query(..), filterQuery, parseQueryTerm, queryEndDate, queryStartDate, queryIsDate, simplifyQuery)
import Hledger.Reports.ReportOptions (ReportOpts(..), queryFromFlags, rawOptsToReportOpts) import Hledger.Reports.ReportOptions (ReportOpts(..), queryFromFlags, rawOptsToReportOpts)
import Hledger.Utils import Hledger.Utils
import Text.Printf (printf)
import Hledger.Read.InputOptions import Hledger.Read.InputOptions
import Safe (atMay) import Hledger.Read.Checks (journalCheckAccountsDeclared, journalCheckCommoditiesDeclared)
--- ** doctest setup --- ** doctest setup
-- $setup -- $setup
@ -359,180 +353,6 @@ journalAddForecast (Just forecastspan) j = j{jtxns = jtxns j ++ forecasttxns}
. concatMap (`runPeriodicTransaction` forecastspan) . concatMap (`runPeriodicTransaction` forecastspan)
$ jperiodictxns j $ jperiodictxns j
-- | Check that all the journal's transactions have payees declared with
-- payee directives, returning an error message otherwise.
journalCheckPayeesDeclared :: Journal -> Either String ()
journalCheckPayeesDeclared j = mapM_ checkpayee (jtxns j)
where
checkpayee t
| payee `elem` journalPayeesDeclared j = Right ()
| otherwise = Left $
printf "%s:%d:%d-%d:\n%sundeclared payee \"%s\"\n" f l col col2 ex payee
where
payee = transactionPayee t
(f,l,mcols,ex) = makeTransactionErrorExcerpt t finderrcols
col = maybe 0 fst mcols
col2 = maybe 0 (fromMaybe 0 . snd) mcols
finderrcols t = Just (col, Just col2)
where
col = T.length (showTransactionLineFirstPart t) + 2
col2 = col + T.length (transactionPayee t) - 1
-- | Check that all the journal's postings are to accounts declared with
-- account directives, returning an error message otherwise.
journalCheckAccountsDeclared :: Journal -> Either String ()
journalCheckAccountsDeclared j = mapM_ checkacct (journalPostings j)
where
checkacct p@Posting{paccount=a}
| a `elem` journalAccountNamesDeclared j = Right ()
| otherwise = Left $
printf "%s:%d:%d-%d:\n%sundeclared account \"%s\"\n" f l col col2 ex a
where
(f,l,mcols,ex) = makePostingErrorExcerpt p finderrcols
col = maybe 0 fst mcols
col2 = maybe 0 (fromMaybe 0 . snd) mcols
finderrcols p _ _ = Just (col, Just col2)
where
col = 5 + if isVirtual p then 1 else 0
col2 = col + T.length a - 1
-- | Check that all the commodities used in this journal's postings have been declared
-- by commodity directives, returning an error message otherwise.
journalCheckCommoditiesDeclared :: Journal -> Either String ()
journalCheckCommoditiesDeclared j = mapM_ checkcommodities (journalPostings j)
where
checkcommodities p =
case findundeclaredcomm p of
Nothing -> Right ()
Just (comm, _) ->
Left $ printf "%s:%d:%d-%d:\n%sundeclared commodity \"%s\"\n" f l col col2 ex comm
where
(f,l,mcols,ex) = makePostingErrorExcerpt p finderrcols
col = maybe 0 fst mcols
col2 = maybe 0 (fromMaybe 0 . snd) mcols
where
-- Find the first undeclared commodity symbol in this posting's amount
-- or balance assertion amount, if any. The boolean will be true if
-- the undeclared symbol was in the posting amount.
findundeclaredcomm :: Posting -> Maybe (CommoditySymbol, Bool)
findundeclaredcomm Posting{pamount=amt,pbalanceassertion} =
case (findundeclared postingcomms, findundeclared assertioncomms) of
(Just c, _) -> Just (c, True)
(_, Just c) -> Just (c, False)
_ -> Nothing
where
postingcomms = map acommodity $ filter (not . isIgnorable) $ amountsRaw amt
where
-- Ignore missing amounts and zero amounts without commodity (#1767)
isIgnorable a = (T.null (acommodity a) && amountIsZero a) || a == missingamt
assertioncomms = [acommodity a | Just a <- [baamount <$> pbalanceassertion]]
findundeclared = find (`M.notMember` jcommodities j)
-- Find the best position for an error column marker when this posting
-- is rendered by showTransaction.
-- Reliably locating a problem commodity symbol in showTransaction output
-- is really tricky. Some examples:
--
-- assets "C $" -1 @ $ 2
-- ^
-- assets $1 = $$1
-- ^
-- assets [ANSI RED]$-1[ANSI RESET]
-- ^
--
-- To simplify, we will mark the whole amount + balance assertion region, like:
-- assets "C $" -1 @ $ 2
-- ^^^^^^^^^^^^^^
finderrcols p t txntxt =
case transactionFindPostingIndex (==p) t of
Nothing -> Nothing
Just pindex -> Just (amtstart, Just amtend)
where
tcommentlines = max 0 (length (T.lines $ tcomment t) - 1)
errrelline = 1 + tcommentlines + pindex -- XXX doesn't count posting coment lines
errline = fromMaybe "" (T.lines txntxt `atMay` (errrelline-1))
acctend = 4 + T.length (paccount p) + if isVirtual p then 2 else 0
amtstart = acctend + (T.length $ T.takeWhile isSpace $ T.drop acctend errline) + 1
amtend = amtstart + (T.length $ T.stripEnd $ T.takeWhile (/=';') $ T.drop amtstart errline)
-- | Given a problem transaction and a function calculating the best
-- column(s) for marking the error region:
-- render it as a megaparsec-style excerpt, showing the original line number
-- on the transaction line, and a column(s) marker.
-- Returns the file path, line number, column(s) if known,
-- and the rendered excerpt, or as much of these as is possible.
makeTransactionErrorExcerpt :: Transaction -> (Transaction -> Maybe (Int, Maybe Int)) -> (FilePath, Int, Maybe (Int, Maybe Int), Text)
makeTransactionErrorExcerpt t findtxnerrorcolumns = (f, tl, merrcols, ex)
-- XXX findtxnerrorcolumns is awkward, I don't think this is the final form
where
(SourcePos f tpos _) = fst $ tsourcepos t
tl = unPos tpos
txntxt = showTransaction t & textChomp & (<>"\n")
merrcols = findtxnerrorcolumns t
ex = decorateTransactionErrorExcerpt tl merrcols txntxt
-- | Add megaparsec-style left margin, line number, and optional column marker(s).
decorateTransactionErrorExcerpt :: Int -> Maybe (Int, Maybe Int) -> Text -> Text
decorateTransactionErrorExcerpt l mcols txt =
T.unlines $ ls' <> colmarkerline <> map (lineprefix<>) ms
where
(ls,ms) = splitAt 1 $ T.lines txt
ls' = map ((T.pack (show l) <> " | ") <>) ls
colmarkerline =
[lineprefix <> T.replicate (col-1) " " <> T.replicate regionw "^"
| Just (col, mendcol) <- [mcols]
, let regionw = maybe 1 (subtract col) mendcol + 1
]
lineprefix = T.replicate marginw " " <> "| "
where marginw = length (show l) + 1
-- | Given a problem posting and a function calculating the best
-- column(s) for marking the error region:
-- look up error info from the parent transaction, and render the transaction
-- as a megaparsec-style excerpt, showing the original line number
-- on the problem posting's line, and a column indicator.
-- Returns the file path, line number, column(s) if known,
-- and the rendered excerpt, or as much of these as is possible.
makePostingErrorExcerpt :: Posting -> (Posting -> Transaction -> Text -> Maybe (Int, Maybe Int)) -> (FilePath, Int, Maybe (Int, Maybe Int), Text)
makePostingErrorExcerpt p findpostingerrorcolumns =
case ptransaction p of
Nothing -> ("-", 0, Nothing, "")
Just t -> (f, errabsline, merrcols, ex)
where
(SourcePos f tl _) = fst $ tsourcepos t
tcommentlines = max 0 (length (T.lines $ tcomment t) - 1)
mpindex = transactionFindPostingIndex (==p) t
errrelline = maybe 0 (tcommentlines+) mpindex -- XXX doesn't count posting coment lines
errabsline = unPos tl + errrelline
txntxt = showTransaction t & textChomp & (<>"\n")
merrcols = findpostingerrorcolumns p t txntxt
ex = decoratePostingErrorExcerpt errabsline errrelline merrcols txntxt
-- | Add megaparsec-style left margin, line number, and optional column marker(s).
decoratePostingErrorExcerpt :: Int -> Int -> Maybe (Int, Maybe Int) -> Text -> Text
decoratePostingErrorExcerpt absline relline mcols txt =
T.unlines $ js' <> ks' <> colmarkerline <> ms'
where
(ls,ms) = splitAt (relline+1) $ T.lines txt
(js,ks) = splitAt (length ls - 1) ls
(js',ks') = case ks of
[k] -> (map (lineprefix<>) js, [T.pack (show absline) <> " | " <> k])
_ -> ([], [])
ms' = map (lineprefix<>) ms
colmarkerline =
[lineprefix <> T.replicate (col-1) " " <> T.replicate regionw "^"
| Just (col, mendcol) <- [mcols]
, let regionw = 1 + maybe 0 (subtract col) mendcol
]
lineprefix = T.replicate marginw " " <> "| "
where marginw = length (show absline) + 1
-- | Find the 1-based index of the first posting in this transaction
-- satisfying the given predicate.
transactionFindPostingIndex :: (Posting -> Bool) -> Transaction -> Maybe Int
transactionFindPostingIndex ppredicate =
fmap fst . find (ppredicate.snd) . zip [1..] . tpostings
setYear :: Year -> JournalParser m () setYear :: Year -> JournalParser m ()
setYear y = modify' (\j -> j{jparsedefaultyear=Just y}) setYear y = modify' (\j -> j{jparsedefaultyear=Just y})

View File

@ -0,0 +1,99 @@
{-|
Helpers for making error messages.
-}
{-# LANGUAGE OverloadedStrings #-}
module Hledger.Read.Error (
makeTransactionErrorExcerpt,
makePostingErrorExcerpt,
transactionFindPostingIndex,
)
where
import Data.Function ((&))
import Data.List (find)
import Data.Text (Text)
import qualified Data.Text as T
import Hledger.Data
import Hledger.Utils
-- | Given a problem transaction and a function calculating the best
-- column(s) for marking the error region:
-- render it as a megaparsec-style excerpt, showing the original line number
-- on the transaction line, and a column(s) marker.
-- Returns the file path, line number, column(s) if known,
-- and the rendered excerpt, or as much of these as is possible.
makeTransactionErrorExcerpt :: Transaction -> (Transaction -> Maybe (Int, Maybe Int)) -> (FilePath, Int, Maybe (Int, Maybe Int), Text)
makeTransactionErrorExcerpt t findtxnerrorcolumns = (f, tl, merrcols, ex)
-- XXX findtxnerrorcolumns is awkward, I don't think this is the final form
where
(SourcePos f tpos _) = fst $ tsourcepos t
tl = unPos tpos
txntxt = showTransaction t & textChomp & (<>"\n")
merrcols = findtxnerrorcolumns t
ex = decorateTransactionErrorExcerpt tl merrcols txntxt
-- | Add megaparsec-style left margin, line number, and optional column marker(s).
decorateTransactionErrorExcerpt :: Int -> Maybe (Int, Maybe Int) -> Text -> Text
decorateTransactionErrorExcerpt l mcols txt =
T.unlines $ ls' <> colmarkerline <> map (lineprefix<>) ms
where
(ls,ms) = splitAt 1 $ T.lines txt
ls' = map ((T.pack (show l) <> " | ") <>) ls
colmarkerline =
[lineprefix <> T.replicate (col-1) " " <> T.replicate regionw "^"
| Just (col, mendcol) <- [mcols]
, let regionw = maybe 1 (subtract col) mendcol + 1
]
lineprefix = T.replicate marginw " " <> "| "
where marginw = length (show l) + 1
-- | Given a problem posting and a function calculating the best
-- column(s) for marking the error region:
-- look up error info from the parent transaction, and render the transaction
-- as a megaparsec-style excerpt, showing the original line number
-- on the problem posting's line, and a column indicator.
-- Returns the file path, line number, column(s) if known,
-- and the rendered excerpt, or as much of these as is possible.
makePostingErrorExcerpt :: Posting -> (Posting -> Transaction -> Text -> Maybe (Int, Maybe Int)) -> (FilePath, Int, Maybe (Int, Maybe Int), Text)
makePostingErrorExcerpt p findpostingerrorcolumns =
case ptransaction p of
Nothing -> ("-", 0, Nothing, "")
Just t -> (f, errabsline, merrcols, ex)
where
(SourcePos f tl _) = fst $ tsourcepos t
tcommentlines = max 0 (length (T.lines $ tcomment t) - 1)
mpindex = transactionFindPostingIndex (==p) t
errrelline = maybe 0 (tcommentlines+) mpindex -- XXX doesn't count posting coment lines
errabsline = unPos tl + errrelline
txntxt = showTransaction t & textChomp & (<>"\n")
merrcols = findpostingerrorcolumns p t txntxt
ex = decoratePostingErrorExcerpt errabsline errrelline merrcols txntxt
-- | Add megaparsec-style left margin, line number, and optional column marker(s).
decoratePostingErrorExcerpt :: Int -> Int -> Maybe (Int, Maybe Int) -> Text -> Text
decoratePostingErrorExcerpt absline relline mcols txt =
T.unlines $ js' <> ks' <> colmarkerline <> ms'
where
(ls,ms) = splitAt (relline+1) $ T.lines txt
(js,ks) = splitAt (length ls - 1) ls
(js',ks') = case ks of
[k] -> (map (lineprefix<>) js, [T.pack (show absline) <> " | " <> k])
_ -> ([], [])
ms' = map (lineprefix<>) ms
colmarkerline =
[lineprefix <> T.replicate (col-1) " " <> T.replicate regionw "^"
| Just (col, mendcol) <- [mcols]
, let regionw = 1 + maybe 0 (subtract col) mendcol
]
lineprefix = T.replicate marginw " " <> "| "
where marginw = length (show absline) + 1
-- | Find the 1-based index of the first posting in this transaction
-- satisfying the given predicate.
transactionFindPostingIndex :: (Posting -> Bool) -> Transaction -> Maybe Int
transactionFindPostingIndex ppredicate =
fmap fst . find (ppredicate.snd) . zip [1..] . tpostings

View File

@ -63,6 +63,8 @@ library
Hledger.Data.Valuation Hledger.Data.Valuation
Hledger.Query Hledger.Query
Hledger.Read Hledger.Read
Hledger.Read.Checks
Hledger.Read.Checks.Uniqueleafnames
Hledger.Read.Common Hledger.Read.Common
Hledger.Read.CsvReader Hledger.Read.CsvReader
Hledger.Read.JournalReader Hledger.Read.JournalReader
@ -86,6 +88,7 @@ library
Hledger.Utils.Text Hledger.Utils.Text
Text.Tabular.AsciiWide Text.Tabular.AsciiWide
other-modules: other-modules:
Hledger.Read.Error
Text.Megaparsec.Custom Text.Megaparsec.Custom
Text.WideString Text.WideString
Paths_hledger_lib Paths_hledger_lib

View File

@ -115,6 +115,8 @@ library:
- Hledger.Data.Valuation - Hledger.Data.Valuation
- Hledger.Query - Hledger.Query
- Hledger.Read - Hledger.Read
- Hledger.Read.Checks
- Hledger.Read.Checks.Uniqueleafnames
- Hledger.Read.Common - Hledger.Read.Common
- Hledger.Read.CsvReader - Hledger.Read.CsvReader
- Hledger.Read.JournalReader - Hledger.Read.JournalReader

View File

@ -18,7 +18,6 @@ import System.Console.CmdArgs.Explicit
import Hledger import Hledger
import Hledger.Cli.CliOptions import Hledger.Cli.CliOptions
import Hledger.Cli.Commands.Check.Ordereddates (journalCheckOrdereddates) import Hledger.Cli.Commands.Check.Ordereddates (journalCheckOrdereddates)
import Hledger.Cli.Commands.Check.Uniqueleafnames (journalCheckUniqueleafnames)
checkmode :: Mode RawOpts checkmode :: Mode RawOpts
checkmode = hledgerCommandMode checkmode = hledgerCommandMode

View File

@ -9,7 +9,9 @@ import Control.Monad (forM)
import Data.List (groupBy) import Data.List (groupBy)
import Text.Printf (printf) import Text.Printf (printf)
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
import Hledger.Read.Error (makeTransactionErrorExcerpt)
-- XXX does this need CliOpts ? Can it move to Hledger.Read.Checks ?
journalCheckOrdereddates :: CliOpts -> Journal -> Either String () journalCheckOrdereddates :: CliOpts -> Journal -> Either String ()
journalCheckOrdereddates CliOpts{reportspec_=rspec} j = do journalCheckOrdereddates CliOpts{reportspec_=rspec} j = do
let let
@ -18,7 +20,7 @@ journalCheckOrdereddates CliOpts{reportspec_=rspec} j = do
filets = filets =
groupBy (\t1 t2 -> transactionFile t1 == transactionFile t2) $ groupBy (\t1 t2 -> transactionFile t1 == transactionFile t2) $
filter (_rsQuery rspec `matchesTransaction`) $ filter (_rsQuery rspec `matchesTransaction`) $
jtxns $ journalApplyValuationFromOpts rspec j jtxns $ journalApplyValuationFromOpts rspec j -- XXX why apply valuation ?
checkunique = False -- boolopt "unique" rawopts XXX was supported by checkdates command checkunique = False -- boolopt "unique" rawopts XXX was supported by checkdates command
compare a b = if checkunique then getdate a < getdate b else getdate a <= getdate b compare a b = if checkunique then getdate a < getdate b else getdate a <= getdate b
where getdate = transactionDateFn ropts where getdate = transactionDateFn ropts

View File

@ -111,7 +111,6 @@ library
Hledger.Cli.Commands.Cashflow Hledger.Cli.Commands.Cashflow
Hledger.Cli.Commands.Check Hledger.Cli.Commands.Check
Hledger.Cli.Commands.Check.Ordereddates Hledger.Cli.Commands.Check.Ordereddates
Hledger.Cli.Commands.Check.Uniqueleafnames
Hledger.Cli.Commands.Close Hledger.Cli.Commands.Close
Hledger.Cli.Commands.Codes Hledger.Cli.Commands.Codes
Hledger.Cli.Commands.Commodities Hledger.Cli.Commands.Commodities

View File

@ -158,7 +158,6 @@ library:
- Hledger.Cli.Commands.Cashflow - Hledger.Cli.Commands.Cashflow
- Hledger.Cli.Commands.Check - Hledger.Cli.Commands.Check
- Hledger.Cli.Commands.Check.Ordereddates - Hledger.Cli.Commands.Check.Ordereddates
- Hledger.Cli.Commands.Check.Uniqueleafnames
- Hledger.Cli.Commands.Close - Hledger.Cli.Commands.Close
- Hledger.Cli.Commands.Codes - Hledger.Cli.Commands.Codes
- Hledger.Cli.Commands.Commodities - Hledger.Cli.Commands.Commodities