packages feed

hledger-lib 1.50 → 1.50.1

raw patch · 9 files changed

+98/−71 lines, 9 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Hledger.Data.Posting: isPostingInDateSpan :: DateSpan -> Posting -> Bool
- Hledger.Data.Posting: isPostingInDateSpan' :: WhichDate -> DateSpan -> Posting -> Bool
+ Hledger.Data: dateSpansToPeriodData :: [DateSpan] -> Maybe (PeriodData Day)
+ Hledger.Data: lookupPeriodDataOrHistorical :: Day -> PeriodData a -> (Maybe Day, a)
+ Hledger.Data: maybePeriodDataToDateSpans :: Maybe (PeriodData Day) -> [DateSpan]
+ Hledger.Data: periodDataToDateSpans :: PeriodData Day -> [DateSpan]
+ Hledger.Data: periodDataToList :: PeriodData a -> (a, [(Day, a)])
- Hledger.Data: lookupPeriodData :: Day -> PeriodData a -> a
+ Hledger.Data: lookupPeriodData :: Day -> PeriodData a -> Maybe (Day, a)
- Hledger.Data: padPeriodData :: Monoid a => IntSet -> PeriodData a -> PeriodData a
+ Hledger.Data: padPeriodData :: a -> PeriodData b -> PeriodData a -> PeriodData a
- Hledger.Reports.MultiBalanceReport: generateMultiBalanceAccount :: ReportSpec -> Journal -> PriceOracle -> [DateSpan] -> [Posting] -> Account BalanceData
+ Hledger.Reports.MultiBalanceReport: generateMultiBalanceAccount :: ReportSpec -> Journal -> PriceOracle -> Maybe (PeriodData Day) -> [Posting] -> Account BalanceData
- Hledger.Reports.MultiBalanceReport: generatePeriodicReport :: Show c => (forall a. () => ReportOpts -> (BalanceData -> MixedAmount) -> a -> Account b -> PeriodicReportRow a c) -> (b -> MixedAmount) -> (c -> MixedAmount) -> ReportOpts -> [DateSpan] -> Account b -> PeriodicReport DisplayName c
+ Hledger.Reports.MultiBalanceReport: generatePeriodicReport :: Show c => (forall a. () => ReportOpts -> (BalanceData -> MixedAmount) -> a -> Account b -> PeriodicReportRow a c) -> (b -> MixedAmount) -> (c -> MixedAmount) -> ReportOpts -> Maybe (PeriodData Day) -> Account b -> PeriodicReport DisplayName c
- Hledger.Reports.ReportOptions: reportSpan :: Journal -> ReportSpec -> (DateSpan, [DateSpan])
+ Hledger.Reports.ReportOptions: reportSpan :: Journal -> ReportSpec -> (DateSpan, Maybe (PeriodData Day))
- Hledger.Reports.ReportOptions: reportSpanBothDates :: Journal -> ReportSpec -> (DateSpan, [DateSpan])
+ Hledger.Reports.ReportOptions: reportSpanBothDates :: Journal -> ReportSpec -> (DateSpan, Maybe (PeriodData Day))

Files

