diff --git a/hledger-lib/Hledger/Data/Journal.hs b/hledger-lib/Hledger/Data/Journal.hs index ce9c5fbc1..88361af9f 100644 --- a/hledger-lib/Hledger/Data/Journal.hs +++ b/hledger-lib/Hledger/Data/Journal.hs @@ -123,6 +123,7 @@ nullfilterspec = FilterSpec { ,acctpats=[] ,descpats=[] ,depth=Nothing + ,metadata=[] } journalFilePath :: Journal -> FilePath @@ -234,10 +235,12 @@ filterJournalTransactions FilterSpec{datespan=datespan ,acctpats=apats ,descpats=dpats ,depth=depth + ,metadata=md } = filterJournalTransactionsByClearedStatus cleared . filterJournalPostingsByDepth depth . filterJournalTransactionsByAccount apats . + filterJournalTransactionsByMetadata md . filterJournalTransactionsByDescription dpats . filterJournalTransactionsByDate datespan @@ -251,15 +254,22 @@ filterJournalPostings FilterSpec{datespan=datespan ,acctpats=apats ,descpats=dpats ,depth=depth + ,metadata=md } = filterJournalPostingsByRealness real . filterJournalPostingsByClearedStatus cleared . filterJournalPostingsByEmpty empty . filterJournalPostingsByDepth depth . filterJournalPostingsByAccount apats . + filterJournalTransactionsByMetadata md . filterJournalTransactionsByDescription dpats . filterJournalTransactionsByDate datespan +-- | Keep only transactions whose metadata matches all metadata specifications. +filterJournalTransactionsByMetadata :: [(String,String)] -> Journal -> Journal +filterJournalTransactionsByMetadata pats j@Journal{jtxns=ts} = j{jtxns=filter matchmd ts} + where matchmd t = all (`elem` tmetadata t) pats + -- | Keep only transactions whose description matches the description patterns. filterJournalTransactionsByDescription :: [String] -> Journal -> Journal filterJournalTransactionsByDescription pats j@Journal{jtxns=ts} = j{jtxns=filter matchdesc ts} diff --git a/hledger-lib/Hledger/Data/Types.hs b/hledger-lib/Hledger/Data/Types.hs index ea8f6f13f..6135f8564 100644 --- a/hledger-lib/Hledger/Data/Types.hs +++ b/hledger-lib/Hledger/Data/Types.hs @@ -263,5 +263,6 @@ data FilterSpec = FilterSpec { ,acctpats :: [String] -- ^ only include if matching these account patterns ,descpats :: [String] -- ^ only include if matching these description patterns ,depth :: Maybe Int + ,metadata :: [(String,String)] -- ^ only include if matching these metadata } deriving (Show) diff --git a/hledger-lib/Hledger/Reports.hs b/hledger-lib/Hledger/Reports.hs index 9a033766d..86493c135 100644 --- a/hledger-lib/Hledger/Reports.hs +++ b/hledger-lib/Hledger/Reports.hs @@ -177,8 +177,9 @@ filterSpecFromOpts opts@ReportOpts{..} d = FilterSpec { ,acctpats=apats ,descpats=dpats ,depth = depth_ + ,metadata = mds } - where (apats,dpats) = parsePatternArgs patterns_ + where (apats,dpats,mds) = parsePatternArgs patterns_ -- | Convert report options to a (new) query. queryFromOpts :: ReportOpts -> Day -> Query @@ -200,12 +201,21 @@ queryFromOpts opts@ReportOpts{..} d = -- strace $ -- follows: those prefixed with "desc:" are description patterns, all -- others are account patterns; also patterns prefixed with "not:" are -- negated. not: should come after desc: if both are used. -parsePatternArgs :: [String] -> ([String],[String]) -parsePatternArgs args = (as, ds') +-- pattern "tag" means the word after it should be interpreted as metadata +-- constraint. +parsePatternArgs :: [String] -> ([String],[String],[(String,String)]) +parsePatternArgs args = (as, ds', mds) where + (tags, args') = filterOutTags False [] [] args descprefix = "desc:" - (ds, as) = partition (descprefix `isPrefixOf`) args + (ds, as) = partition (descprefix `isPrefixOf`) args' ds' = map (drop (length descprefix)) ds + mds = map (\(a,b)->(a,tail b)) $ map (\t->span (/='=') t) tags + + filterOutTags _ tags args' [] = (reverse tags, reverse args') + filterOutTags False tags args' ("tag":xs) = filterOutTags True tags args' xs + filterOutTags False tags args' (x:xs) = filterOutTags False tags (x:args') xs + filterOutTags True tags args' (x:xs) = filterOutTags False (x:tags) args' xs ------------------------------------------------------------------------------- diff --git a/tests/metadata.test b/tests/metadata.test index a95f7bc03..6bdf97f0e 100644 --- a/tests/metadata.test +++ b/tests/metadata.test @@ -18,3 +18,28 @@ bin/hledger -f - print >>>2 >>>=0 + +bin/hledger -f - print tag key1=value +<<< +2010/01/01 + ; key:value + a 1 + b -1 +>>> +>>>2 +>>>=0 + +bin/hledger -f - print tag key=value +<<< +2010/01/01 + ; key:value + a 1 + b -1 +>>> +2010/01/01 + ; key:value + a 1 + b -1 + +>>>2 +>>>=0