diff --git a/doc/lib.m4 b/doc/lib.m4 index 7511f9c26..f5863e750 100644 --- a/doc/lib.m4 +++ b/doc/lib.m4 @@ -147,6 +147,9 @@ m4_define({{_reportingoptions_}}, {{ : will transform the journal before any other processing by replacing the account name of every posting having the tag TAG with content VALUE by the account name "TAG:VALUE". : The TAG will only match if it is a full-length match. The pivot will only happen if the TAG is on a posting, not if it is on the transaction. If the tag value is a multi:level:account:name the new account name will be "TAG:multi:level:account:name". +`--anon` +: show anonymized accounts and payees + }} )m4_dnl m4_dnl m4_define({{_hledgerdescription_}}, {{ diff --git a/hledger/Hledger/Cli/CliOptions.hs b/hledger/Hledger/Cli/CliOptions.hs index 04d1b756a..70a1ebfdc 100644 --- a/hledger/Hledger/Cli/CliOptions.hs +++ b/hledger/Hledger/Cli/CliOptions.hs @@ -143,6 +143,7 @@ reportflags = [ ,flagReq ["depth"] (\s opts -> Right $ setopt "depth" s opts) "N" "hide accounts/postings deeper than N" ,flagNone ["empty","E"] (setboolopt "empty") "show items with zero amount, normally hidden" ,flagNone ["cost","B"] (setboolopt "cost") "show amounts in their cost price's commodity" + ,flagNone ["anon"] (setboolopt "anon") "output ledger with anonymized accounts and payees." ] -- | Common output-related flags: --output-file, --output-format... diff --git a/hledger/Hledger/Cli/Utils.hs b/hledger/Hledger/Cli/Utils.hs index 1dcfe6fb0..059b4c4c0 100644 --- a/hledger/Hledger/Cli/Utils.hs +++ b/hledger/Hledger/Cli/Utils.hs @@ -23,12 +23,15 @@ module Hledger.Cli.Utils ) where import Control.Exception as C +import Data.Hashable (hash) import Data.List import Data.Maybe import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.IO as T import Data.Time (Day) +import Data.Word +import Numeric import Safe (readMay) import System.Console.CmdArgs import System.Directory (getModificationTime, getDirectoryContents, copyFile) @@ -73,7 +76,7 @@ withJournalDo opts cmd = do rulespath <- rulesFilePathFromOpts opts journalpaths <- journalFilePathFromOpts opts ej <- readJournalFiles Nothing rulespath (not $ ignore_assertions_ opts) journalpaths - either error' (cmd opts . pivotByOpts opts . journalApplyAliases (aliasesFromOpts opts)) ej + either error' (cmd opts . pivotByOpts opts . anonymiseByOpts opts . journalApplyAliases (aliasesFromOpts opts)) ej -- | Apply the pivot transformation on a journal, if option is present. pivotByOpts :: CliOpts -> Journal -> Journal @@ -92,6 +95,30 @@ pivot tag j = j{jtxns = map pivotTrans . jtxns $ j} | _ <- tagTuple = p where tagTuple = find ((tag ==) . fst) . ptags $ p +-- | Apply the anonymisation transformation on a journal, if option is present +anonymiseByOpts :: CliOpts -> Journal -> Journal +anonymiseByOpts opts = + case maybestringopt "anon" . rawopts_ $ opts of + Just _ -> anonymise + Nothing -> id + +-- | Apply the anonymisation transformation on a journal +anonymise :: Journal -> Journal +anonymise j + = let + pAnons p = p { paccount = T.intercalate (T.pack ":") . map anon . T.splitOn (T.pack ":") . paccount $ p + , pcomment = T.empty + , ptransaction = fmap tAnons . ptransaction $ p + } + tAnons txn = txn { tpostings = map pAnons . tpostings $ txn + , tdescription = anon . tdescription $ txn + , tcomment = T.empty + } + in + j { jtxns = map tAnons . jtxns $ j } + where + anon = T.pack . flip showHex "" . (fromIntegral :: Int -> Word32) . hash + -- | Write some output to stdout or to a file selected by --output-file. writeOutput :: CliOpts -> String -> IO () writeOutput opts s = do diff --git a/hledger/hledger.cabal b/hledger/hledger.cabal index ded5270d1..782e8e1fd 100644 --- a/hledger/hledger.cabal +++ b/hledger/hledger.cabal @@ -98,6 +98,7 @@ library , cmdargs >=0.10 && <0.11 , csv , data-default >=0.5 + , hashable >=1.2.4 , haskeline >=0.6 && <=0.8 , HUnit , mtl diff --git a/hledger/package.yaml b/hledger/package.yaml index 5e0d9eb3e..bd8bf4089 100644 --- a/hledger/package.yaml +++ b/hledger/package.yaml @@ -111,6 +111,7 @@ library: - cmdargs >=0.10 && <0.11 - csv - data-default >=0.5 + - hashable >=1.2.4 - haskeline >=0.6 && <=0.8 - HUnit - mtl