CHANGES.md view
@@ -17,6 +17,8 @@ For user-visible changes, see the hledger package changelog.  +# 1.50.1 2025-09-16+ # 1.50 2025-09-03  Breaking changes
Hledger/Data/PeriodData.hs view
@@ -9,13 +9,19 @@ -} module Hledger.Data.PeriodData ( periodDataFromList+, periodDataToList  , lookupPeriodData+, lookupPeriodDataOrHistorical , insertPeriodData , opPeriodData , mergePeriodData , padPeriodData +, periodDataToDateSpans+, maybePeriodDataToDateSpans+, dateSpansToPeriodData+ , tests_PeriodData ) where @@ -24,18 +30,17 @@ #else import Control.Applicative (liftA2) #endif+import Data.Bifunctor (first) import qualified Data.IntMap.Strict as IM-import qualified Data.IntSet as IS #if !MIN_VERSION_base(4,20,0) import Data.List (foldl') #endif import Data.Time (Day(..), fromGregorian) -import Test.Tasty (testGroup)-import Test.Tasty.HUnit ((@?=), testCase)- import Hledger.Data.Amount+import Hledger.Data.Dates import Hledger.Data.Types+import Hledger.Utils   instance Show a => Show (PeriodData a) where@@ -44,7 +49,7 @@         showString "PeriodData"       . showString "{ pdpre = " . shows h       . showString ", pdperiods = "-      . showString "fromList " . shows (map (\(day, x) -> (ModifiedJulianDay $ toInteger day, x)) $ IM.toList ds)+      . showString "fromList " . shows (map (\(day, x) -> (intToDay day, x)) $ IM.toList ds)       . showChar '}'  instance Foldable PeriodData where@@ -73,18 +78,32 @@  -- | Construct an 'PeriodData' from a list. periodDataFromList :: a -> [(Day, a)] -> PeriodData a-periodDataFromList h = PeriodData h . IM.fromList . map (\(d, a) -> (fromInteger $ toModifiedJulianDay d, a))+periodDataFromList h = PeriodData h . IM.fromList . map (\(d, a) -> (dayToInt d, a)) --- | Get account balance information to the period containing a given 'Day'.-lookupPeriodData :: Day -> PeriodData a -> a-lookupPeriodData d (PeriodData h as) =-    maybe h snd $ IM.lookupLE (fromInteger $ toModifiedJulianDay d) as+-- | Convert 'PeriodData' to a list of pairs.+periodDataToList :: PeriodData a -> (a, [(Day, a)])+periodDataToList (PeriodData h as) = (h, map (\(s, e) -> (intToDay s, e)) $ IM.toList as) ++-- | Get account balance information for the period containing a given 'Day',+-- along with the start of the period, or 'Nothing' if this day lies in the+-- historical period.+lookupPeriodData :: Day -> PeriodData a -> Maybe (Day, a)+lookupPeriodData d (PeriodData _ as) = first intToDay <$> IM.lookupLE (dayToInt d) as++-- | Get account balance information for the period containing a given 'Day'+-- or the historical data if this day lies in the historical period, along with+-- the start of the period or 'Nothing' if it lies in the historical period.+lookupPeriodDataOrHistorical :: Day -> PeriodData a -> (Maybe Day, a)+lookupPeriodDataOrHistorical d pd@(PeriodData h _) = case lookupPeriodData d pd of+    Nothing     -> (Nothing, h)+    Just (a, b) -> (Just a, b)+ -- | Add account balance information to the appropriate location in 'PeriodData'. insertPeriodData :: Semigroup a => Maybe Day -> a -> PeriodData a -> PeriodData a insertPeriodData mday b balances = case mday of     Nothing  -> balances{pdpre = pdpre balances <> b}-    Just day -> balances{pdperiods = IM.insertWith (<>) (fromInteger $ toModifiedJulianDay day) b $ pdperiods balances}+    Just day -> balances{pdperiods = IM.insertWith (<>) (dayToInt day) b $ pdperiods balances}  -- | Merges two 'PeriodData', using the given operation to combine their balance information. --@@ -103,10 +122,38 @@   where     merge = IM.mergeWithKey (\_ x y -> Just $ f x y) (fmap only1) (fmap only2) --- | Pad out the datemap of an 'PeriodData' so that every key from a set is present.-padPeriodData :: Monoid a => IS.IntSet -> PeriodData a -> PeriodData a-padPeriodData keys bal = bal{pdperiods = pdperiods bal <> IM.fromSet (const mempty) keys}+-- | Pad out the datemap of a 'PeriodData' so that every key from another 'PeriodData' is present.+padPeriodData :: a -> PeriodData b -> PeriodData a -> PeriodData a+padPeriodData x pad bal = bal{pdperiods = pdperiods bal <> (x <$ pdperiods pad)} ++-- | Convert 'PeriodData Day' to a list of 'DateSpan's.+periodDataToDateSpans :: PeriodData Day -> [DateSpan]+periodDataToDateSpans = map (\(s, e) -> DateSpan (toEFDay s) (toEFDay e)) . snd . periodDataToList+  where toEFDay = Just . Exact++-- Convert a periodic report 'Maybe (PeriodData Day)' to a list of 'DateSpans',+-- replacing the empty case with an appropriate placeholder.+maybePeriodDataToDateSpans :: Maybe (PeriodData Day) -> [DateSpan]+maybePeriodDataToDateSpans = maybe [DateSpan Nothing Nothing] periodDataToDateSpans++-- | Convert a list of 'DateSpan's to a 'PeriodData Day', or 'Nothing' if it is not well-formed.+-- PARTIAL:+dateSpansToPeriodData :: [DateSpan] -> Maybe (PeriodData Day)+-- Handle the cases of partitions which would arise from journals with no transactions+dateSpansToPeriodData []                           = Nothing+dateSpansToPeriodData [DateSpan Nothing  Nothing]  = Nothing+dateSpansToPeriodData [DateSpan Nothing  (Just _)] = Nothing+dateSpansToPeriodData [DateSpan (Just _) Nothing]  = Nothing+-- Handle properly defined reports+dateSpansToPeriodData (x:xs) = Just $ periodDataFromList (fst $ boundaries x) (map boundaries (x:xs))+  where+    boundaries spn = makeJust (spanStart spn, spanEnd spn)+    makeJust (Just a, Just b)  = (a, b)+    makeJust ab = error' $ "dateSpansToPeriodData: expected all spans to have start and end dates, but one has " ++ show ab++intToDay = ModifiedJulianDay . toInteger+dayToInt = fromInteger . toModifiedJulianDay  -- tests 
Hledger/Data/Posting.hs view
@@ -46,8 +46,6 @@   postingDate,   postingDate2,   postingDateOrDate2,-  isPostingInDateSpan,-  isPostingInDateSpan',   -- * account name operations   accountNamesFromPostings,   -- * comment/tag operations@@ -107,7 +105,7 @@ import Hledger.Data.Types import Hledger.Data.Amount import Hledger.Data.AccountName-import Hledger.Data.Dates (nulldate, spanContainsDate)+import Hledger.Data.Dates (nulldate) import Hledger.Data.Valuation  @@ -443,15 +441,6 @@ relatedPostings :: Posting -> [Posting] relatedPostings p@Posting{ptransaction=Just t} = filter (/= p) $ tpostings t relatedPostings _ = []---- | Does this posting fall within the given date span ?-isPostingInDateSpan :: DateSpan -> Posting -> Bool-isPostingInDateSpan = isPostingInDateSpan' PrimaryDate---- --date2-sensitive version, separate for now to avoid disturbing multiBalanceReport.-isPostingInDateSpan' :: WhichDate -> DateSpan -> Posting -> Bool-isPostingInDateSpan' PrimaryDate   s = spanContainsDate s . postingDate-isPostingInDateSpan' SecondaryDate s = spanContainsDate s . postingDate2  isEmptyPosting :: Posting -> Bool isEmptyPosting = mixedAmountLooksZero . pamount
Hledger/Read/Common.hs view
@@ -1025,7 +1025,7 @@     }  -- Parse a Ledger-style lot cost,--- {UNITCOST} or {{TOTALCOST}} or {=FIXEDUNITCOST} or {{=FIXEDTOTALCOST}},+-- {UNITCOST} or {{TOTALCOST}} or {=FIXEDUNITCOST} or {{=FIXEDTOTALCOST}} or {}, -- and discard it. lotcostp :: JournalParser m () lotcostp =@@ -1036,7 +1036,7 @@   lift skipNonNewlineSpaces   _fixed <- fmap isJust $ optional $ char '='   lift skipNonNewlineSpaces-  _a <- simpleamountp False+  _a <- option 0 $ simpleamountp False   lift skipNonNewlineSpaces   char '}'   when (doublebrace) $ void $ char '}'
Hledger/Reports/BudgetReport.hs view
@@ -19,12 +19,12 @@ import Data.Bifunctor (bimap) import Data.Foldable (toList) import Data.List (find, maximumBy, intercalate)-import Data.List.Extra (nubSort) import Data.Maybe (catMaybes, fromMaybe, isJust) import Data.Ord (comparing) import qualified Data.Set as S import qualified Data.Text as T import Data.These (These(..), these)+import Data.Time (Day) import Safe (minimumDef)  import Hledger.Data@@ -89,7 +89,7 @@         -- budgetgoalreport's span might be shorter actualreport's due to periodic txns;         -- it should be safe to replace it with the latter, so they combine well.         NoInterval -> actualspans-        _          -> nubSort . filter (/= nulldatespan) $ actualspans ++ budgetspans+        _          -> maybe id (padPeriodData nulldate) budgetspans <$> actualspans      actualps = dbg5 "actualps" $ getPostings rspec actualj priceoracle reportspan     budgetps = dbg5 "budgetps" $ getPostings rspec budgetj priceoracle reportspan@@ -107,7 +107,7 @@ -- | Lay out a set of postings grouped by date span into a regular matrix with rows -- given by AccountName and columns by DateSpan, then generate a MultiBalanceReport -- from the columns.-generateBudgetReport :: ReportOpts -> [DateSpan] -> Account (These BalanceData BalanceData) -> BudgetReport+generateBudgetReport :: ReportOpts -> Maybe (PeriodData Day) -> Account (These BalanceData BalanceData) -> BudgetReport generateBudgetReport = generatePeriodicReport makeBudgetReportRow treeActualBalance flatActualBalance   where     treeActualBalance = these bdincludingsubs (const nullmixedamt) (const . bdincludingsubs)
Hledger/Reports/MultiBalanceReport.hs view
@@ -43,8 +43,7 @@ import Data.List.NonEmpty (NonEmpty((:|))) import qualified Data.HashSet as HS import qualified Data.IntMap.Strict as IM-import qualified Data.IntSet as IS-import Data.Maybe (fromMaybe, isJust, mapMaybe)+import Data.Maybe (fromMaybe, isJust) import Data.Ord (Down(..)) import Data.Semigroup (sconcat) import Data.These (these)@@ -163,7 +162,7 @@         subreportTotal (_, sr, increasestotal) =             (if increasestotal then id else fmap maNegate) $ prTotals sr -    cbr = CompoundPeriodicReport "" colspans subreports overalltotals+    cbr = CompoundPeriodicReport "" (maybePeriodDataToDateSpans colspans) subreports overalltotals   -- | Remove any date queries and insert queries from the report span.@@ -217,7 +216,7 @@  -- | Generate the 'Account' for the requested multi-balance report from a list -- of 'Posting's.-generateMultiBalanceAccount :: ReportSpec -> Journal -> PriceOracle -> [DateSpan] -> [Posting] -> Account BalanceData+generateMultiBalanceAccount :: ReportSpec -> Journal -> PriceOracle -> Maybe (PeriodData Day) -> [Posting] -> Account BalanceData generateMultiBalanceAccount rspec@ReportSpec{_rsReportOpts=ropts} j priceoracle colspans =     -- Add declared accounts if called with --declared and --empty     (if (declared_ ropts && empty_ ropts) then addDeclaredAccounts rspec j else id)@@ -263,8 +262,10 @@ -- | Gather the account balance changes into a regular matrix, then -- accumulate and value amounts, as specified by the report options. -- Makes sure all report columns have an entry.-calculateReportAccount :: ReportSpec -> Journal -> PriceOracle -> [DateSpan] -> [Posting] -> Account BalanceData-calculateReportAccount rspec@ReportSpec{_rsReportOpts=ropts} j priceoracle colspans ps =  -- PARTIAL:+calculateReportAccount :: ReportSpec -> Journal -> PriceOracle -> Maybe (PeriodData Day) -> [Posting] -> Account BalanceData+calculateReportAccount _ _ _ Nothing _ =+    accountFromBalances "root" $ periodDataFromList mempty [(nulldate, mempty)]+calculateReportAccount rspec@ReportSpec{_rsReportOpts=ropts} j priceoracle (Just colspans) ps =     mapPeriodData rowbals changesAcct   where     -- The valued row amounts to be displayed: per-period changes,@@ -291,23 +292,17 @@         avalue = periodDataValuation ropts j priceoracle colspans      changesAcct = dbg5With (\x -> "calculateReportAccount changesAcct\n" ++ showAccounts x) .-        mapPeriodData (padPeriodData intervalStarts) $+        mapPeriodData (padPeriodData mempty colspans) $         accountFromPostings getIntervalStartDate ps -    getIntervalStartDate p = intToDay <$> IS.lookupLE (dayToInt $ getPostingDate p) intervalStarts+    getIntervalStartDate p = fst <$> lookupPeriodData (getPostingDate p) colspans     getPostingDate = postingDateOrDate2 (whichDate (_rsReportOpts rspec)) -    intervalStarts = IS.fromList . map dayToInt $ case mapMaybe spanStart colspans of-      [] -> [nulldate]  -- Deal with the case of the empty journal-      xs -> xs-    dayToInt = fromInteger . toModifiedJulianDay-    intToDay = ModifiedJulianDay . toInteger- -- | The valuation function to use for the chosen report options. -- This can call error in various situations.-periodDataValuation :: ReportOpts -> Journal -> PriceOracle -> [DateSpan]+periodDataValuation :: ReportOpts -> Journal -> PriceOracle -> PeriodData Day                     -> PeriodData BalanceData -> PeriodData BalanceData-periodDataValuation ropts j priceoracle colspans =+periodDataValuation ropts j priceoracle periodEnds =     opPeriodData valueBalanceData balanceDataPeriodEnds   where     valueBalanceData :: Day -> BalanceData -> BalanceData@@ -316,18 +311,9 @@     valueMixedAmount :: Day -> MixedAmount -> MixedAmount     valueMixedAmount = mixedAmountApplyValuationAfterSumFromOptsWith ropts j priceoracle +    -- The end date of a period is one before the beginning of the next period     balanceDataPeriodEnds :: PeriodData Day-    balanceDataPeriodEnds = dbg5 "balanceDataPeriodEnds" $ case colspans of  -- FIXME: Change colspans to nonempty list-        [DateSpan Nothing Nothing] -> periodDataFromList nulldate [(nulldate, nulldate)]  -- Empty journal-        h:ds                       -> periodDataFromList (makeJustFst $ boundaries h) $ map (makeJust . boundaries) (h:ds)-        []                         -> error' "balanceDataPeriodEnds: Shouldn't have empty colspans"  -- PARTIAL: Shouldn't occur-      where-        boundaries spn = (spanStart spn, spanEnd spn)--        makeJust (Just x, Just y) = (x, addDays (-1) y)-        makeJust _    = error' "balanceDataPeriodEnds: expected all non-initial spans to have start and end dates"-        makeJustFst (Just x, _) = addDays (-1) x-        makeJustFst _ = error' "balanceDataPeriodEnds: expected initial span to have an end date"+    balanceDataPeriodEnds = dbg5 "balanceDataPeriodEnds" $ addDays (-1) <$> periodEnds  -- | Mark which nodes of an 'Account' are boring, and so should be omitted from reports. markAccountBoring :: ReportSpec -> Account BalanceData -> Account BalanceData@@ -381,7 +367,7 @@ -- | Build a report row. -- -- Calculate the column totals. These are always the sum of column amounts.-generateMultiBalanceReport :: ReportOpts -> [DateSpan] -> Account BalanceData -> MultiBalanceReport+generateMultiBalanceReport :: ReportOpts -> Maybe (PeriodData Day) -> Account BalanceData -> MultiBalanceReport generateMultiBalanceReport ropts colspans =     reportPercent ropts . generatePeriodicReport makeMultiBalanceReportRow bdincludingsubs id ropts colspans @@ -391,9 +377,9 @@ generatePeriodicReport :: Show c =>     (forall a. ReportOpts -> (BalanceData -> MixedAmount) -> a -> Account b -> PeriodicReportRow a c)     -> (b -> MixedAmount) -> (c -> MixedAmount)-    -> ReportOpts -> [DateSpan] -> Account b -> PeriodicReport DisplayName c+    -> ReportOpts -> Maybe (PeriodData Day) -> Account b -> PeriodicReport DisplayName c generatePeriodicReport makeRow treeAmt flatAmt ropts colspans acct =-    PeriodicReport colspans (buildAndSort acct) totalsrow+    PeriodicReport (maybePeriodDataToDateSpans colspans) (buildAndSort acct) totalsrow   where     -- Build report rows and sort them     buildAndSort = dbg5 "generatePeriodicReport buildAndSort" . case accountlistmode_ ropts of@@ -431,6 +417,8 @@     -- Build the row for an account at a given depth with some number of boring parents     mkRows :: Bool -> Int -> Int -> Account b -> [PeriodicReportRow DisplayName c]     mkRows isRoot d boringParents acct+        -- Account is boring and has no interesting children at any depth, so we stop+        | allBoring acct                 = []         -- Account is a boring root account, and should be bypassed entirely         | aboring acct && isRoot         = buildSubrows d 0         -- Account is boring and has been dropped, so should be skipped and move up the hierarchy@@ -444,6 +432,7 @@         buildSubrows i b = concatMap (mkRows False i b) $ asubs acct      canOmitParents = flat_ ropts || not (no_elide_ ropts)+    allBoring a = aboring a && all allBoring (asubs a)     balance = case accountlistmode_ ropts of         ALTree -> bdincludingsubs         ALFlat -> bdexcludingsubs
Hledger/Reports/PostingsReport.hs view
@@ -209,12 +209,12 @@ -- | Convert a list of postings into summary postings, one per interval, -- aggregated to the specified depth if any. -- Each summary posting will have a non-Nothing interval end date.-summarisePostingsByInterval :: WhichDate -> Maybe Int -> Bool -> [DateSpan] -> [Posting] -> [SummaryPosting]+summarisePostingsByInterval :: WhichDate -> Maybe Int -> Bool -> Maybe (PeriodData Day) -> [Posting] -> [SummaryPosting] summarisePostingsByInterval wd mdepth showempty colspans =     concatMap (\(s,ps) -> summarisePostingsInDateSpan s wd mdepth showempty ps)     -- Group postings into their columns. We try to be efficient, since     -- there can possibly be a very large number of intervals (cf #1683)-    . groupByDateSpan showempty (postingDateOrDate2 wd) colspans+    . groupByDateSpan showempty (postingDateOrDate2 wd) (maybePeriodDataToDateSpans colspans)  -- | Given a date span (representing a report interval) and a list of -- postings within it, aggregate the postings into one summary posting per@@ -416,7 +416,7 @@     -}    ,testCase "summarisePostingsByInterval" $-    summarisePostingsByInterval PrimaryDate Nothing False [DateSpan Nothing Nothing] [] @?= []+    summarisePostingsByInterval PrimaryDate Nothing False Nothing [] @?= []    -- ,tests_summarisePostingsInDateSpan = [     --  "summarisePostingsInDateSpan" ~: do
Hledger/Reports/ReportOptions.hs view
@@ -677,7 +677,7 @@           _          -> spanEnd <=< latestSpanContaining (historical : spans)      historical = DateSpan Nothing $ (fmap Exact . spanStart) =<< headMay spans-    spans = snd $ reportSpanBothDates j rspec+    spans = maybePeriodDataToDateSpans . snd $ reportSpanBothDates j rspec     styles = journalCommodityStyles j     err = error' "journalApplyValuationFromOpts: expected all spans to have an end date" @@ -778,18 +778,18 @@ -- (or non-future market price date, when doing an end value report) is used. -- If none of these things are present, the null date span is returned. -- The report sub-periods caused by a report interval, if any, are also returned.-reportSpan :: Journal -> ReportSpec -> (DateSpan, [DateSpan])+reportSpan :: Journal -> ReportSpec -> (DateSpan, Maybe (PeriodData Day)) reportSpan = reportSpanHelper False -- Note: In end value reports, the report end date and valuation date are the same. -- If valuation date ever needs to be different, journalApplyValuationFromOptsWith is the place.  -- | Like reportSpan, but considers both primary and secondary dates, not just one or the other.-reportSpanBothDates :: Journal -> ReportSpec -> (DateSpan, [DateSpan])+reportSpanBothDates :: Journal -> ReportSpec -> (DateSpan, Maybe (PeriodData Day)) reportSpanBothDates = reportSpanHelper True -reportSpanHelper :: Bool -> Journal -> ReportSpec -> (DateSpan, [DateSpan])+reportSpanHelper :: Bool -> Journal -> ReportSpec -> (DateSpan, Maybe (PeriodData Day)) reportSpanHelper bothdates j ReportSpec{_rsQuery=query, _rsReportOpts=ropts, _rsDay=today} =-  (enlargedreportspan, if not (null intervalspans) then intervalspans else [enlargedreportspan])+  (enlargedreportspan, dateSpansToPeriodData $ if not (null intervalspans) then intervalspans else [enlargedreportspan])   where     -- The date span specified by -b/-e/-p options and query args if any.     requestedspan = dbg3 "requestedspan" $
hledger-lib.cabal view
@@ -1,11 +1,11 @@ cabal-version: 2.2 --- This file has been generated from package.yaml by hpack version 0.38.2.+-- This file has been generated from package.yaml by hpack version 0.38.1. -- -- see: https://github.com/sol/hpack  name:           hledger-lib-version:        1.50+version:        1.50.1 synopsis:       A library providing the core functionality of hledger description:    This library contains hledger's core functionality.                 It is used by most hledger* packages so that they support the same