packages feed

hledger-lib 1.18 → 1.18.1

raw patch · 27 files changed

+687/−610 lines, 27 files

Files

CHANGES.md view
@@ -1,6 +1,10 @@ Internal/api/developer-ish changes in the hledger-lib (and hledger) packages. For user-visible changes, see the hledger package changelog. +# 1.18.1 2020-06-21++- fix some doc typos (Martin Michlmayr)+ # 1.18 2020-06-07  - added: getHledgerCliOpts', takes an explicit argument list
Hledger/Data/Journal.hs view
@@ -179,18 +179,18 @@     ,jparseparentaccounts       = jparseparentaccounts       j2     ,jparsealiases              = jparsealiases              j2     -- ,jparsetransactioncount     = jparsetransactioncount     j1 +  jparsetransactioncount     j2-    ,jparsetimeclockentries     = jparsetimeclockentries j1 <> jparsetimeclockentries j2-    ,jincludefilestack          = jincludefilestack          j2+    ,jparsetimeclockentries     = jparsetimeclockentries     j1 <> jparsetimeclockentries     j2+    ,jincludefilestack          = jincludefilestack j2     ,jdeclaredaccounts          = jdeclaredaccounts          j1 <> jdeclaredaccounts          j2     ,jdeclaredaccounttypes      = jdeclaredaccounttypes      j1 <> jdeclaredaccounttypes      j2     ,jcommodities               = jcommodities               j1 <> jcommodities               j2     ,jinferredcommodities       = jinferredcommodities       j1 <> jinferredcommodities       j2-    ,jpricedirectives              = jpricedirectives              j1 <> jpricedirectives              j2-    ,jtransactionimpliedmarketprices = jtransactionimpliedmarketprices j1 <> jtransactionimpliedmarketprices j2+    ,jpricedirectives           = jpricedirectives           j1 <> jpricedirectives           j2+    ,jinferredmarketprices      = jinferredmarketprices      j1 <> jinferredmarketprices      j2     ,jtxnmodifiers              = jtxnmodifiers              j1 <> jtxnmodifiers              j2     ,jperiodictxns              = jperiodictxns              j1 <> jperiodictxns              j2     ,jtxns                      = jtxns                      j1 <> jtxns                      j2-    ,jfinalcommentlines         = jfinalcommentlines         j2  -- XXX discards j1's ?+    ,jfinalcommentlines         = jfinalcommentlines j2  -- XXX discards j1's ?     ,jfiles                     = jfiles                     j1 <> jfiles                     j2     ,jlastreadtime              = max (jlastreadtime j1) (jlastreadtime j2)     }@@ -211,8 +211,8 @@   ,jdeclaredaccounttypes      = M.empty   ,jcommodities               = M.empty   ,jinferredcommodities       = M.empty-  ,jpricedirectives              = []-  ,jtransactionimpliedmarketprices = []+  ,jpricedirectives           = []+  ,jinferredmarketprices      = []   ,jtxnmodifiers              = []   ,jperiodictxns              = []   ,jtxns                      = []@@ -1044,16 +1044,16 @@ -- been balanced and posting amounts have appropriate prices attached. journalInferMarketPricesFromTransactions :: Journal -> Journal journalInferMarketPricesFromTransactions j =-  j{jtransactionimpliedmarketprices =-       dbg4 "jtransactionimpliedmarketprices" $-       mapMaybe postingImpliedMarketPrice $ journalPostings j+  j{jinferredmarketprices =+       dbg4 "jinferredmarketprices" $+       mapMaybe postingInferredmarketPrice $ journalPostings j    }  -- | Make a market price equivalent to this posting's amount's unit -- price, if any. If the posting amount is multicommodity, only the -- first commodity amount is considered.-postingImpliedMarketPrice :: Posting -> Maybe MarketPrice-postingImpliedMarketPrice p@Posting{pamount} =+postingInferredmarketPrice :: Posting -> Maybe MarketPrice+postingInferredmarketPrice p@Posting{pamount} =   -- convert any total prices to unit prices   case mixedAmountTotalPriceToUnitPrice pamount of     Mixed ( Amount{acommodity=fromcomm, aprice = Just (UnitPrice Amount{acommodity=tocomm, aquantity=rate})} : _) ->
Hledger/Data/Types.hs view
@@ -470,9 +470,9 @@   ,jdeclaredaccounts      :: [(AccountName,AccountDeclarationInfo)] -- ^ Accounts declared by account directives, in parse order (after journal finalisation)   ,jdeclaredaccounttypes  :: M.Map AccountType [AccountName]        -- ^ Accounts whose type has been declared in account directives (usually 5 top-level accounts)   ,jcommodities           :: M.Map CommoditySymbol Commodity        -- ^ commodities and formats declared by commodity directives-  ,jinferredcommodities   :: M.Map CommoditySymbol AmountStyle      -- ^ commodities and formats inferred from journal amounts  TODO misnamed - jusedstyles+  ,jinferredcommodities   :: M.Map CommoditySymbol AmountStyle      -- ^ commodities and formats inferred from journal amounts  TODO misnamed, should be eg jusedstyles   ,jpricedirectives       :: [PriceDirective]                       -- ^ Declarations of market prices by P directives, in parse order (after journal finalisation)-  ,jtransactionimpliedmarketprices :: [MarketPrice]                 -- ^ Market prices implied by transactions, in parse order (after journal finalisation)+  ,jinferredmarketprices  :: [MarketPrice]                          -- ^ Market prices implied by transactions, in parse order (after journal finalisation)   ,jtxnmodifiers          :: [TransactionModifier]   ,jperiodictxns          :: [PeriodicTransaction]   ,jtxns                  :: [Transaction]
Hledger/Data/Valuation.hs view
@@ -52,6 +52,17 @@ ------------------------------------------------------------------------------ -- Types +-- | What kind of value conversion should be done on amounts ?+-- CLI: --value=cost|then|end|now|DATE[,COMM]+data ValuationType =+    AtCost     (Maybe CommoditySymbol)  -- ^ convert to cost commodity using transaction prices, then optionally to given commodity using market prices at posting date+  | AtThen     (Maybe CommoditySymbol)  -- ^ convert to default or given valuation commodity, using market prices at each posting's date+  | AtEnd      (Maybe CommoditySymbol)  -- ^ convert to default or given valuation commodity, using market prices at period end(s)+  | AtNow      (Maybe CommoditySymbol)  -- ^ convert to default or given valuation commodity, using current market prices+  | AtDate Day (Maybe CommoditySymbol)  -- ^ convert to default or given valuation commodity, using market prices on some date+  | AtDefault  (Maybe CommoditySymbol)  -- ^ works like AtNow in single period reports, like AtEnd in multiperiod reports+  deriving (Show,Data,Eq) -- Typeable+ -- | A snapshot of the known exchange rates between commodity pairs at a given date, -- as a graph allowing fast lookup and path finding, along with some helper data. data PriceGraph = PriceGraph {@@ -60,9 +71,9 @@     -- Node labels are commodities and edge labels are exchange rates,     -- which were either:     -- declared by P directives,-    -- implied by transaction prices,+    -- inferred from transaction prices,     -- inferred by reversing a declared rate,-    -- or inferred by reversing a transaction-implied rate.+    -- or inferred by reversing a transaction-inferred rate.     -- There will be at most one edge between each directed pair of commodities,     -- eg there can be one USD->EUR and one EUR->USD.   ,prNodemap :: NodeMap CommoditySymbol@@ -71,7 +82,7 @@     -- ^ The default valuation commodity for each source commodity.     --   These are used when a valuation commodity is not specified     --   (-V). They are the destination commodity of the latest-    --   (declared or transaction-implied, but not reverse) each+    --   (declared or inferred, but not reverse) each     --   source commodity's latest market price (on the date of this     --   graph).   }@@ -79,25 +90,38 @@  instance NFData PriceGraph --- | A price oracle is a magic function that looks up market prices--- (exchange rates) from one commodity to another (or if unspecified,--- to a default valuation commodity) on a given date, somewhat efficiently.+-- | A price oracle is a magic memoising function that efficiently+-- looks up market prices (exchange rates) from one commodity to+-- another (or if unspecified, to a default valuation commodity) on a+-- given date. type PriceOracle = (Day, CommoditySymbol, Maybe CommoditySymbol) -> Maybe (CommoditySymbol, Quantity) --- | What kind of value conversion should be done on amounts ?--- CLI: --value=cost|then|end|now|DATE[,COMM]-data ValuationType =-    AtCost     (Maybe CommoditySymbol)  -- ^ convert to cost commodity using transaction prices, then optionally to given commodity using market prices at posting date-  | AtThen     (Maybe CommoditySymbol)  -- ^ convert to default or given valuation commodity, using market prices at each posting's date-  | AtEnd      (Maybe CommoditySymbol)  -- ^ convert to default or given valuation commodity, using market prices at period end(s)-  | AtNow      (Maybe CommoditySymbol)  -- ^ convert to default or given valuation commodity, using current market prices-  | AtDate Day (Maybe CommoditySymbol)  -- ^ convert to default or given valuation commodity, using market prices on some date-  | AtDefault  (Maybe CommoditySymbol)  -- ^ works like AtNow in single period reports, like AtEnd in multiperiod reports-  deriving (Show,Data,Eq) -- Typeable+-- | Generate a price oracle (memoising price lookup function) from a+-- journal's directive-declared and transaction-inferred market+-- prices. For best performance, generate this only once per journal,+-- reusing it across reports if there are more than one, as+-- compoundBalanceCommand does.+-- The boolean argument is whether to infer market prices from+-- transactions or not.+journalPriceOracle :: Bool -> Journal -> PriceOracle+journalPriceOracle infer Journal{jpricedirectives, jinferredmarketprices} =+  let+    declaredprices = map priceDirectiveToMarketPrice jpricedirectives+    inferredprices = if infer then jinferredmarketprices else []+    makepricegraph = memo $ makePriceGraph declaredprices inferredprices+  in+    memo $ uncurry3 $ priceLookup makepricegraph +priceDirectiveToMarketPrice :: PriceDirective -> MarketPrice+priceDirectiveToMarketPrice PriceDirective{..} =+  MarketPrice{ mpdate = pddate+             , mpfrom = pdcommodity+             , mpto   = acommodity pdamount+             , mprate = aquantity pdamount+             }  --------------------------------------------------------------------------------- Valuation+-- Converting things to value  -- | Apply a specified valuation to this mixed amount, using the -- provided price oracle, commodity styles, reference dates, and@@ -135,8 +159,8 @@ -- use postingApplyValuation for that. --  -- This is all a bit complicated. See the reference doc at--- https://hledger.org/hledger.html#effect-of-value-on-reports--- (hledger_options.m4.md "Effect of --value on reports"), and #1083.+-- https://hledger.org/hledger.html#effect-of-valuation-on-reports+-- (hledger_options.m4.md "Effect of valuation on reports"), and #1083. -- amountApplyValuation :: PriceOracle -> M.Map CommoditySymbol AmountStyle -> Day -> Maybe Day -> Day -> Bool -> ValuationType -> Amount -> Amount amountApplyValuation priceoracle styles periodlast mreportlast today ismultiperiod v a =@@ -189,76 +213,33 @@ ------------------------------------------------------------------------------ -- Market price lookup --- From a journal's directive-declared and transaction-implied market--- prices, generate a memoising function that efficiently looks up--- exchange rates between commodities on any date. For best performance,--- you should generate this only once per journal, reusing it across--- reports if there are more than one (as in compoundBalanceCommand).-journalPriceOracle :: Journal -> PriceOracle-journalPriceOracle Journal{jpricedirectives, jtransactionimpliedmarketprices} =-  -- traceStack "journalPriceOracle" $-  let-    pricesatdate =-      memo $-      pricesAtDate jpricedirectives jtransactionimpliedmarketprices-  in-    memo $-    uncurry3 $-    priceLookup pricesatdate---- | Given a list of price directives in parse order, find the market--- value at the given date of one unit of a given source commodity, in--- a different specified valuation commodity, or a default valuation--- commodity.------ When the valuation commodity is specified, this looks for an--- exchange rate (market price) calculated in any of the following--- ways, in order of preference:------ 1. a declared market price (DMP) - a P directive giving the---    exchange rate from source commodity to valuation commodity------ 2. a transaction-implied market price (TMP) - a market price---    equivalent to the transaction price used in the latest---    transaction from source commodity to valuation commodity---    (on or before the valuation date)------ 3. a reverse declared market price (RDMP) - calculated by inverting---    a DMP------ 4. a reverse transaction-implied market price (RTMP) - calculated---    by inverting a TMP------ 5. an indirect market price (IMP) - calculated by combining the---    shortest chain of market prices (any of the above types) leading---    from source commodity to valuation commodity.------ When the valuation commodity is not specified, this looks for the--- latest applicable declared or transaction-implied price, and--- converts to the commodity mentioned in that price (the default--- valuation commodity).------ Note this default valuation commodity can vary across successive--- calls for different dates, since it depends on the price--- declarations in each period.+-- | Given a memoising price graph generator, a valuation date, a+-- source commodity and an optional valuation commodity, find the+-- value on that date of one unit of the source commodity in the+-- valuation commodity, or in a default valuation commodity. Returns+-- the valuation commodity that was specified or chosen, and the+-- quantity of it that one unit of the source commodity is worth. Or+-- if no applicable market price can be found or calculated, or if the+-- source commodity and the valuation commodity are the same, returns+-- Nothing. ----- This returns the valuation commodity that was specified or--- inferred, and the quantity of it that one unit of the source--- commodity is worth. Or if no applicable market price or chain of--- prices can be found, or the source commodity and the valuation--- commodity are the same, returns Nothing.+-- See makePriceGraph for how prices are determined.+-- Note that both market prices and default valuation commodities can+-- vary with valuation date, since that determines which market prices+-- are visible. -- priceLookup :: (Day -> PriceGraph) -> Day -> CommoditySymbol -> Maybe CommoditySymbol -> Maybe (CommoditySymbol, Quantity)-priceLookup pricesatdate d from mto =+priceLookup makepricegraph d from mto =   -- trace ("priceLookup ("++show d++", "++show from++", "++show mto++")") $   let     -- build a graph of the commodity exchange rates in effect on this day     -- XXX should hide these fgl details better-    PriceGraph{prGraph=g, prNodemap=m, prDefaultValuationCommodities=defaultdests} = pricesatdate d+    PriceGraph{prGraph=g, prNodemap=m, prDefaultValuationCommodities=defaultdests} =+      traceAt 1 ("valuation date: "++show d) $ makepricegraph d     fromnode = node m from     mto' = mto <|> mdefaultto       where-        mdefaultto = dbg4 ("default valuation commodity for "++T.unpack from) $+        mdefaultto = dbg1 ("default valuation commodity for "++T.unpack from) $                      M.lookup from defaultdests   in     case mto' of@@ -276,18 +257,17 @@             case sp fromnode tonode g :: Maybe [Node] of               Nothing    -> Nothing               Just nodes ->-                dbg ("market price "++intercalate "->" (map T.unpack comms)) $+                dbg ("market price for "++intercalate " -> " (map T.unpack comms)) $                 Just $ product $ pathEdgeLabels g nodes  -- convert to a single exchange rate                 where comms = catMaybes $ map (lab g) nodes            -- log a message and a Maybe Quantity, hiding Just/Nothing and limiting decimal places-          dbg msg = dbg4With (((msg++": ")++) . maybe "" (show . roundTo 8))+          dbg msg = dbg1With (((msg++": ")++) . maybe "" (show . roundTo 8))  tests_priceLookup =   let     d = parsedate-    a q c = amount{acommodity=c, aquantity=q}-    p date from q to = PriceDirective{pddate=d date, pdcommodity=from, pdamount=a q to}+    p date from q to = MarketPrice{mpdate=d date, mpfrom=from, mpto=to, mprate=q}     ps1 = [        p "2000/01/01" "A" 10 "B"       ,p "2000/01/01" "B" 10 "C"@@ -295,78 +275,113 @@       ,p "2000/01/01" "E"  2 "D"       ,p "2001/01/01" "A" 11 "B"       ]-    pricesatdate = pricesAtDate ps1 []+    makepricegraph = makePriceGraph ps1 []   in test "priceLookup" $ do-    priceLookup pricesatdate (d "1999/01/01") "A" Nothing    @?= Nothing-    priceLookup pricesatdate (d "2000/01/01") "A" Nothing    @?= Just ("B",10)-    priceLookup pricesatdate (d "2000/01/01") "B" (Just "A") @?= Just ("A",0.1)-    priceLookup pricesatdate (d "2000/01/01") "A" (Just "E") @?= Just ("E",500)----------------------------------------------------------------------------------- Building the price graph (network of commodity conversions) on a given day.+    priceLookup makepricegraph (d "1999/01/01") "A" Nothing    @?= Nothing+    priceLookup makepricegraph (d "2000/01/01") "A" Nothing    @?= Just ("B",10)+    priceLookup makepricegraph (d "2000/01/01") "B" (Just "A") @?= Just ("A",0.1)+    priceLookup makepricegraph (d "2000/01/01") "A" (Just "E") @?= Just ("E",500) --- | Convert a list of market price directives in parse order, and a--- list of transaction-implied market prices in parse order, to a--- graph of the effective exchange rates between commodity pairs on--- the given day.-pricesAtDate :: [PriceDirective] -> [MarketPrice] -> Day -> PriceGraph-pricesAtDate pricedirectives transactionimpliedmarketprices d =-  -- trace ("pricesAtDate ("++show d++")") $+-- | Build the graph of commodity conversion prices for a given day.+-- Converts a list of declared market prices in parse order, and a+-- list of transaction-inferred market prices in parse order, to a+-- graph of all known exchange rates between commodity pairs in effect+-- on that day. Cf hledger.m4.md -> Valuation:+--+-- hledger looks for a market price (exchange rate) from commodity A+-- to commodity B in one or more of these ways, in this order of+-- preference:+--+-- 1. A *declared market price* or *inferred market price*:+--    A's latest market price in B on or before the valuation date+--    as declared by a P directive, or (with the `--infer-value` flag)+--    inferred from transaction prices.+--   +-- 2. A *reverse market price*:+--    the inverse of a declared or inferred market price from B to A.+-- +-- 3. A *chained market price*:+--    a synthetic price formed by combining the shortest chain of market+--    prices (any of the above types) leading from A to B.+--+-- 1 and 2 form the edges of the price graph, and we can query it for+-- 3 (which is the reason we use a graph).+--+-- We also identify each commodity's default valuation commodity, if+-- any. For each commodity A, hledger picks a default valuation+-- commodity as follows, in this order of preference:+--+-- 1. The price commodity from the latest declared market price for A+--    on or before valuation date.+--+-- 2. The price commodity from the latest declared market price for A+--    on any date. (Allows conversion to proceed if there are inferred+--    prices before the valuation date.)+--+-- 3. If there are no P directives at all (any commodity or date), and+--    the `--infer-value` flag is used, then the price commodity from+--    the latest transaction price for A on or before valuation date.+--+makePriceGraph :: [MarketPrice] -> [MarketPrice] -> Day -> PriceGraph+makePriceGraph alldeclaredprices allinferredprices d =+  dbg9 ("makePriceGraph "++show d) $   PriceGraph{prGraph=g, prNodemap=m, prDefaultValuationCommodities=defaultdests}   where-    declaredandimpliedprices = latestPriceForEachPairOn pricedirectives transactionimpliedmarketprices d+    -- prices in effect on date d, either declared or inferred+    visibledeclaredprices = filter ((<=d).mpdate) alldeclaredprices+    visibleinferredprices = filter ((<=d).mpdate) allinferredprices+    declaredandinferredprices = dbg2 "declaredandinferredprices" $+      effectiveMarketPrices visibledeclaredprices visibleinferredprices -    -- infer any additional reverse prices not already declared or implied-    reverseprices =-      dbg5 "reverseprices" $-      map marketPriceReverse declaredandimpliedprices \\ declaredandimpliedprices+    -- infer any additional reverse prices not already declared or inferred+    reverseprices = dbg2 "reverseprices" $+      map marketPriceReverse declaredandinferredprices \\ declaredandinferredprices      -- build the graph and associated node map     (g, m) =       mkMapGraph-      (dbg5 "g nodelabels" $ sort allcomms) -- this must include all nodes mentioned in edges-      (dbg5 "g edges"      $ [(mpfrom, mpto, mprate) | MarketPrice{..} <- prices])+      (dbg9 "price graph labels" $ sort allcomms) -- this must include all nodes mentioned in edges+      (dbg9 "price graph edges" $ [(mpfrom, mpto, mprate) | MarketPrice{..} <- prices])       :: (Gr CommoditySymbol Quantity, NodeMap CommoditySymbol)       where-        prices   = declaredandimpliedprices ++ reverseprices+        prices   = declaredandinferredprices ++ reverseprices         allcomms = map mpfrom prices -    -- save the forward prices' destinations as the default valuation-    -- commodity for those source commodities-    defaultdests = M.fromList [(mpfrom,mpto) | MarketPrice{..} <- declaredandimpliedprices]+    -- determine a default valuation commodity for each source commodity+    -- somewhat but not quite like effectiveMarketPrices+    defaultdests = M.fromList [(mpfrom,mpto) | MarketPrice{..} <- pricesfordefaultcomms]+      where+        pricesfordefaultcomms = dbg2 "prices for choosing default valuation commodities, by date then parse order" $+          ps+          & zip [1..]  -- label items with their parse order+          & sortBy (compare `on` (\(parseorder,MarketPrice{..})->(mpdate,parseorder)))  -- sort by increasing date then increasing parse order+          & map snd    -- discard labels+          where+            ps | not $ null visibledeclaredprices = visibledeclaredprices+               | not $ null alldeclaredprices     = alldeclaredprices+               | otherwise                        = visibleinferredprices  -- will be null without --infer-value --- From a list of price directives in parse order, and a list of--- transaction-implied market prices in parse order, get the effective--- price on the given date for each commodity pair. That is, the--- latest declared or transaction-implied price dated on or before--- that day, with declared prices taking precedence.-latestPriceForEachPairOn :: [PriceDirective] -> [MarketPrice] -> Day -> [MarketPrice]-latestPriceForEachPairOn pricedirectives transactionimpliedmarketprices d =-  dbg5 "latestPriceForEachPairOn" $+-- | Given a list of P-declared market prices in parse order and a+-- list of transaction-inferred market prices in parse order, select+-- just the latest prices that are in effect for each commodity pair.+-- That is, for each commodity pair, the latest price by date then+-- parse order, with declared prices having precedence over inferred+-- prices on the same day.+effectiveMarketPrices :: [MarketPrice] -> [MarketPrice] -> [MarketPrice]+effectiveMarketPrices declaredprices inferredprices =   let-    -- consider only declarations/transactions before the valuation date-    declaredprices = map priceDirectiveToMarketPrice $ filter ((<=d).pddate) pricedirectives-    transactionimpliedmarketprices' = filter ((<=d).mpdate) transactionimpliedmarketprices-    -- label the items with their precedence and then their parse order-    declaredprices'                  = [(1, i, p) | (i,p) <- zip [1..] declaredprices]-    transactionimpliedmarketprices'' = [(0, i, p) | (i,p) <- zip [1..] transactionimpliedmarketprices']+    -- label each item with its same-day precedence, then parse order+    declaredprices' = [(1, i, p) | (i,p) <- zip [1..] declaredprices]+    inferredprices' = [(0, i, p) | (i,p) <- zip [1..] inferredprices]   in     -- combine-    declaredprices' ++ transactionimpliedmarketprices''-    -- sort by newest date then highest precedence then latest parse order+    declaredprices' ++ inferredprices'+    -- sort by decreasing date then decreasing precedence then decreasing parse order     & sortBy (flip compare `on` (\(precedence,parseorder,mp)->(mpdate mp,precedence,parseorder)))     -- discard the sorting labels     & map third3-    -- keep only the first (ie the newest, highest precedence and latest parsed) price for each pair+    -- keep only the first (ie the newest, highest precedence, latest parsed) price for each pair     & nubSortBy (compare `on` (\(MarketPrice{..})->(mpfrom,mpto)))--priceDirectiveToMarketPrice :: PriceDirective -> MarketPrice-priceDirectiveToMarketPrice PriceDirective{..} =-  MarketPrice{ mpdate = pddate-             , mpfrom = pdcommodity-             , mpto   = acommodity pdamount-             , mprate = aquantity pdamount-             }  marketPriceReverse :: MarketPrice -> MarketPrice marketPriceReverse mp@MarketPrice{..} = mp{mpfrom=mpto, mpto=mpfrom, mprate=1/mprate}
Hledger/Read.hs view
@@ -111,7 +111,7 @@ readJournal iopts mpath txt = do   let r :: Reader IO =         fromMaybe JournalReader.reader $ findReader (mformat_ iopts) mpath-  dbg1IO "trying reader" (rFormat r)+  dbg7IO "trying reader" (rFormat r)   (runExceptT . (rReadFn r) iopts (fromMaybe "(string)" mpath)) txt  -- | Read the default journal file specified by the environment, or raise an error.
Hledger/Read/CsvReader.hs view
@@ -382,7 +382,7 @@           }  blankorcommentlinep :: CsvRulesParser ()-blankorcommentlinep = lift (dbgparse 3 "trying blankorcommentlinep") >> choiceInState [blanklinep, commentlinep]+blankorcommentlinep = lift (dbgparse 8 "trying blankorcommentlinep") >> choiceInState [blanklinep, commentlinep]  blanklinep :: CsvRulesParser () blanklinep = lift (skipMany spacenonewline) >> newline >> return () <?> "blank line"@@ -395,7 +395,7 @@  directivep :: CsvRulesParser (DirectiveName, String) directivep = (do-  lift $ dbgparse 3 "trying directive"+  lift $ dbgparse 8 "trying directive"   d <- fmap T.unpack $ choiceInState $ map (lift . string . T.pack) directives   v <- (((char ':' >> lift (many spacenonewline)) <|> lift (some spacenonewline)) >> directivevalp)        <|> (optional (char ':') >> lift (skipMany spacenonewline) >> lift eolof >> return "")@@ -418,7 +418,7 @@  fieldnamelistp :: CsvRulesParser [CsvFieldName] fieldnamelistp = (do-  lift $ dbgparse 3 "trying fieldnamelist"+  lift $ dbgparse 8 "trying fieldnamelist"   string "fields"   optional $ char ':'   lift (skipSome spacenonewline)@@ -444,7 +444,7 @@  fieldassignmentp :: CsvRulesParser (HledgerFieldName, FieldTemplate) fieldassignmentp = do-  lift $ dbgparse 3 "trying fieldassignmentp"+  lift $ dbgparse 8 "trying fieldassignmentp"   f <- journalfieldnamep   v <- choiceInState [ assignmentseparatorp >> fieldvalp                      , lift eolof >> return ""@@ -454,7 +454,7 @@  journalfieldnamep :: CsvRulesParser String journalfieldnamep = do-  lift (dbgparse 2 "trying journalfieldnamep")+  lift (dbgparse 8 "trying journalfieldnamep")   T.unpack <$> choiceInState (map (lift . string . T.pack) journalfieldnames)  maxpostings = 99@@ -489,7 +489,7 @@  assignmentseparatorp :: CsvRulesParser () assignmentseparatorp = do-  lift $ dbgparse 3 "trying assignmentseparatorp"+  lift $ dbgparse 8 "trying assignmentseparatorp"   _ <- choiceInState [ lift (skipMany spacenonewline) >> char ':' >> lift (skipMany spacenonewline)                      , lift (skipSome spacenonewline)                      ]@@ -497,13 +497,13 @@  fieldvalp :: CsvRulesParser String fieldvalp = do-  lift $ dbgparse 2 "trying fieldvalp"+  lift $ dbgparse 8 "trying fieldvalp"   anySingle `manyTill` lift eolof  -- A conditional block: one or more matchers, one per line, followed by one or more indented rules. conditionalblockp :: CsvRulesParser ConditionalBlock conditionalblockp = do-  lift $ dbgparse 3 "trying conditionalblockp"+  lift $ dbgparse 8 "trying conditionalblockp"   string "if" >> lift (skipMany spacenonewline) >> optional newline   ms <- some matcherp   as <- many (try $ lift (skipSome spacenonewline) >> fieldassignmentp)@@ -520,7 +520,7 @@ -- A pattern on the whole line, not beginning with a csv field reference. recordmatcherp :: CsvRulesParser Matcher recordmatcherp = do-  lift $ dbgparse 2 "trying matcherp"+  lift $ dbgparse 8 "trying matcherp"   -- pos <- currentPos   -- _  <- optional (matchoperatorp >> lift (skipMany spacenonewline) >> optional newline)   r <- regexp@@ -535,7 +535,7 @@ -- %description chez jacques fieldmatcherp :: CsvRulesParser Matcher fieldmatcherp = do-  lift $ dbgparse 2 "trying fieldmatcher"+  lift $ dbgparse 8 "trying fieldmatcher"   -- An optional fieldname (default: "all")   -- f <- fromMaybe "all" `fmap` (optional $ do   --        f' <- fieldnamep@@ -551,7 +551,7 @@  csvfieldreferencep :: CsvRulesParser CsvFieldReference csvfieldreferencep = do-  lift $ dbgparse 3 "trying csvfieldreferencep"+  lift $ dbgparse 8 "trying csvfieldreferencep"   char '%'   f <- fieldnamep   return $ '%' : quoteIfNeeded f@@ -559,7 +559,7 @@ -- A single regular expression regexp :: CsvRulesParser RegexpPattern regexp = do-  lift $ dbgparse 3 "trying regexp"+  lift $ dbgparse 8 "trying regexp"   -- notFollowedBy matchoperatorp   c <- lift nonspace   cs <- anySingle `manyTill` lift eolof@@ -606,12 +606,12 @@   rulestext <-     if rulesfileexists     then do-      dbg1IO "using conversion rules file" rulesfile+      dbg7IO "using conversion rules file" rulesfile       readFilePortably rulesfile >>= expandIncludes (takeDirectory rulesfile)     else       return $ defaultRulesText rulesfile   rules <- either throwerr return $ parseAndValidateCsvRules rulesfile rulestext-  dbg2IO "rules" rules+  dbg7IO "rules" rules    -- parse the skip directive's value, if any   let skiplines = case getDirective "skip" rules of@@ -623,12 +623,12 @@   -- parsec seems to fail if you pass it "-" here TODO: try again with megaparsec   let parsecfilename = if csvfile == "-" then "(stdin)" else csvfile   let separator = fromMaybe ',' (getDirective "separator" rules >>= parseSeparator)-  dbg2IO "separator" separator+  dbg7IO "separator" separator   records <- (either throwerr id .-              dbg2 "validateCsv" . validateCsv rules skiplines .-              dbg2 "parseCsv")+              dbg8 "validateCsv" . validateCsv rules skiplines .+              dbg8 "parseCsv")              `fmap` parseCsv separator parsecfilename csvdata-  dbg1IO "first 3 csv records" $ take 3 records+  dbg7IO "first 3 csv records" $ take 3 records    -- identify header lines   -- let (headerlines, datalines) = identifyHeaderLines records@@ -653,10 +653,10 @@     -- than one date and the first date is more recent than the last):     -- reverse them to get same-date transactions ordered chronologically.     txns' =-      (if newestfirst || mseemsnewestfirst == Just True then reverse else id) txns+      (if newestfirst || mdataseemsnewestfirst == Just True then reverse else id) txns       where-        newestfirst = dbg3 "newestfirst" $ isJust $ getDirective "newest-first" rules-        mseemsnewestfirst = dbg3 "mseemsnewestfirst" $+        newestfirst = dbg7 "newestfirst" $ isJust $ getDirective "newest-first" rules+        mdataseemsnewestfirst = dbg7 "mdataseemsnewestfirst" $           case nub $ map tdate txns of             ds | length ds > 1 -> Just $ head ds > last ds             _                  -> Nothing@@ -1060,7 +1060,7 @@ getEffectiveAssignment rules record f = lastMay $ map snd $ assignments   where     -- all active assignments to field f, in order-    assignments = dbg2 "assignments" $ filter ((==f).fst) $ toplevelassignments ++ conditionalassignments+    assignments = dbg8 "assignments" $ filter ((==f).fst) $ toplevelassignments ++ conditionalassignments       where         -- all top level field assignments         toplevelassignments    = rassignments rules@@ -1077,20 +1077,20 @@                 matcherMatches :: Matcher -> Bool                 matcherMatches (RecordMatcher pat) = regexMatchesCI pat' wholecsvline                   where-                    pat' = dbg3 "regex" pat+                    pat' = dbg8 "regex" pat                     -- A synthetic whole CSV record to match against. Note, this can be                     -- different from the original CSV data:                     -- - any whitespace surrounding field values is preserved                     -- - any quotes enclosing field values are removed                     -- - and the field separator is always comma                     -- which means that a field containing a comma will look like two fields.-                    wholecsvline = dbg3 "wholecsvline" $ intercalate "," record+                    wholecsvline = dbg8 "wholecsvline" $ intercalate "," record                 matcherMatches (FieldMatcher csvfieldref pat) = regexMatchesCI pat csvfieldvalue                   where                     -- the value of the referenced CSV field to match against.-                    csvfieldvalue = dbg3 "csvfieldvalue" $ replaceCsvFieldReference rules record csvfieldref+                    csvfieldvalue = dbg8 "csvfieldvalue" $ replaceCsvFieldReference rules record csvfieldref --- | Render a field assigment's template, possibly interpolating referenced+-- | Render a field assignment's template, possibly interpolating referenced -- CSV field values. Outer whitespace is removed from interpolated values. renderTemplate ::  CsvRules -> CsvRecord -> FieldTemplate -> String renderTemplate rules record t = regexReplaceBy "%[A-z0-9_-]+" (replaceCsvFieldReference rules record) t
Hledger/Read/JournalReader.hs view
@@ -296,7 +296,7 @@       -- on journal. Duplicating readJournal a bit here.       let r = fromMaybe reader $ findReader Nothing (Just prefixedpath)           parser = rParser r-      dbg1IO "trying reader" (rFormat r)+      dbg7IO "trying reader" (rFormat r)       updatedChildj <- journalAddFile (filepath, childInput) <$>                         parseIncludeFile parser initChildj filepath childInput @@ -425,7 +425,7 @@     pure $ (off, amount)   lift (skipMany spacenonewline)   _ <- lift followingcommentp-  let comm = Commodity{csymbol=acommodity, cformat=Just $ dbg2 "style from commodity directive" astyle}+  let comm = Commodity{csymbol=acommodity, cformat=Just $ dbg7 "style from commodity directive" astyle}   if asdecimalpoint astyle == Nothing   then customFailure $ parseErrorAt off pleaseincludedecimalpoint   else modify' (\j -> j{jcommodities=M.insert acommodity comm $ jcommodities j})@@ -469,7 +469,7 @@     then       if asdecimalpoint astyle == Nothing       then customFailure $ parseErrorAt off pleaseincludedecimalpoint-      else return $ dbg2 "style from format subdirective" astyle+      else return $ dbg7 "style from format subdirective" astyle     else customFailure $ parseErrorAt off $          printf "commodity directive symbol \"%s\" and format directive symbol \"%s\" should be the same" expectedsym acommodity 
Hledger/Reports/AccountTransactionsReport.hs view
@@ -102,7 +102,7 @@     ts3 = filter (matchesTransaction thisacctq . filterTransactionPostings (And [realq, statusq])) ts2      -- maybe convert these transactions to cost or value-    prices = journalPriceOracle j+    prices = journalPriceOracle (infer_value_ ropts) j     styles = journalCommodityStyles j     periodlast =       fromMaybe (error' "journalApplyValuation: expected a non-empty journal") $ -- XXX shouldn't happen
Hledger/Reports/BalanceReport.hs view
@@ -70,8 +70,9 @@   (if invert_ then brNegate  else id) $   (mappedsorteditems, mappedtotal)     where-      -- dbg1 = const id -- exclude from debug output-      dbg1 s = let p = "balanceReport" in Hledger.Utils.dbg1 (p++" "++s)  -- add prefix in debug output+      -- dbg = const id -- exclude from debug output+      dbg s = let p = "balanceReport" in Hledger.Utils.dbg4 (p++" "++s)  -- add prefix in debug output+      dbg' s = let p = "balanceReport" in Hledger.Utils.dbg5 (p++" "++s)  -- add prefix in debug output        -- Get all the summed accounts & balances, according to the query, as an account tree.       -- If doing cost valuation, amounts will be converted to cost first.@@ -81,27 +82,31 @@       -- per hledger_options.m4.md "Effect of --value on reports".       valuedaccttree = mapAccounts avalue accttree         where-          avalue a@Account{..} = a{aebalance=bvalue aebalance, aibalance=bvalue aibalance}+          avalue a@Account{..} = a{aebalance=maybevalue aebalance, aibalance=maybevalue aibalance}             where-              bvalue = maybe id (mixedAmountApplyValuation (journalPriceOracle j) (journalCommodityStyles j) periodlast mreportlast today multiperiod) value_+              maybevalue = maybe id applyvaluation value_                 where-                  periodlast =-                    fromMaybe (error' "balanceReport: expected a non-empty journal") $ -- XXX shouldn't happen-                    reportPeriodOrJournalLastDay ropts j-                  mreportlast = reportPeriodLastDay ropts-                  today = fromMaybe (error' "balanceReport: could not pick a valuation date, ReportOpts today_ is unset") today_-                  multiperiod = interval_ /= NoInterval+                  applyvaluation = mixedAmountApplyValuation priceoracle styles periodlast mreportlast today multiperiod+                    where+                      priceoracle = journalPriceOracle infer_value_ j+                      styles = journalCommodityStyles j+                      periodlast = fromMaybe+                                   (error' "balanceReport: expected a non-empty journal") $ -- XXX shouldn't happen+                                   reportPeriodOrJournalLastDay ropts j+                      mreportlast = reportPeriodLastDay ropts+                      today = fromMaybe (error' "balanceReport: could not pick a valuation date, ReportOpts today_ is unset") today_+                      multiperiod = interval_ /= NoInterval        -- Modify this tree for display - depth limit, boring parents, zeroes - and convert to a list.       displayaccts :: [Account]           | queryDepth q == 0 =-                         dbg1 "displayaccts" $+                         dbg' "displayaccts" $                          take 1 $ clipAccountsAndAggregate (queryDepth q) $ flattenAccounts valuedaccttree-          | flat_ ropts = dbg1 "displayaccts" $+          | flat_ ropts = dbg' "displayaccts" $                          filterzeros $                          filterempty $                          drop 1 $ clipAccountsAndAggregate (queryDepth q) $ flattenAccounts valuedaccttree-          | otherwise  = dbg1 "displayaccts" $+          | otherwise  = dbg' "displayaccts" $                          filter (not.aboring) $                          drop 1 $ flattenAccounts $                          markboring $@@ -116,7 +121,7 @@             markboring  = if no_elide_ then id else markBoringParentAccounts        -- Make a report row for each account.-      items = dbg1 "items" $ map (balanceReportItem ropts q) displayaccts+      items = dbg "items" $ map (balanceReportItem ropts q) displayaccts        -- Sort report rows (except sorting by amount in tree mode, which was done above).       sorteditems@@ -139,17 +144,17 @@               sortedrows = sortAccountItemsLike sortedanames anamesandrows        -- Calculate the grand total.-      total | not (flat_ ropts) = dbg1 "total" $ sum [amt | (_,_,indent,amt) <- items, indent == 0]-            | otherwise         = dbg1 "total" $+      total | not (flat_ ropts) = dbg "total" $ sum [amt | (_,_,indent,amt) <- items, indent == 0]+            | otherwise         = dbg "total" $                                   if flatShowsExclusiveBalance                                   then sum $ map fourth4 items                                   else sum $ map aebalance $ clipAccountsAndAggregate 1 displayaccts              -- Calculate percentages if needed.-      mappedtotal | percent_  = dbg1 "mappedtotal" $ total `perdivide` total+      mappedtotal | percent_  = dbg "mappedtotal" $ total `perdivide` total                   | otherwise = total       mappedsorteditems | percent_ =-                            dbg1 "mappedsorteditems" $+                            dbg "mappedsorteditems" $                             map (\(fname, sname, indent, amount) -> (fname, sname, indent, amount `perdivide` total)) sorteditems                         | otherwise = sorteditems 
Hledger/Reports/EntriesReport.hs view
@@ -40,7 +40,7 @@     tvalue t@Transaction{..} = t{tpostings=map pvalue tpostings}       where         pvalue p = maybe p-          (postingApplyValuation (journalPriceOracle j) (journalCommodityStyles j) periodlast mreportlast today False p)+          (postingApplyValuation (journalPriceOracle infer_value_ j) (journalCommodityStyles j) periodlast mreportlast today False p)           value_           where             periodlast  = fromMaybe today $ reportPeriodOrJournalLastDay ropts j
Hledger/Reports/MultiBalanceReport.hs view
@@ -72,7 +72,11 @@ -- hledger's most powerful and useful report, used by the balance -- command (in multiperiod mode) and (via multiBalanceReport') by the bs/cf/is commands. multiBalanceReport :: Day -> ReportOpts -> Journal -> MultiBalanceReport-multiBalanceReport today ropts j = multiBalanceReportWith ropts (queryFromOpts today ropts) j (journalPriceOracle j)+multiBalanceReport today ropts j =+  multiBalanceReportWith ropts q j (journalPriceOracle infer j)+  where+    q = queryFromOpts today ropts+    infer = infer_value_ ropts  -- | A helper for multiBalanceReport. This one takes an explicit Query -- instead of deriving one from ReportOpts, and an extra argument, a@@ -85,49 +89,52 @@   (if invert_ then prNegate else id) $   PeriodicReport colspans mappedsortedrows mappedtotalsrow     where-      dbg1 s = let p = "multiBalanceReport" in Hledger.Utils.dbg1 (p++" "++s)  -- add prefix in this function's debug output-      -- dbg1 = const id  -- exclude this function from debug output+      -- add a prefix to this function's debug output+      dbg   s = let p = "multiBalanceReport" in Hledger.Utils.dbg3 (p++" "++s)+      dbg'  s = let p = "multiBalanceReport" in Hledger.Utils.dbg4 (p++" "++s)+      dbg'' s = let p = "multiBalanceReport" in Hledger.Utils.dbg5 (p++" "++s)+      -- dbg = const id  -- exclude this function from debug output        ----------------------------------------------------------------------       -- 1. Queries, report/column dates. -      symq       = dbg1 "symq"   $ filterQuery queryIsSym $ dbg1 "requested q" q-      depthq     = dbg1 "depthq" $ filterQuery queryIsDepth q+      symq       = dbg "symq"   $ filterQuery queryIsSym $ dbg "requested q" q+      depthq     = dbg "depthq" $ filterQuery queryIsDepth q       depth      = queryDepth depthq-      depthless  = dbg1 "depthless" . filterQuery (not . queryIsDepth)-      datelessq  = dbg1 "datelessq"  $ filterQuery (not . queryIsDateOrDate2) q+      depthless  = dbg "depthless" . filterQuery (not . queryIsDepth)+      datelessq  = dbg "datelessq"  $ filterQuery (not . queryIsDateOrDate2) q       dateqcons  = if date2_ then Date2 else Date       -- The date span specified by -b/-e/-p options and query args if any.-      requestedspan  = dbg1 "requestedspan"  $ queryDateSpan date2_ q+      requestedspan  = dbg "requestedspan"  $ queryDateSpan date2_ q       -- If the requested span is open-ended, close it using the journal's end dates.       -- This can still be the null (open) span if the journal is empty.-      requestedspan' = dbg1 "requestedspan'" $ requestedspan `spanDefaultsFrom` journalDateSpan date2_ j+      requestedspan' = dbg "requestedspan'" $ requestedspan `spanDefaultsFrom` journalDateSpan date2_ j       -- The list of interval spans enclosing the requested span.       -- This list can be empty if the journal was empty,       -- or if hledger-ui has added its special date:-tomorrow to the query       -- and all txns are in the future.-      intervalspans  = dbg1 "intervalspans"  $ splitSpan interval_ requestedspan'+      intervalspans  = dbg "intervalspans"  $ splitSpan interval_ requestedspan'       -- The requested span enlarged to enclose a whole number of intervals.       -- This can be the null span if there were no intervals.-      reportspan     = dbg1 "reportspan"     $ DateSpan (maybe Nothing spanStart $ headMay intervalspans)+      reportspan     = dbg "reportspan"     $ DateSpan (maybe Nothing spanStart $ headMay intervalspans)                                                         (maybe Nothing spanEnd   $ lastMay intervalspans)       mreportstart = spanStart reportspan       -- The user's query with no depth limit, and expanded to the report span       -- if there is one (otherwise any date queries are left as-is, which       -- handles the hledger-ui+future txns case above).-      reportq   = dbg1 "reportq" $ depthless $+      reportq   = dbg "reportq" $ depthless $         if reportspan == nulldatespan         then q         else And [datelessq, reportspandatesq]           where-            reportspandatesq = dbg1 "reportspandatesq" $ dateqcons reportspan+            reportspandatesq = dbg "reportspandatesq" $ dateqcons reportspan       -- The date spans to be included as report columns.-      colspans :: [DateSpan] = dbg1 "colspans" $ splitSpan interval_ displayspan+      colspans :: [DateSpan] = dbg "colspans" $ splitSpan interval_ displayspan         where           displayspan-            | empty_    = dbg1 "displayspan (-E)" reportspan                              -- all the requested intervals-            | otherwise = dbg1 "displayspan" $ requestedspan `spanIntersect` matchedspan  -- exclude leading/trailing empty intervals-          matchedspan = dbg1 "matchedspan" . daysSpan $ map snd ps+            | empty_    = dbg "displayspan (-E)" reportspan                              -- all the requested intervals+            | otherwise = dbg "displayspan" $ requestedspan `spanIntersect` matchedspan  -- exclude leading/trailing empty intervals+          matchedspan = dbg "matchedspan" . daysSpan $ map snd ps        -- If doing cost valuation, convert amounts to cost.       j' = journalSelectingAmountFromOpts ropts j@@ -137,9 +144,9 @@        -- Balances at report start date, from all earlier postings which otherwise match the query.       -- These balances are unvalued except maybe converted to cost.-      startbals :: [(AccountName, MixedAmount)] = dbg1 "startbals" $ map (\(a,_,_,b) -> (a,b)) startbalanceitems+      startbals :: [(AccountName, MixedAmount)] = dbg' "startbals" $ map (\(a,_,_,b) -> (a,b)) startbalanceitems         where-          (startbalanceitems,_) = dbg1 "starting balance report" $ balanceReport ropts''{value_=Nothing, percent_=False} startbalq j'+          (startbalanceitems,_) = dbg'' "starting balance report" $ balanceReport ropts''{value_=Nothing, percent_=False} startbalq j'             where               ropts' | tree_ ropts = ropts{no_elide_=True}                      | otherwise   = ropts{accountlistmode_=ALFlat}@@ -149,14 +156,14 @@               -- q projected back before the report start date.               -- When there's no report start date, in case there are future txns (the hledger-ui case above),               -- we use emptydatespan to make sure they aren't counted as starting balance.-              startbalq = dbg1 "startbalq" $ And [datelessq, dateqcons precedingspan]+              startbalq = dbg'' "startbalq" $ And [datelessq, dateqcons precedingspan]                 where                   precedingspan = case mreportstart of                                   Just d  -> DateSpan Nothing (Just d)                                   Nothing -> emptydatespan       -- The matched accounts with a starting balance. All of these should appear       -- in the report even if they have no postings during the report period.-      startaccts = dbg1 "startaccts" $ map fst startbals+      startaccts = dbg'' "startaccts" $ map fst startbals       -- Helpers to look up an account's starting balance.       startingBalanceFor a = fromMaybe nullmixedamt $ lookup a startbals @@ -165,7 +172,7 @@        -- Postings matching the query within the report period.       ps :: [(Posting, Day)] =-          dbg1 "ps" $+          dbg'' "ps" $           map postingWithDate $           journalPostings $           filterJournalAmounts symq $      -- remove amount parts excluded by cur:@@ -178,7 +185,7 @@        -- Group postings into their columns, with the column end dates.       colps :: [([Posting], Maybe Day)] =-          dbg1 "colps"+          dbg'' "colps"           [ (posts, end) | (DateSpan _ end, posts) <- M.toList colMap ]         where           colMap = foldr addPosting emptyMap ps@@ -199,7 +206,7 @@                 | tree_ ropts = filter ((depthq `matchesAccount`).aname) -- exclude deeper balances                 | otherwise   = clipAccountsAndAggregate depth -- aggregate deeper balances at the depth limit       colacctchanges :: [[(ClippedAccountName, MixedAmount)]] =-          dbg1 "colacctchanges" $ map (acctChangesFromPostings . fst) colps+          dbg'' "colacctchanges" $ map (acctChangesFromPostings . fst) colps        ----------------------------------------------------------------------       -- 5. Gather the account balance changes into a regular matrix including the accounts@@ -207,7 +214,7 @@        -- All account names that will be displayed, possibly depth-clipped.       displayaccts :: [ClippedAccountName] =-          dbg1 "displayaccts" $+          dbg'' "displayaccts" $           (if tree_ ropts then expandAccountNames else id) $           nub $ map (clipOrEllipsifyAccountName depth) $           if empty_ || balancetype_ == HistoricalBalance@@ -215,16 +222,16 @@           else allpostedaccts         where           allpostedaccts :: [AccountName] =-            dbg1 "allpostedaccts" . sort . accountNamesFromPostings $ map fst ps+            dbg'' "allpostedaccts" . sort . accountNamesFromPostings $ map fst ps       -- Each column's balance changes for each account, adding zeroes where needed.       colallacctchanges :: [[(ClippedAccountName, MixedAmount)]] =-          dbg1 "colallacctchanges"+          dbg'' "colallacctchanges"           [ sortOn fst $ unionBy (\(a,_) (a',_) -> a == a') postedacctchanges zeroes              | postedacctchanges <- colacctchanges ]           where zeroes = [(a, nullmixedamt) | a <- displayaccts]       -- Transpose to get each account's balance changes across all columns.       acctchanges :: [(ClippedAccountName, [MixedAmount])] =-          dbg1 "acctchanges"+          dbg'' "acctchanges"           [(a, map snd abs) | abs@((a,_):_) <- transpose colallacctchanges] -- never null, or used when null...        ----------------------------------------------------------------------@@ -232,18 +239,18 @@        -- One row per account, with account name info, row amounts, row total and row average.       rows :: [MultiBalanceReportRow] =-          dbg1 "rows" $+          dbg'' "rows" $           [ PeriodicReportRow a (accountNameLevel a) valuedrowbals rowtot rowavg-           | (a,changes) <- dbg1 "acctchanges" acctchanges+           | (a,changes) <- dbg'' "acctchanges" acctchanges              -- The row amounts to be displayed: per-period changes,              -- zero-based cumulative totals, or              -- starting-balance-based historical balances.-           , let rowbals = dbg1 "rowbals" $ case balancetype_ of+           , let rowbals = dbg'' "rowbals" $ case balancetype_ of                    PeriodChange      -> changes                    CumulativeChange  -> drop 1 $ scanl (+) 0                      changes                    HistoricalBalance -> drop 1 $ scanl (+) (startingBalanceFor a) changes              -- We may be converting amounts to value, per hledger_options.m4.md "Effect of --value on reports".-           , let valuedrowbals = dbg1 "valuedrowbals" $ [avalue periodlastday amt | (amt,periodlastday) <- zip rowbals lastdays]+           , let valuedrowbals = dbg'' "valuedrowbals" $ [avalue periodlastday amt | (amt,periodlastday) <- zip rowbals lastdays]              -- The total and average for the row.              -- These are always simply the sum/average of the displayed row amounts.              -- Total for a cumulative/historical report is always zero.@@ -273,7 +280,7 @@       -- Sort the rows by amount or by account declaration order. This is a bit tricky.       -- TODO: is it always ok to sort report rows after report has been generated, as a separate step ?       sortedrows :: [MultiBalanceReportRow] =-        dbg1 "sortedrows" $+        dbg' "sortedrows" $         sortrows rows         where           sortrows@@ -319,7 +326,7 @@       colamts = transpose . map prrAmounts $ filter isHighest rows         where isHighest row = not (tree_ ropts) || prrName row `elem` highestlevelaccts       coltotals :: [MixedAmount] =-        dbg1 "coltotals" $ map sum colamts+        dbg'' "coltotals" $ map sum colamts       -- Calculate the grand total and average. These are always the sum/average       -- of the column totals.       [grandtotal,grandaverage] =@@ -330,7 +337,7 @@         in amts       -- Totals row.       totalsrow :: PeriodicReportRow () MixedAmount =-        dbg1 "totalsrow" $ PeriodicReportRow () 0 coltotals grandtotal grandaverage+        dbg' "totalsrow" $ PeriodicReportRow () 0 coltotals grandtotal grandaverage        ----------------------------------------------------------------------       -- 9. Map the report rows to percentages if needed@@ -339,7 +346,7 @@       -- Perform the divisions to obtain percentages       mappedsortedrows :: [MultiBalanceReportRow] =         if not percent_ then sortedrows-        else dbg1 "mappedsortedrows"+        else dbg'' "mappedsortedrows"           [ PeriodicReportRow aname alevel               (zipWith perdivide rowvals coltotals)               (rowtotal `perdivide` grandtotal)@@ -347,7 +354,7 @@            | PeriodicReportRow aname alevel rowvals rowtotal rowavg <- sortedrows           ]       mappedtotalsrow :: PeriodicReportRow () MixedAmount-        | percent_  = dbg1 "mappedtotalsrow" $ PeriodicReportRow () 0+        | percent_  = dbg'' "mappedtotalsrow" $ PeriodicReportRow () 0              (map (\t -> perdivide t t) coltotals)              (perdivide grandtotal grandtotal)              (perdivide grandaverage grandaverage)@@ -360,7 +367,8 @@ balanceReportFromMultiBalanceReport :: ReportOpts -> Query -> Journal -> BalanceReport balanceReportFromMultiBalanceReport opts q j = (rows', total)   where-    PeriodicReport _ rows (PeriodicReportRow _ _ totals _ _) = multiBalanceReportWith opts q j (journalPriceOracle j)+    PeriodicReport _ rows (PeriodicReportRow _ _ totals _ _) =+      multiBalanceReportWith opts q j (journalPriceOracle (infer_value_ opts) j)     rows' = [( a              , if flat_ opts then a else accountLeafName a   -- BalanceReport expects full account name here with --flat              , if tree_ opts then d-1 else 0  -- BalanceReport uses 0-based account depths
Hledger/Reports/PostingsReport.hs view
@@ -74,7 +74,7 @@       whichdate   = whichDateFromOpts ropts       depth       = queryDepth q       styles      = journalCommodityStyles j-      priceoracle = journalPriceOracle j+      priceoracle = journalPriceOracle infer_value_ j       multiperiod = interval_ /= NoInterval       today       = fromMaybe (error' "postingsReport: could not pick a valuation date, ReportOpts today_ is unset") today_ 
Hledger/Reports/ReportOptions.hs view
@@ -93,6 +93,7 @@     ,interval_       :: Interval     ,statuses_       :: [Status]  -- ^ Zero, one, or two statuses to be matched     ,value_          :: Maybe ValuationType  -- ^ What value should amounts be converted to ?+    ,infer_value_    :: Bool      -- ^ Infer market prices from transactions ?     ,depth_          :: Maybe Int     ,display_        :: Maybe DisplayExp  -- XXX unused ?     ,date2_          :: Bool@@ -161,6 +162,7 @@     def     def     def+    def  rawOptsToReportOpts :: RawOpts -> IO ReportOpts rawOptsToReportOpts rawopts = checkReportOpts <$> do@@ -173,6 +175,7 @@     ,interval_    = intervalFromRawOpts rawopts'     ,statuses_    = statusesFromRawOpts rawopts'     ,value_       = valuationTypeFromRawOpts rawopts'+    ,infer_value_ = boolopt "infer-value" rawopts'     ,depth_       = maybeintopt "depth" rawopts'     ,display_     = maybedisplayopt d rawopts'     ,date2_       = boolopt "date2" rawopts'@@ -317,8 +320,7 @@ -- | get period expression from --forecast option forecastPeriodFromRawOpts :: Day -> RawOpts -> Maybe DateSpan forecastPeriodFromRawOpts d opts =-  case -    dbg2 "forecastopt" $ maybestringopt "forecast" opts+  case maybestringopt "forecast" opts   of     Nothing -> Nothing     Just "" -> Just nulldatespan@@ -478,13 +480,13 @@ reportSpan :: Journal -> ReportOpts -> IO DateSpan reportSpan j ropts = do   (mspecifiedstartdate, mspecifiedenddate) <--    dbg2 "specifieddates" <$> specifiedStartEndDates ropts+    dbg3 "specifieddates" <$> specifiedStartEndDates ropts   let     DateSpan mjournalstartdate mjournalenddate =-      dbg2 "journalspan" $ journalDateSpan False j  -- ignore secondary dates+      dbg3 "journalspan" $ journalDateSpan False j  -- ignore secondary dates     mstartdate = mspecifiedstartdate <|> mjournalstartdate     menddate   = mspecifiedenddate   <|> mjournalenddate-  return $ dbg1 "reportspan" $ DateSpan mstartdate menddate+  return $ dbg3 "reportspan" $ DateSpan mstartdate menddate  reportStartDate :: Journal -> ReportOpts -> IO (Maybe Day) reportStartDate j ropts = spanStart <$> reportSpan j ropts
Hledger/Utils/Debug.hs view
@@ -1,5 +1,33 @@ {-# LANGUAGE FlexibleContexts, TypeFamilies #-}--- | Debugging helpers+{- | Debugging helpers.++You can enable increasingly verbose debug output by adding --debug [1-9]+to a hledger command line. --debug with no argument means --debug 1.+This is implemented by calling dbgN or similar helpers, defined below.+These calls can be found throughout hledger code; they have been added+organically where it seemed likely they would be needed again.+The choice of debug level has not been very systematic.+202006 Here's a start at some guidelines, not yet applied project-wide:++Debug level:  What to show:+------------  ---------------------------------------------------------+0             normal command output only (no warnings, eg)+1 (--debug)   useful warnings, most common troubleshooting info, eg valuation+2             common troubleshooting info, more detail+3             report options selection+4             report generation+5             report generation, more detail+6             command line parsing+7             input file reading+8             input file reading, more detail+9             any other rarely needed / more in-depth info++Tip: when debugging with GHCI, the first run after loading Debug.hs sets the+debug level. If you need to change it, you must touch Debug.hs, :reload in GHCI,+then run the command with a new --debug value. Or, often it's more convenient+to add a temporary dbg0 and :reload (dbg0 always prints).++-}  -- more: -- http://hackage.haskell.org/packages/archive/TraceUtils/0.1.0.2/doc/html/Debug-TraceUtils.html
hledger-lib.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 20f17b4cb289218f7b75159b42ad69840906c54c555a2191679edd3842b72e7b+-- hash: 22c04257dd0778ffcde96603d006e72ff6bf1b3da2ac7c3c12bc4e9df2064863  name:           hledger-lib-version:        1.18+version:        1.18.1 synopsis:       A reusable library providing the core functionality of hledger description:    A reusable library containing hledger's core functionality.                 This is used by most hledger* packages so that they support the same
hledger_csv.5 view
@@ -1,6 +1,6 @@ .\"t -.TH "hledger_csv" "5" "June 2020" "hledger 1.18" "hledger User Manuals"+.TH "hledger_csv" "5" "June 2020" "hledger 1.18.1" "hledger User Manuals"   @@ -961,7 +961,7 @@ .PP A posting amount can be set in one of these ways: .IP \[bu] 2-by assigning (with a fields list or field assigment) to+by assigning (with a fields list or field assignment) to \f[C]amountN\f[R] (posting N\[aq]s amount) or \f[C]amount\f[R] (posting 1\[aq]s amount) .IP \[bu] 2
hledger_csv.info view
@@ -3,8 +3,8 @@  File: hledger_csv.info,  Node: Top,  Next: EXAMPLES,  Up: (dir) -hledger_csv(5) hledger 1.18-***************************+hledger_csv(5) hledger 1.18.1+*****************************  CSV - how hledger reads CSV data, and the CSV rules file format @@ -907,7 +907,7 @@  A posting amount can be set in one of these ways: -   * by assigning (with a fields list or field assigment) to 'amountN'+   * by assigning (with a fields list or field assignment) to 'amountN'      (posting N's amount) or 'amount' (posting 1's amount)     * by assigning to 'amountN-in' and 'amountN-out' (or 'amount-in' and@@ -1036,74 +1036,74 @@  Tag Table: Node: Top72-Node: EXAMPLES2174-Ref: #examples2280-Node: Basic2488-Ref: #basic2588-Node: Bank of Ireland3130-Ref: #bank-of-ireland3265-Node: Amazon4727-Ref: #amazon4845-Node: Paypal6564-Ref: #paypal6658-Node: CSV RULES14302-Ref: #csv-rules14411-Node: skip14687-Ref: #skip14780-Node: fields15155-Ref: #fields15277-Node: Transaction field names16442-Ref: #transaction-field-names16602-Node: Posting field names16713-Ref: #posting-field-names16865-Node: account16935-Ref: #account17051-Node: amount17588-Ref: #amount17719-Node: currency18826-Ref: #currency18961-Node: balance19167-Ref: #balance19301-Node: comment19618-Ref: #comment19735-Node: field assignment19898-Ref: #field-assignment20041-Node: separator20859-Ref: #separator20988-Node: if21399-Ref: #if21501-Node: end23657-Ref: #end23763-Node: date-format23987-Ref: #date-format24119-Node: newest-first24868-Ref: #newest-first25006-Node: include25689-Ref: #include25818-Node: balance-type26262-Ref: #balance-type26382-Node: TIPS27082-Ref: #tips27164-Node: Rapid feedback27420-Ref: #rapid-feedback27537-Node: Valid CSV27997-Ref: #valid-csv28127-Node: File Extension28319-Ref: #file-extension28471-Node: Reading multiple CSV files28881-Ref: #reading-multiple-csv-files29066-Node: Valid transactions29307-Ref: #valid-transactions29485-Node: Deduplicating importing30113-Ref: #deduplicating-importing30292-Node: Setting amounts31325-Ref: #setting-amounts31494-Node: Setting currency/commodity32480-Ref: #setting-currencycommodity32672-Node: Referencing other fields33475-Ref: #referencing-other-fields33675-Node: How CSV rules are evaluated34572-Ref: #how-csv-rules-are-evaluated34745+Node: EXAMPLES2178+Ref: #examples2284+Node: Basic2492+Ref: #basic2592+Node: Bank of Ireland3134+Ref: #bank-of-ireland3269+Node: Amazon4731+Ref: #amazon4849+Node: Paypal6568+Ref: #paypal6662+Node: CSV RULES14306+Ref: #csv-rules14415+Node: skip14691+Ref: #skip14784+Node: fields15159+Ref: #fields15281+Node: Transaction field names16446+Ref: #transaction-field-names16606+Node: Posting field names16717+Ref: #posting-field-names16869+Node: account16939+Ref: #account17055+Node: amount17592+Ref: #amount17723+Node: currency18830+Ref: #currency18965+Node: balance19171+Ref: #balance19305+Node: comment19622+Ref: #comment19739+Node: field assignment19902+Ref: #field-assignment20045+Node: separator20863+Ref: #separator20992+Node: if21403+Ref: #if21505+Node: end23661+Ref: #end23767+Node: date-format23991+Ref: #date-format24123+Node: newest-first24872+Ref: #newest-first25010+Node: include25693+Ref: #include25822+Node: balance-type26266+Ref: #balance-type26386+Node: TIPS27086+Ref: #tips27168+Node: Rapid feedback27424+Ref: #rapid-feedback27541+Node: Valid CSV28001+Ref: #valid-csv28131+Node: File Extension28323+Ref: #file-extension28475+Node: Reading multiple CSV files28885+Ref: #reading-multiple-csv-files29070+Node: Valid transactions29311+Ref: #valid-transactions29489+Node: Deduplicating importing30117+Ref: #deduplicating-importing30296+Node: Setting amounts31329+Ref: #setting-amounts31498+Node: Setting currency/commodity32485+Ref: #setting-currencycommodity32677+Node: Referencing other fields33480+Ref: #referencing-other-fields33680+Node: How CSV rules are evaluated34577+Ref: #how-csv-rules-are-evaluated34750  End Tag Table 
hledger_csv.txt view
@@ -710,7 +710,7 @@    Setting amounts        A posting amount can be set in one of these ways: -       o by assigning (with a fields  list  or  field  assigment)  to  amountN+       o by assigning (with a fields list  or  field  assignment)  to  amountN          (posting N's amount) or amount (posting 1's amount)         o by  assigning to amountN-in and amountN-out (or amount-in and amount-@@ -852,4 +852,4 @@   -hledger 1.18                       June 2020                    hledger_csv(5)+hledger 1.18.1                     June 2020                    hledger_csv(5)
hledger_journal.5 view
@@ -1,6 +1,6 @@ .\"t -.TH "hledger_journal" "5" "June 2020" "hledger 1.18" "hledger User Manuals"+.TH "hledger_journal" "5" "June 2020" "hledger 1.18.1" "hledger User Manuals"   @@ -1143,15 +1143,20 @@ If the file path does not begin with a slash, it is relative to the current file\[aq]s folder. .PP-It may contain glob patterns to match multiple files, eg:+A tilde means home directory, eg: \f[C]include \[ti]/main.journal\f[R].+.PP+The path may contain glob patterns to match multiple files, eg: \f[C]include *.journal\f[R]. .PP-Or a tilde, meaning home directory:-\f[C]include \[ti]/main.journal\f[R].+There is limited support for recursive wildcards: \f[C]**/\f[R] (the+slash is required) matches 0 or more subdirectories.+It\[aq]s not super convenient since you have to avoid include cycles and+including directories, but this can be done, eg:+\f[C]include */**/*.journal\f[R]. .PP-It may also be prefixed to force a specific file format, overriding the-file extension (as described in hledger.1 -> Input files):-\f[C]include timedot:\[ti]/notes/2020*.md\f[R].+The path may also be prefixed to force a specific file format,+overriding the file extension (as described in hledger.1 -> Input+files): \f[C]include timedot:\[ti]/notes/2020*.md\f[R]. .SS Default year .PP You can set a default year to be used for subsequent dates which
hledger_journal.info view
@@ -4,8 +4,8 @@  File: hledger_journal.info,  Node: Top,  Up: (dir) -hledger_journal(5) hledger 1.18-*******************************+hledger_journal(5) hledger 1.18.1+*********************************  Journal - hledger's default file format, representing a General Journal @@ -1023,15 +1023,20 @@    If the file path does not begin with a slash, it is relative to the current file's folder. -   It may contain glob patterns to match multiple files, eg: 'include-*.journal'.+   A tilde means home directory, eg: 'include ~/main.journal'. -   Or a tilde, meaning home directory: 'include ~/main.journal'.+   The path may contain glob patterns to match multiple files, eg:+'include *.journal'. -   It may also be prefixed to force a specific file format, overriding-the file extension (as described in hledger.1 -> Input files): 'include-timedot:~/notes/2020*.md'.+   There is limited support for recursive wildcards: '**/' (the slash is+required) matches 0 or more subdirectories.  It's not super convenient+since you have to avoid include cycles and including directories, but+this can be done, eg: 'include */**/*.journal'. +   The path may also be prefixed to force a specific file format,+overriding the file extension (as described in hledger.1 -> Input+files): 'include timedot:~/notes/2020*.md'.+  File: hledger_journal.info,  Node: Default year,  Next: Declaring commodities,  Prev: Including other files,  Up: Directives @@ -1823,124 +1828,124 @@  Tag Table: Node: Top76-Node: Transactions1869-Ref: #transactions1961-Node: Dates3245-Ref: #dates3344-Node: Simple dates3409-Ref: #simple-dates3535-Node: Secondary dates4044-Ref: #secondary-dates4198-Node: Posting dates5534-Ref: #posting-dates5663-Node: Status7035-Ref: #status7156-Node: Description8864-Ref: #description8998-Node: Payee and note9318-Ref: #payee-and-note9432-Node: Comments9767-Ref: #comments9893-Node: Tags11087-Ref: #tags11202-Node: Postings12595-Ref: #postings12723-Node: Virtual postings13749-Ref: #virtual-postings13866-Node: Account names15171-Ref: #account-names15312-Node: Amounts15799-Ref: #amounts15938-Node: Digit group marks17046-Ref: #digit-group-marks17194-Node: Amount display style18132-Ref: #amount-display-style18286-Node: Transaction prices19723-Ref: #transaction-prices19895-Node: Lot prices and lot dates22227-Ref: #lot-prices-and-lot-dates22424-Node: Balance assertions22912-Ref: #balance-assertions23098-Node: Assertions and ordering24131-Ref: #assertions-and-ordering24319-Node: Assertions and included files25019-Ref: #assertions-and-included-files25262-Node: Assertions and multiple -f options25595-Ref: #assertions-and-multiple--f-options25851-Node: Assertions and commodities25983-Ref: #assertions-and-commodities26215-Node: Assertions and prices27372-Ref: #assertions-and-prices27586-Node: Assertions and subaccounts28026-Ref: #assertions-and-subaccounts28255-Node: Assertions and virtual postings28579-Ref: #assertions-and-virtual-postings28821-Node: Assertions and precision28963-Ref: #assertions-and-precision29156-Node: Balance assignments29423-Ref: #balance-assignments29597-Node: Balance assignments and prices30761-Ref: #balance-assignments-and-prices30933-Node: Directives31157-Ref: #directives31316-Node: Directives and multiple files37007-Ref: #directives-and-multiple-files37190-Node: Comment blocks37854-Ref: #comment-blocks38037-Node: Including other files38213-Ref: #including-other-files38393-Node: Default year39044-Ref: #default-year39213-Node: Declaring commodities39620-Ref: #declaring-commodities39803-Node: Default commodity41609-Ref: #default-commodity41795-Node: Declaring market prices42684-Ref: #declaring-market-prices42879-Node: Declaring accounts43736-Ref: #declaring-accounts43922-Node: Account comments44847-Ref: #account-comments45010-Node: Account subdirectives45434-Ref: #account-subdirectives45629-Node: Account types45942-Ref: #account-types46126-Node: Account display order47765-Ref: #account-display-order47935-Node: Rewriting accounts49086-Ref: #rewriting-accounts49271-Node: Basic aliases50028-Ref: #basic-aliases50174-Node: Regex aliases50878-Ref: #regex-aliases51050-Node: Combining aliases51768-Ref: #combining-aliases51961-Node: Aliases and multiple files53237-Ref: #aliases-and-multiple-files53446-Node: end aliases54025-Ref: #end-aliases54182-Node: Default parent account54283-Ref: #default-parent-account54451-Node: Periodic transactions55335-Ref: #periodic-transactions55510-Node: Periodic rule syntax57382-Ref: #periodic-rule-syntax57588-Node: Two spaces between period expression and description!58292-Ref: #two-spaces-between-period-expression-and-description58611-Node: Forecasting with periodic transactions59295-Ref: #forecasting-with-periodic-transactions59600-Node: Budgeting with periodic transactions61655-Ref: #budgeting-with-periodic-transactions61894-Node: Auto postings62343-Ref: #auto-postings62483-Node: Auto postings and multiple files64662-Ref: #auto-postings-and-multiple-files64866-Node: Auto postings and dates65075-Ref: #auto-postings-and-dates65349-Node: Auto postings and transaction balancing / inferred amounts / balance assertions65524-Ref: #auto-postings-and-transaction-balancing-inferred-amounts-balance-assertions65875-Node: Auto posting tags66217-Ref: #auto-posting-tags66432+Node: Transactions1873+Ref: #transactions1965+Node: Dates3249+Ref: #dates3348+Node: Simple dates3413+Ref: #simple-dates3539+Node: Secondary dates4048+Ref: #secondary-dates4202+Node: Posting dates5538+Ref: #posting-dates5667+Node: Status7039+Ref: #status7160+Node: Description8868+Ref: #description9002+Node: Payee and note9322+Ref: #payee-and-note9436+Node: Comments9771+Ref: #comments9897+Node: Tags11091+Ref: #tags11206+Node: Postings12599+Ref: #postings12727+Node: Virtual postings13753+Ref: #virtual-postings13870+Node: Account names15175+Ref: #account-names15316+Node: Amounts15803+Ref: #amounts15942+Node: Digit group marks17050+Ref: #digit-group-marks17198+Node: Amount display style18136+Ref: #amount-display-style18290+Node: Transaction prices19727+Ref: #transaction-prices19899+Node: Lot prices and lot dates22231+Ref: #lot-prices-and-lot-dates22428+Node: Balance assertions22916+Ref: #balance-assertions23102+Node: Assertions and ordering24135+Ref: #assertions-and-ordering24323+Node: Assertions and included files25023+Ref: #assertions-and-included-files25266+Node: Assertions and multiple -f options25599+Ref: #assertions-and-multiple--f-options25855+Node: Assertions and commodities25987+Ref: #assertions-and-commodities26219+Node: Assertions and prices27376+Ref: #assertions-and-prices27590+Node: Assertions and subaccounts28030+Ref: #assertions-and-subaccounts28259+Node: Assertions and virtual postings28583+Ref: #assertions-and-virtual-postings28825+Node: Assertions and precision28967+Ref: #assertions-and-precision29160+Node: Balance assignments29427+Ref: #balance-assignments29601+Node: Balance assignments and prices30765+Ref: #balance-assignments-and-prices30937+Node: Directives31161+Ref: #directives31320+Node: Directives and multiple files37011+Ref: #directives-and-multiple-files37194+Node: Comment blocks37858+Ref: #comment-blocks38041+Node: Including other files38217+Ref: #including-other-files38397+Node: Default year39321+Ref: #default-year39490+Node: Declaring commodities39897+Ref: #declaring-commodities40080+Node: Default commodity41886+Ref: #default-commodity42072+Node: Declaring market prices42961+Ref: #declaring-market-prices43156+Node: Declaring accounts44013+Ref: #declaring-accounts44199+Node: Account comments45124+Ref: #account-comments45287+Node: Account subdirectives45711+Ref: #account-subdirectives45906+Node: Account types46219+Ref: #account-types46403+Node: Account display order48042+Ref: #account-display-order48212+Node: Rewriting accounts49363+Ref: #rewriting-accounts49548+Node: Basic aliases50305+Ref: #basic-aliases50451+Node: Regex aliases51155+Ref: #regex-aliases51327+Node: Combining aliases52045+Ref: #combining-aliases52238+Node: Aliases and multiple files53514+Ref: #aliases-and-multiple-files53723+Node: end aliases54302+Ref: #end-aliases54459+Node: Default parent account54560+Ref: #default-parent-account54728+Node: Periodic transactions55612+Ref: #periodic-transactions55787+Node: Periodic rule syntax57659+Ref: #periodic-rule-syntax57865+Node: Two spaces between period expression and description!58569+Ref: #two-spaces-between-period-expression-and-description58888+Node: Forecasting with periodic transactions59572+Ref: #forecasting-with-periodic-transactions59877+Node: Budgeting with periodic transactions61932+Ref: #budgeting-with-periodic-transactions62171+Node: Auto postings62620+Ref: #auto-postings62760+Node: Auto postings and multiple files64939+Ref: #auto-postings-and-multiple-files65143+Node: Auto postings and dates65352+Ref: #auto-postings-and-dates65626+Node: Auto postings and transaction balancing / inferred amounts / balance assertions65801+Ref: #auto-postings-and-transaction-balancing-inferred-amounts-balance-assertions66152+Node: Auto posting tags66494+Ref: #auto-posting-tags66709  End Tag Table 
hledger_journal.txt view
@@ -792,18 +792,23 @@        If  the  file  path  does not begin with a slash, it is relative to the        current file's folder. -       It may contain glob patterns  to  match  multiple  files,  eg:  include+       A tilde means home directory, eg: include ~/main.journal.++       The path may contain glob patterns to match multiple files, eg: include        *.journal. -       Or a tilde, meaning home directory: include ~/main.journal.+       There is limited support for recursive wildcards: **/ (the slash is re-+       quired) matches 0 or more subdirectories.  It's  not  super  convenient+       since  you  have to avoid include cycles and including directories, but+       this can be done, eg: include */**/*.journal. -       It may also be prefixed to force a specific file format, overriding the-       file extension (as described in  hledger.1  ->  Input  files):  include-       timedot:~/notes/2020*.md.+       The path may also be prefixed to force a specific file format, overrid-+       ing  the file extension (as described in hledger.1 -> Input files): in-+       clude timedot:~/notes/2020*.md.     Default year-       You  can set a default year to be used for subsequent dates which don't-       specify a year.  This is a line beginning with Y followed by the  year.+       You can set a default year to be used for subsequent dates which  don't+       specify  a year.  This is a line beginning with Y followed by the year.        Eg:                Y2009  ; set default year to 2009@@ -825,19 +830,19 @@    Declaring commodities        The commodity directive has several functions: -       1. It  declares  commodities which may be used in the journal.  This is+       1. It declares commodities which may be used in the journal.   This  is           currently not enforced, but can serve as documentation. -       2. It declares what decimal mark character (period or comma) to  expect-          when  parsing  input  -  useful to disambiguate international number-          formats in your data.  (Without this, hledger will parse both  1,000+       2. It  declares what decimal mark character (period or comma) to expect+          when parsing input - useful  to  disambiguate  international  number+          formats  in your data.  (Without this, hledger will parse both 1,000           and 1.000 as 1). -       3. It  declares the amount display style to use in output - decimal and+       3. It declares the amount display style to use in output - decimal  and           digit group marks, number of decimal places, symbol placement etc. -       You are likely to run into one of the problems solved by commodity  di--       rectives,  sooner or later, so it's a good idea to just always use them+       You  are likely to run into one of the problems solved by commodity di-+       rectives, sooner or later, so it's a good idea to just always use  them        to declare your commodities.         A commodity directive is just the word commodity followed by an amount.@@ -850,8 +855,8 @@               ; separating thousands with comma.               commodity 1,000.0000 AAAA -       or  on  multiple lines, using the "format" subdirective.  (In this case-       the commodity symbol appears twice and  should  be  the  same  in  both+       or on multiple lines, using the "format" subdirective.  (In  this  case+       the  commodity  symbol  appears  twice  and  should be the same in both        places.):                ; commodity SYMBOL@@ -864,22 +869,22 @@                 format INR 1,00,00,000.00         The quantity of the amount does not matter; only the format is signifi--       cant.  The number must include a decimal mark: either  a  period  or  a+       cant.   The  number  must  include a decimal mark: either a period or a        comma, followed by 0 or more decimal digits. -       Note  hledger  normally  uses  banker's rounding, so 0.5 displayed with+       Note hledger normally uses banker's rounding,  so  0.5  displayed  with        zero decimal digits is "0".  (More at Amount display style.)     Default commodity-       The D directive sets a default commodity, to be used for amounts  with-+       The  D directive sets a default commodity, to be used for amounts with-        out a commodity symbol (ie, plain numbers).  This commodity will be ap-        plied to all subsequent commodity-less amounts, or until the next D di-        rective.  (Note, this is different from Ledger's D.) -       For  compatibility/historical reasons, D also acts like a commodity di-+       For compatibility/historical reasons, D also acts like a commodity  di-        rective, setting the commodity's display style (for output) and decimal        mark (for parsing input).  As with commodity, the amount must always be-       written with a decimal mark (period or comma).  If both directives  are+       written  with a decimal mark (period or comma).  If both directives are        used, commodity's style takes precedence.         The syntax is D AMOUNT.  Eg:@@ -893,9 +898,9 @@                 b     Declaring market prices-       The  P directive declares a market price, which is an exchange rate be--       tween two commodities on a certain date.  (In Ledger, they  are  called-       "historical  prices".)  These are often obtained from a stock exchange,+       The P directive declares a market price, which is an exchange rate  be-+       tween  two  commodities on a certain date.  (In Ledger, they are called+       "historical prices".) These are often obtained from a  stock  exchange,        cryptocurrency exchange, or the foreign exchange market.         Here is the format:@@ -906,16 +911,16 @@         o COMMODITYA is the symbol of the commodity being priced -       o COMMODITYBAMOUNT is an amount (symbol and quantity) in a second  com-+       o COMMODITYBAMOUNT  is an amount (symbol and quantity) in a second com-          modity, giving the price in commodity B of one unit of commodity A. -       These  two  market price directives say that one euro was worth 1.35 US+       These two market price directives say that one euro was worth  1.35  US        dollars during 2009, and $1.40 from 2010 onward:                P 2009/1/1 EUR $1.35               P 2010/1/1 EUR $1.40 -       The -V, -X and --value flags use these market  prices  to  show  amount+       The  -V,  -X  and  --value flags use these market prices to show amount        values in another commodity.  See Valuation.     Declaring accounts@@ -925,20 +930,20 @@        o They can document your intended chart of accounts, providing a refer-          ence. -       o They  can  store  extra  information about accounts (account numbers,+       o They can store extra information  about  accounts  (account  numbers,          notes, etc.) -       o They can help hledger know your accounts'  types  (asset,  liability,-         equity,  revenue,  expense), useful for reports like balancesheet and+       o They  can  help  hledger know your accounts' types (asset, liability,+         equity, revenue, expense), useful for reports like  balancesheet  and          incomestatement. -       o They control account display order in  reports,  allowing  non-alpha-+       o They  control  account  display order in reports, allowing non-alpha-          betic sorting (eg Revenues to appear above Expenses). -       o They  help  with account name completion in the add command, hledger-+       o They help with account name completion in the add  command,  hledger-          iadd, hledger-web, ledger-mode etc. -       The simplest form is just the word account followed by a  hledger-style+       The  simplest form is just the word account followed by a hledger-style        account name, eg:                account assets:bank:checking@@ -946,7 +951,7 @@    Account comments        Comments, beginning with a semicolon, can be added: -       o on  the  same line, after two or more spaces (because ; is allowed in+       o on the same line, after two or more spaces (because ; is  allowed  in          account names)         o on the next lines, indented@@ -960,7 +965,7 @@        Same-line comments are not supported by Ledger, or hledger <1.13.     Account subdirectives-       We also allow (and ignore) Ledger-style  indented  subdirectives,  just+       We  also  allow  (and ignore) Ledger-style indented subdirectives, just        for compatibility.:                account assets:bank:checking@@ -973,18 +978,18 @@                 [LEDGER-STYLE SUBDIRECTIVES, IGNORED]     Account types-       hledger  recognises  five types (or classes) of account: Asset, Liabil--       ity, Equity, Revenue, Expense.  This is used by a few  accounting-aware+       hledger recognises five types (or classes) of account:  Asset,  Liabil-+       ity,  Equity, Revenue, Expense.  This is used by a few accounting-aware        reports such as balancesheet, incomestatement and cashflow.     Auto-detected account types        If you name your top-level accounts with some variation of assets, lia--       bilities/debts, equity, revenues/income, or expenses, their  types  are+       bilities/debts,  equity,  revenues/income, or expenses, their types are        detected automatically.     Account types declared with tags-       More  generally,  you can declare an account's type with an account di--       rective, by writing a type: tag in a comment, followed by  one  of  the+       More generally, you can declare an account's type with an  account  di-+       rective,  by  writing  a type: tag in a comment, followed by one of the        words Asset, Liability, Equity, Revenue, Expense, or one of the letters        ALERX (case insensitive): @@ -995,8 +1000,8 @@               account expenses     ; type:Expense     Account types declared with account type codes-       Or, you can write one of those letters separated from the account  name-       by  two  or  more spaces, but this should probably be considered depre-+       Or,  you can write one of those letters separated from the account name+       by two or more spaces, but this should probably  be  considered  depre-        cated as of hledger 1.13:                account assets       A@@ -1006,7 +1011,7 @@               account expenses     X     Overriding auto-detected types-       If you ever override the types of those auto-detected  english  account+       If  you  ever override the types of those auto-detected english account        names mentioned above, you might need to help the reports a bit.  Eg:                ; make "liabilities" not have the liability type - who knows why@@ -1017,8 +1022,8 @@               account -            ; type:L     Account display order-       Account  directives also set the order in which accounts are displayed,-       eg in reports, the hledger-ui  accounts  screen,  and  the  hledger-web+       Account directives also set the order in which accounts are  displayed,+       eg  in  reports,  the  hledger-ui  accounts screen, and the hledger-web        sidebar.  By default accounts are listed in alphabetical order.  But if        you have these account directives in the journal: @@ -1040,20 +1045,20 @@         Undeclared accounts, if any, are displayed last, in alphabetical order. -       Note  that  sorting  is  done at each level of the account tree (within-       each group of sibling accounts under the same parent).  And  currently,+       Note that sorting is done at each level of  the  account  tree  (within+       each  group of sibling accounts under the same parent).  And currently,        this directive:                account other:zoo -       would  influence the position of zoo among other's subaccounts, but not+       would influence the position of zoo among other's subaccounts, but  not        the position of other among the top-level accounts.  This means: -       o you will sometimes declare parent accounts (eg account  other  above)+       o you  will  sometimes declare parent accounts (eg account other above)          that you don't intend to post to, just to customize their display or-          der -       o sibling accounts stay together (you couldn't display x:y  in  between+       o sibling  accounts  stay together (you couldn't display x:y in between          a:b and a:c).     Rewriting accounts@@ -1071,14 +1076,14 @@        o customising reports         Account aliases also rewrite account names in account directives.  They-       do  not  affect account names being entered via hledger add or hledger-+       do not affect account names being entered via hledger add  or  hledger-        web.         See also Rewrite account names.     Basic aliases-       To set an account alias, use the alias directive in your journal  file.-       This  affects all subsequent journal entries in the current file or its+       To  set an account alias, use the alias directive in your journal file.+       This affects all subsequent journal entries in the current file or  its        included files.  The spaces around the = are optional:                alias OLD = NEW@@ -1086,49 +1091,49 @@        Or, you can use the --alias 'OLD=NEW' option on the command line.  This        affects all entries.  It's useful for trying out aliases interactively. -       OLD  and  NEW  are case sensitive full account names.  hledger will re--       place any occurrence of the old account name with the new one.   Subac-+       OLD and NEW are case sensitive full account names.   hledger  will  re-+       place  any occurrence of the old account name with the new one.  Subac-        counts are also affected.  Eg:                alias checking = assets:bank:wells fargo:checking               ; rewrites "checking" to "assets:bank:wells fargo:checking", or "checking:a" to "assets:bank:wells fargo:checking:a"     Regex aliases-       There  is  also a more powerful variant that uses a regular expression,+       There is also a more powerful variant that uses a  regular  expression,        indicated by the forward slashes:                alias /REGEX/ = REPLACEMENT         or --alias '/REGEX/=REPLACEMENT'. -       REGEX is a case-insensitive regular expression.   Anywhere  it  matches-       inside  an  account name, the matched part will be replaced by REPLACE--       MENT.  If REGEX contains parenthesised match groups, these can be  ref-+       REGEX  is  a  case-insensitive regular expression.  Anywhere it matches+       inside an account name, the matched part will be replaced  by  REPLACE-+       MENT.   If REGEX contains parenthesised match groups, these can be ref-        erenced by the usual numeric backreferences in REPLACEMENT.  Eg:                alias /^(.+):bank:([^:]+)(.*)/ = \1:\2 \3               ; rewrites "assets:bank:wells fargo:checking" to  "assets:wells fargo checking" -       Also  note that REPLACEMENT continues to the end of line (or on command-       line, to end of option argument), so it  can  contain  trailing  white-+       Also note that REPLACEMENT continues to the end of line (or on  command+       line,  to  end  of  option argument), so it can contain trailing white-        space.     Combining aliases-       You  can  define  as many aliases as you like, using journal directives+       You can define as many aliases as you like,  using  journal  directives        and/or command line options. -       Recursive aliases - where an account name is rewritten  by  one  alias,-       then  by  another  alias, and so on - are allowed.  Each alias sees the+       Recursive  aliases  -  where an account name is rewritten by one alias,+       then by another alias, and so on - are allowed.  Each  alias  sees  the        effect of previously applied aliases. -       In such cases it can be important to understand which aliases  will  be-       applied  and  in  which order.  For (each account name in) each journal+       In  such  cases it can be important to understand which aliases will be+       applied and in which order.  For (each account name  in)  each  journal        entry, we apply: -       1. alias directives preceding the journal entry, most  recently  parsed+       1. alias  directives  preceding the journal entry, most recently parsed           first (ie, reading upward from the journal entry, bottom to top) -       2. --alias  options,  in  the  order  they appeared on the command line+       2. --alias options, in the order they  appeared  on  the  command  line           (left to right).         In other words, for (an account name in) a given journal entry:@@ -1139,20 +1144,20 @@         o aliases defined after/below the entry do not affect it. -       This gives nearby aliases precedence over distant ones, and helps  pro--       vide  semantic stability - aliases will keep working the same way inde-+       This  gives nearby aliases precedence over distant ones, and helps pro-+       vide semantic stability - aliases will keep working the same way  inde-        pendent of which files are being read and in which order. -       In case of trouble, adding --debug=6 to  the  command  line  will  show+       In  case  of  trouble,  adding  --debug=6 to the command line will show        which aliases are being applied when.     Aliases and multiple files-       As  explained at Directives and multiple files, alias directives do not+       As explained at Directives and multiple files, alias directives do  not        affect parent or sibling files.  Eg in this command,                hledger -f a.aliases -f b.journal -       account aliases defined in a.aliases will not  affect  b.journal.   In-+       account  aliases  defined  in a.aliases will not affect b.journal.  In-        cluding the aliases doesn't work either:                include a.aliases@@ -1174,14 +1179,14 @@               include c.journal  ; also affected     end aliases-       You can clear (forget) all  currently  defined  aliases  with  the  end+       You  can  clear  (forget)  all  currently  defined aliases with the end        aliases directive:                end aliases     Default parent account-       You  can  specify  a  parent account which will be prepended to all ac--       counts within a section of the journal.  Use the apply account and  end+       You can specify a parent account which will be  prepended  to  all  ac-+       counts  within a section of the journal.  Use the apply account and end        apply account directives like so:                apply account home@@ -1198,7 +1203,7 @@                   home:food           $10                   home:cash          $-10 -       If  end  apply  account  is omitted, the effect lasts to the end of the+       If end apply account is omitted, the effect lasts to  the  end  of  the        file.  Included files are also affected, eg:                apply account business@@ -1207,50 +1212,50 @@               apply account personal               include personal.journal -       Prior to hledger 1.0, legacy account and end spellings were  also  sup-+       Prior  to  hledger 1.0, legacy account and end spellings were also sup-        ported. -       A  default parent account also affects account directives.  It does not-       affect account names being entered via hledger add or hledger-web.   If-       account  aliases are present, they are applied after the default parent+       A default parent account also affects account directives.  It does  not+       affect  account names being entered via hledger add or hledger-web.  If+       account aliases are present, they are applied after the default  parent        account.     Periodic transactions-       Periodic transaction rules describe transactions that recur.  They  al--       low  hledger  to  generate  temporary  future transactions to help with-       forecasting, so you don't have to write out each one  in  the  journal,-       and  it's easy to try out different forecasts.  Secondly, they are also+       Periodic  transaction rules describe transactions that recur.  They al-+       low hledger to generate temporary  future  transactions  to  help  with+       forecasting,  so  you  don't have to write out each one in the journal,+       and it's easy to try out different forecasts.  Secondly, they are  also        used to define the budgets shown in budget reports. -       Periodic transactions can be a little tricky, so before you  use  them,+       Periodic  transactions  can be a little tricky, so before you use them,        read this whole section - or at least these tips: -       1. Two  spaces  accidentally  added or omitted will cause you trouble -+       1. Two spaces accidentally added or omitted will cause  you  trouble  -           read about this below. -       2. For troubleshooting, show the generated  transactions  with  hledger-          print   --forecast  tag:generated  or  hledger  register  --forecast+       2. For  troubleshooting,  show  the generated transactions with hledger+          print  --forecast  tag:generated  or  hledger  register   --forecast           tag:generated. -       3. Forecasted transactions will begin only  after  the  last  non-fore-+       3. Forecasted  transactions  will  begin  only after the last non-fore-           casted transaction's date. -       4. Forecasted  transactions  will  end 6 months from today, by default.+       4. Forecasted transactions will end 6 months from  today,  by  default.           See below for the exact start/end rules. -       5. period expressions can be tricky.   Their  documentation  needs  im-+       5. period  expressions  can  be  tricky.  Their documentation needs im-           provement, but is worth studying. -       6. Some  period  expressions  with a repeating interval must begin on a-          natural boundary of that interval.  Eg in  weekly  from  DATE,  DATE-          must  be a monday.  ~ weekly from 2019/10/1 (a tuesday) will give an+       6. Some period expressions with a repeating interval must  begin  on  a+          natural  boundary  of  that  interval.  Eg in weekly from DATE, DATE+          must be a monday.  ~ weekly from 2019/10/1 (a tuesday) will give  an           error.         7. Other period expressions with an interval are automatically expanded-          to  cover a whole number of that interval.  (This is done to improve+          to cover a whole number of that interval.  (This is done to  improve           reports, but it also affects periodic transactions.  Yes, it's a bit-          inconsistent  with  the  above.)  Eg: ~ every 10th day of month from-          2020/01, which is equivalent to ~  every  10th  day  of  month  from+          inconsistent with the above.) Eg: ~ every 10th  day  of  month  from+          2020/01,  which  is  equivalent  to  ~  every 10th day of month from           2020/01/01, will be adjusted to start on 2019/12/10.     Periodic rule syntax@@ -1262,17 +1267,17 @@                   expenses:rent          $2000                   assets:bank:checking -       There  is  an additional constraint on the period expression: the start-       date must fall on a natural boundary of the interval.  Eg monthly  from+       There is an additional constraint on the period expression:  the  start+       date  must fall on a natural boundary of the interval.  Eg monthly from        2018/1/1 is valid, but monthly from 2018/1/15 is not. -       Partial  or  relative dates (M/D, D, tomorrow, last week) in the period-       expression can work (useful or not).  They will be relative to  today's-       date,  unless  a  Y  default year directive is in effect, in which case+       Partial or relative dates (M/D, D, tomorrow, last week) in  the  period+       expression  can work (useful or not).  They will be relative to today's+       date, unless a Y default year directive is in  effect,  in  which  case        they will be relative to Y/1/1.     Two spaces between period expression and description!-       If the period expression is  followed  by  a  transaction  description,+       If  the  period  expression  is  followed by a transaction description,        these must be separated by two or more spaces.  This helps hledger know        where the period expression ends, so that descriptions can not acciden-        tally alter their meaning, as in this example:@@ -1286,68 +1291,68 @@         So, -       o Do  write two spaces between your period expression and your transac-+       o Do write two spaces between your period expression and your  transac-          tion description, if any. -       o Don't accidentally write two spaces in the middle of your period  ex-+       o Don't  accidentally write two spaces in the middle of your period ex-          pression.     Forecasting with periodic transactions-       The  --forecast  flag  activates  any periodic transaction rules in the-       journal.  They will generate temporary  recurring  transactions,  which-       are  not  saved  in  the  journal,  but  will appear in all reports (eg+       The --forecast flag activates any periodic  transaction  rules  in  the+       journal.   They  will  generate temporary recurring transactions, which+       are not saved in the journal,  but  will  appear  in  all  reports  (eg        print).  This can be useful for estimating balances into the future, or-       experimenting  with  different scenarios.  Or, it can be used as a data+       experimenting with different scenarios.  Or, it can be used as  a  data        entry aid: describe recurring transactions, and every so often copy the        output of print --forecast into the journal. -       These  transactions  will  have  an extra tag indicating which periodic+       These transactions will have an extra  tag  indicating  which  periodic        rule generated them: generated-transaction:~ PERIODICEXPR.  And a simi--       lar,  hidden  tag  (beginning  with  an underscore) which, because it's-       never displayed by print, can be used to match  transactions  generated+       lar, hidden tag (beginning with  an  underscore)  which,  because  it's+       never  displayed  by print, can be used to match transactions generated        "just now": _generated-transaction:~ PERIODICEXPR. -       Periodic  transactions  are  generated within some forecast period.  By+       Periodic transactions are generated within some  forecast  period.   By        default, this         o begins on the later of           o the report start date if specified with -b/-p/date: -         o the day after the latest normal (non-periodic) transaction  in  the+         o the  day  after the latest normal (non-periodic) transaction in the            journal, or today if there are no normal transactions. -       o ends  on  the  report  end  date  if specified with -e/-p/date:, or 6+       o ends on the report end date  if  specified  with  -e/-p/date:,  or  6          months (180 days) from today. -       This means that periodic transactions will begin only after the  latest-       recorded  transaction.   And a recorded transaction dated in the future-       can prevent generation of periodic transactions.  (You can  avoid  that+       This  means that periodic transactions will begin only after the latest+       recorded transaction.  And a recorded transaction dated in  the  future+       can  prevent  generation of periodic transactions.  (You can avoid that        by writing the future transaction as a one-time periodic rule instead -        put tilde before the date, eg ~ YYYY-MM-DD ...).         Or, you can set your own arbitrary "forecast period", which can overlap-       recorded  transactions,  and need not be in the future, by providing an-       option argument, like --forecast=PERIODEXPR.  Note the equals  sign  is+       recorded transactions, and need not be in the future, by  providing  an+       option  argument,  like --forecast=PERIODEXPR.  Note the equals sign is        required, a space won't work.  PERIODEXPR is a period expression, which-       can specify the start date, end date, or both, like in a  date:  query.-       (See  also  hledger.1  ->  Report  start  &  end date).  Some examples:+       can  specify  the start date, end date, or both, like in a date: query.+       (See also hledger.1 ->  Report  start  &  end  date).   Some  examples:        --forecast=202001-202004, --forecast=jan-, --forecast=2020.     Budgeting with periodic transactions-       With the --budget flag, currently supported  by  the  balance  command,-       each  periodic transaction rule declares recurring budget goals for the-       specified accounts.  Eg the first example  above  declares  a  goal  of-       spending  $2000  on  rent  (and  also,  a goal of depositing $2000 into-       checking) every month.  Goals and actual performance can then  be  com-+       With  the  --budget  flag,  currently supported by the balance command,+       each periodic transaction rule declares recurring budget goals for  the+       specified  accounts.   Eg  the  first  example above declares a goal of+       spending $2000 on rent (and also,  a  goal  of  depositing  $2000  into+       checking)  every  month.  Goals and actual performance can then be com-        pared in budget reports. -       For  more  details, see: balance: Budget report and Budgeting and Fore-+       For more details, see: balance: Budget report and Budgeting  and  Fore-        casting.     Auto postings-       "Automated postings" or "auto postings" are extra  postings  which  get-       added  automatically  to  transactions which match certain queries, de-+       "Automated  postings"  or  "auto postings" are extra postings which get+       added automatically to transactions which match  certain  queries,  de-        fined by "auto posting rules", when you use the --auto flag.         An auto posting rule looks a bit like a transaction:@@ -1357,27 +1362,27 @@                   ...                   ACCOUNT  [AMOUNT] -       except the first line is an equals sign (mnemonic:  =  suggests  match--       ing),  followed  by a query (which matches existing postings), and each-       "posting" line describes a posting to be  generated,  and  the  posting+       except  the  first  line is an equals sign (mnemonic: = suggests match-+       ing), followed by a query (which matches existing postings),  and  each+       "posting"  line  describes  a  posting to be generated, and the posting        amounts can be: -       o a  normal  amount  with a commodity symbol, eg $2.  This will be used+       o a normal amount with a commodity symbol, eg $2.  This  will  be  used          as-is.         o a number, eg 2.  The commodity symbol (if any) from the matched post-          ing will be added to this. -       o a  numeric  multiplier,  eg  *2 (a star followed by a number N).  The+       o a numeric multiplier, eg *2 (a star followed by  a  number  N).   The          matched posting's amount (and total price, if any) will be multiplied          by N. -       o a  multiplier  with a commodity symbol, eg *$2 (a star, number N, and+       o a multiplier with a commodity symbol, eg *$2 (a star, number  N,  and          symbol S).  The matched posting's amount will be multiplied by N, and          its commodity symbol will be replaced with S. -       Any  query  term containing spaces must be enclosed in single or double-       quotes, as on the command line.  Eg, note the quotes around the  second+       Any query term containing spaces must be enclosed in single  or  double+       quotes,  as on the command line.  Eg, note the quotes around the second        query term below:                = expenses:groceries 'expenses:dining out'@@ -1416,24 +1421,24 @@     Auto postings and multiple files        An auto posting rule can affect any transaction in the current file, or-       in any parent file or child file.  Note, currently it will  not  affect+       in  any  parent file or child file.  Note, currently it will not affect        sibling files (when multiple -f/--file are used - see #1212).     Auto postings and dates-       A  posting  date (or secondary date) in the matched posting, or (taking-       precedence) a posting date in the auto posting rule itself,  will  also+       A posting date (or secondary date) in the matched posting,  or  (taking+       precedence)  a  posting date in the auto posting rule itself, will also        be used in the generated posting.     Auto postings and transaction balancing / inferred amounts / balance asser-        tions        Currently, auto postings are added: -       o after missing amounts are inferred, and transactions are checked  for+       o after  missing amounts are inferred, and transactions are checked for          balancedness,         o but before balance assertions are checked. -       Note  this  means that journal entries must be balanced both before and+       Note this means that journal entries must be balanced both  before  and        after auto postings are added.  This changed in hledger 1.12+; see #893        for background. @@ -1443,11 +1448,11 @@        o generated-posting:= QUERY - shows this was generated by an auto post-          ing rule, and the query -       o _generated-posting:= QUERY - a hidden tag, which does not  appear  in+       o _generated-posting:=  QUERY  - a hidden tag, which does not appear in          hledger's output.  This can be used to match postings generated "just          now", rather than generated in the past and saved to the journal. -       Also, any transaction that has been changed by auto posting rules  will+       Also,  any transaction that has been changed by auto posting rules will        have these tags added:         o modified: - this transaction was modified@@ -1458,7 +1463,7 @@   REPORTING BUGS-       Report bugs at http://bugs.hledger.org (or on the #hledger IRC  channel+       Report  bugs at http://bugs.hledger.org (or on the #hledger IRC channel        or hledger mail list)  @@ -1472,7 +1477,7 @@   SEE ALSO-       hledger(1),      hledger-ui(1),     hledger-web(1),     hledger-api(1),+       hledger(1),     hledger-ui(1),     hledger-web(1),      hledger-api(1),        hledger_csv(5), hledger_journal(5), hledger_timeclock(5), hledger_time-        dot(5), ledger(1) @@ -1480,4 +1485,4 @@   -hledger 1.18                       June 2020                hledger_journal(5)+hledger 1.18.1                     June 2020                hledger_journal(5)
hledger_timeclock.5 view
@@ -1,5 +1,5 @@ -.TH "hledger_timeclock" "5" "June 2020" "hledger 1.18" "hledger User Manuals"+.TH "hledger_timeclock" "5" "June 2020" "hledger 1.18.1" "hledger User Manuals"   
hledger_timeclock.info view
@@ -4,8 +4,8 @@  File: hledger_timeclock.info,  Node: Top,  Up: (dir) -hledger_timeclock(5) hledger 1.18-*********************************+hledger_timeclock(5) hledger 1.18.1+***********************************  Timeclock - the time logging format of timeclock.el, as read by hledger 
hledger_timeclock.txt view
@@ -78,4 +78,4 @@   -hledger 1.18                       June 2020              hledger_timeclock(5)+hledger 1.18.1                     June 2020              hledger_timeclock(5)
hledger_timedot.5 view
@@ -1,5 +1,5 @@ -.TH "hledger_timedot" "5" "June 2020" "hledger 1.18" "hledger User Manuals"+.TH "hledger_timedot" "5" "June 2020" "hledger 1.18.1" "hledger User Manuals"   
hledger_timedot.info view
@@ -4,8 +4,8 @@  File: hledger_timedot.info,  Node: Top,  Up: (dir) -hledger_timedot(5) hledger 1.18-*******************************+hledger_timedot(5) hledger 1.18.1+*********************************  Timedot - hledger's human-friendly time logging format 
hledger_timedot.txt view
@@ -161,4 +161,4 @@   -hledger 1.18                       June 2020                hledger_timedot(5)+hledger 1.18.1                     June 2020                hledger_timedot(5)