-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Core data types, parsers and utilities for the hledger accounting tool. -- -- hledger is a library and set of user tools for working with financial -- data (or anything that can be tracked in a double-entry accounting -- ledger.) It is a haskell port and friendly fork of John Wiegley's -- Ledger. hledger provides command-line, curses and web interfaces, and -- aims to be a reliable, practical tool for daily use. @package hledger-lib @version 0.21 -- | UTF-8 aware string IO functions that will work across multiple -- platforms and GHC versions. Includes code from Text.Pandoc.UTF8 ((C) -- 2010 John MacFarlane). -- -- Example usage: -- -- import Prelude hiding -- (readFile,writeFile,appendFile,getContents,putStr,putStrLn) import -- UTF8IOCompat -- (readFile,writeFile,appendFile,getContents,putStr,putStrLn) import -- UTF8IOCompat -- (SystemString,fromSystemString,toSystemString,error',userError') -- -- 2013410 update: we now trust that current GHC versions & -- platforms do the right thing, so this file is a no-op and on its way -- to being removed. Not carefully tested. module Hledger.Utils.UTF8IOCompat -- | The readFile function reads a file and returns the contents of -- the file as a string. The file is read lazily, on demand, as with -- getContents. readFile :: FilePath -> IO String -- | The computation writeFile file str function writes the -- string str, to the file file. writeFile :: FilePath -> String -> IO () -- | The computation appendFile file str function appends -- the string str, to the file file. -- -- Note that writeFile and appendFile write a literal -- string to a file. To write a value of any printable type, as with -- print, use the show function to convert the value to a -- string first. -- --
--   main = appendFile "squares" (show [(x,x*x) | x <- [0,0.1..2]])
--   
appendFile :: FilePath -> String -> IO () -- | The getContents operation returns all user input as a single -- string, which is read lazily as it is needed (same as -- hGetContents stdin). getContents :: IO String -- | Computation hGetContents hdl returns the list of -- characters corresponding to the unread portion of the channel or file -- managed by hdl, which is put into an intermediate state, -- semi-closed. In this state, hdl is effectively closed, -- but items are read from hdl on demand and accumulated in a -- special list returned by hGetContents hdl. -- -- Any operation that fails because a handle is closed, also fails if a -- handle is semi-closed. The only exception is hClose. A -- semi-closed handle becomes closed: -- -- -- -- Once a semi-closed handle becomes closed, the contents of the -- associated list becomes fixed. The contents of this final list is only -- partially specified: it will contain at least all the items of the -- stream that were evaluated prior to the handle becoming closed. -- -- Any I/O errors encountered while a handle is semi-closed are simply -- discarded. -- -- This operation may fail with: -- -- hGetContents :: Handle -> IO String -- | Write a string to the standard output device (same as hPutStr -- stdout). putStr :: String -> IO () -- | The same as putStr, but adds a newline character. putStrLn :: String -> IO () -- | Computation hPutStr hdl s writes the string s -- to the file or channel managed by hdl. -- -- This operation may fail with: -- -- hPutStr :: Handle -> String -> IO () -- | The same as hPutStr, but adds a newline character. hPutStrLn :: Handle -> String -> IO () -- | A string received from or being passed to the operating system, such -- as a file path, command-line argument, or environment variable name or -- value. With GHC versions before 7.2 on some platforms (posix) these -- are typically encoded. When converting, we assume the encoding is -- UTF-8 (cf -- http://www.dwheeler.com/essays/fixing-unix-linux-filenames.html#UTF8). type SystemString = String -- | Convert a system string to an ordinary string, decoding from UTF-8 if -- it appears to be UTF8-encoded and GHC version is less than 7.2. fromSystemString :: SystemString -> String -- | Convert a unicode string to a system string, encoding with UTF-8 if we -- are on a posix platform with GHC < 7.2. toSystemString :: String -> SystemString -- | A SystemString-aware version of error. error' :: String -> a -- | A SystemString-aware version of userError. userError' :: String -> IOError -- | Most data types are defined here to avoid import cycles. Here is an -- overview of the hledger data model: -- --
--   Journal                  -- a journal is read from one or more data files. It contains..
--    [Transaction]           -- journal transactions (aka entries), which have date, status, code, description and..
--     [Posting]              -- multiple account postings, which have account name and amount
--    [HistoricalPrice]       -- historical commodity prices
--   
--   Ledger                   -- a ledger is derived from a journal, by applying a filter specification and doing some further processing. It contains..
--    Journal                 -- a filtered copy of the original journal, containing only the transactions and postings we are interested in
--    [Account]               -- all accounts, in tree order beginning with a "root" account", with their balances and sub/parent accounts
--   
-- -- For more detailed documentation on each type, see the corresponding -- modules. module Hledger.Data.Types type SmartDate = (String, String, String) data WhichDate PrimaryDate :: WhichDate SecondaryDate :: WhichDate data DateSpan DateSpan :: (Maybe Day) -> (Maybe Day) -> DateSpan data Interval NoInterval :: Interval Days :: Int -> Interval Weeks :: Int -> Interval Months :: Int -> Interval Quarters :: Int -> Interval Years :: Int -> Interval DayOfMonth :: Int -> Interval DayOfWeek :: Int -> Interval type AccountName = String data Side L :: Side R :: Side type Commodity = String type Quantity = Double -- | An amount's price (none, per unit, or total) in another commodity. -- Note the price should be a positive number, although this is not -- enforced. data Price NoPrice :: Price UnitPrice :: Amount -> Price TotalPrice :: Amount -> Price -- | Display style for an amount. data AmountStyle AmountStyle :: Side -> Bool -> Int -> Char -> Char -> [Int] -> AmountStyle -- | does the symbol appear on the left or the right ? ascommodityside :: AmountStyle -> Side -- | space between symbol and quantity ? ascommodityspaced :: AmountStyle -> Bool -- | number of digits displayed after the decimal point asprecision :: AmountStyle -> Int -- | character used as decimal point asdecimalpoint :: AmountStyle -> Char -- | character used for separating digit groups (eg thousands) asseparator :: AmountStyle -> Char -- | positions of digit group separators, counting leftward from decimal -- point asseparatorpositions :: AmountStyle -> [Int] data Amount Amount :: Commodity -> Quantity -> Price -> AmountStyle -> Amount acommodity :: Amount -> Commodity aquantity :: Amount -> Quantity -- | the (fixed) price for this amount, if any aprice :: Amount -> Price astyle :: Amount -> AmountStyle newtype MixedAmount Mixed :: [Amount] -> MixedAmount data PostingType RegularPosting :: PostingType VirtualPosting :: PostingType BalancedVirtualPosting :: PostingType type Tag = (String, String) data Posting Posting :: Maybe Day -> Maybe Day -> Bool -> AccountName -> MixedAmount -> String -> PostingType -> [Tag] -> Maybe MixedAmount -> Maybe Transaction -> Posting -- | this posting's date, if different from the transaction's pdate :: Posting -> Maybe Day -- | this posting's secondary date, if different from the transaction's pdate2 :: Posting -> Maybe Day pstatus :: Posting -> Bool paccount :: Posting -> AccountName pamount :: Posting -> MixedAmount -- | this posting's non-tag comment lines, as a single non-indented string pcomment :: Posting -> String ptype :: Posting -> PostingType ptags :: Posting -> [Tag] -- | optional: the expected balance in the account after this posting pbalanceassertion :: Posting -> Maybe MixedAmount -- | this posting's parent transaction (co-recursive types). Tying this -- knot gets tedious, Maybe makes it easier/optional. ptransaction :: Posting -> Maybe Transaction data Transaction Transaction :: Day -> Maybe Day -> Bool -> String -> String -> String -> [Tag] -> [Posting] -> String -> Transaction tdate :: Transaction -> Day tdate2 :: Transaction -> Maybe Day tstatus :: Transaction -> Bool tcode :: Transaction -> String tdescription :: Transaction -> String -- | this transaction's non-tag comment lines, as a single non-indented -- string tcomment :: Transaction -> String ttags :: Transaction -> [Tag] -- | this transaction's postings tpostings :: Transaction -> [Posting] tpreceding_comment_lines :: Transaction -> String data ModifierTransaction ModifierTransaction :: String -> [Posting] -> ModifierTransaction mtvalueexpr :: ModifierTransaction -> String mtpostings :: ModifierTransaction -> [Posting] data PeriodicTransaction PeriodicTransaction :: String -> [Posting] -> PeriodicTransaction ptperiodicexpr :: PeriodicTransaction -> String ptpostings :: PeriodicTransaction -> [Posting] data TimeLogCode SetBalance :: TimeLogCode SetRequiredHours :: TimeLogCode In :: TimeLogCode Out :: TimeLogCode FinalOut :: TimeLogCode data TimeLogEntry TimeLogEntry :: TimeLogCode -> LocalTime -> String -> TimeLogEntry tlcode :: TimeLogEntry -> TimeLogCode tldatetime :: TimeLogEntry -> LocalTime tlcomment :: TimeLogEntry -> String data HistoricalPrice HistoricalPrice :: Day -> Commodity -> Amount -> HistoricalPrice hdate :: HistoricalPrice -> Day hcommodity :: HistoricalPrice -> Commodity hamount :: HistoricalPrice -> Amount type Year = Integer -- | A journal context is some data which can change in the course -- of parsing a journal. An example is the default year, which changes -- when a Y directive is encountered. At the end of parsing, the final -- context is saved for later use by eg the add command. data JournalContext Ctx :: !(Maybe Year) -> !(Maybe (Commodity, AmountStyle)) -> ![AccountName] -> ![(AccountName, AccountName)] -> JournalContext -- | the default year most recently specified with Y ctxYear :: JournalContext -> !(Maybe Year) -- | the default commodity and amount style most recently specified with D ctxCommodityAndStyle :: JournalContext -> !(Maybe (Commodity, AmountStyle)) -- | the current stack of parent accounts/account name components specified -- with account directive(s). Concatenated, these are the account -- prefix prepended to parsed account names. ctxAccount :: JournalContext -> ![AccountName] -- | the current list of account name aliases in effect ctxAliases :: JournalContext -> ![(AccountName, AccountName)] data Journal Journal :: [ModifierTransaction] -> [PeriodicTransaction] -> [Transaction] -> [TimeLogEntry] -> [HistoricalPrice] -> String -> JournalContext -> [(FilePath, String)] -> ClockTime -> Map Commodity AmountStyle -> Journal jmodifiertxns :: Journal -> [ModifierTransaction] jperiodictxns :: Journal -> [PeriodicTransaction] jtxns :: Journal -> [Transaction] open_timelog_entries :: Journal -> [TimeLogEntry] historical_prices :: Journal -> [HistoricalPrice] -- | any trailing comments from the journal file final_comment_lines :: Journal -> String -- | the context (parse state) at the end of parsing jContext :: Journal -> JournalContext -- | the file path and raw text of the main and any included journal files. -- The main file is first followed by any included files in the order -- encountered (XXX reversed, cf journalAddFile). files :: Journal -> [(FilePath, String)] -- | when this journal was last read from its file(s) filereadtime :: Journal -> ClockTime -- | how to display amounts in each commodity jcommoditystyles :: Journal -> Map Commodity AmountStyle -- | A JournalUpdate is some transformation of a Journal. It can do I/O or -- raise an error. type JournalUpdate = ErrorT String IO (Journal -> Journal) -- | The id of a data format understood by hledger, eg journal or -- csv. type Format = String -- | A hledger journal reader is a triple of format name, format-detecting -- predicate, and a parser to Journal. data Reader Reader :: Format -> (FilePath -> String -> Bool) -> (Maybe FilePath -> FilePath -> String -> ErrorT String IO Journal) -> Reader rFormat :: Reader -> Format rDetector :: Reader -> FilePath -> String -> Bool rParser :: Reader -> Maybe FilePath -> FilePath -> String -> ErrorT String IO Journal data HledgerFormatField AccountField :: HledgerFormatField DefaultDateField :: HledgerFormatField DescriptionField :: HledgerFormatField TotalField :: HledgerFormatField DepthSpacerField :: HledgerFormatField FieldNo :: Int -> HledgerFormatField data FormatString FormatLiteral :: String -> FormatString FormatField :: Bool -> (Maybe Int) -> (Maybe Int) -> HledgerFormatField -> FormatString -- | An account, with name, balances and links to parent/subaccounts which -- let you walk up or down the account tree. data Account Account :: AccountName -> MixedAmount -> [Account] -> MixedAmount -> Maybe Account -> Bool -> Account -- | this account's full name aname :: Account -> AccountName -- | this account's balance, excluding subaccounts aebalance :: Account -> MixedAmount -- | sub-accounts anumpostings :: Int -- ^ number of postings to this -- account derived from the above: asubs :: Account -> [Account] -- | this account's balance, including subaccounts aibalance :: Account -> MixedAmount -- | parent account aparent :: Account -> Maybe Account -- | used in the accounts report to label elidable parents aboring :: Account -> Bool -- | A Ledger has the journal it derives from, and the accounts derived -- from that. Accounts are accessible both list-wise and tree-wise, since -- each one knows its parent and subs; the first account is the root of -- the tree and always exists. data Ledger Ledger :: Journal -> [Account] -> Ledger ljournal :: Ledger -> Journal laccounts :: Ledger -> [Account] instance Typeable Journal instance Eq WhichDate instance Show WhichDate instance Eq DateSpan instance Show DateSpan instance Ord DateSpan instance Eq Interval instance Show Interval instance Ord Interval instance Eq Side instance Show Side instance Read Side instance Ord Side instance Eq AmountStyle instance Ord AmountStyle instance Show AmountStyle instance Read AmountStyle instance Eq Amount instance Ord Amount instance Eq Price instance Ord Price instance Eq MixedAmount instance Ord MixedAmount instance Eq PostingType instance Show PostingType instance Eq Transaction instance Eq ModifierTransaction instance Eq PeriodicTransaction instance Eq TimeLogCode instance Ord TimeLogCode instance Eq TimeLogEntry instance Ord TimeLogEntry instance Eq HistoricalPrice instance Read JournalContext instance Show JournalContext instance Eq JournalContext instance Eq Journal instance Show HledgerFormatField instance Eq HledgerFormatField instance Show FormatString instance Eq FormatString instance Show Reader instance Eq Posting module Hledger.Data.FormatStrings parseFormatString :: String -> Either String [FormatString] formatStrings :: GenParser Char st [FormatString] formatValue :: Bool -> Maybe Int -> Maybe Int -> String -> String data FormatString FormatLiteral :: String -> FormatString FormatField :: Bool -> (Maybe Int) -> (Maybe Int) -> HledgerFormatField -> FormatString data HledgerFormatField AccountField :: HledgerFormatField DefaultDateField :: HledgerFormatField DescriptionField :: HledgerFormatField TotalField :: HledgerFormatField DepthSpacerField :: HledgerFormatField FieldNo :: Int -> HledgerFormatField tests :: Test -- | Standard imports and utilities which are useful everywhere, or needed -- low in the module hierarchy. This is the bottom of hledger's module -- graph. module Hledger.Utils lowercase :: [Char] -> [Char] uppercase :: [Char] -> [Char] strip :: [Char] -> String lstrip :: String -> String rstrip :: [Char] -> [Char] stripbrackets :: String -> String elideLeft :: Int -> [Char] -> [Char] elideRight :: Int -> [Char] -> [Char] underline :: String -> String -- | Wrap a string in single quotes, and -prefix any embedded single -- quotes, if it contains whitespace and is not already single- or -- double-quoted. quoteIfSpaced :: String -> String escapeSingleQuotes :: String -> String escapeQuotes :: String -> String -- | Quote-aware version of words - don't split on spaces which are inside -- quotes. NB correctly handles a'b but not ''a''. Can -- raise an error if parsing fails. words' :: String -> [String] -- | Quote-aware version of unwords - single-quote strings which contain -- whitespace unwords' :: [String] -> String -- | Single-quote this string if it contains whitespace or double-quotes singleQuoteIfNeeded :: [Char] -> [Char] whitespacechars :: [Char] -- | Strip one matching pair of single or double quotes on the ends of a -- string. stripquotes :: String -> String isSingleQuoted :: [Char] -> Bool isDoubleQuoted :: [Char] -> Bool unbracket :: String -> String -- | Join multi-line strings as side-by-side rectangular strings of the -- same height, top-padded. concatTopPadded :: [String] -> String -- | Join multi-line strings as side-by-side rectangular strings of the -- same height, bottom-padded. concatBottomPadded :: [String] -> String -- | Compose strings vertically and right-aligned. vConcatRightAligned :: [String] -> String -- | Convert a multi-line string to a rectangular string top-padded to the -- specified height. padtop :: Int -> String -> String -- | Convert a multi-line string to a rectangular string bottom-padded to -- the specified height. padbottom :: Int -> String -> String -- | Convert a multi-line string to a rectangular string left-padded to the -- specified width. padleft :: Int -> String -> String -- | Convert a multi-line string to a rectangular string right-padded to -- the specified width. padright :: Int -> String -> String -- | Clip a multi-line string to the specified width and height from the -- top left. cliptopleft :: Int -> Int -> String -> String -- | Clip and pad a multi-line string to fill the specified width and -- height. fitto :: Int -> Int -> String -> String difforzero :: (Num a, Ord a) => a -> a -> a regexMatch :: String -> String -> Maybe (RegexResult, MatchList) regexMatchCI :: String -> String -> Maybe (RegexResult, MatchList) regexMatches :: String -> String -> Bool regexMatchesCI :: String -> String -> Bool containsRegex :: String -> String -> Bool regexReplace :: String -> String -> String -> String regexReplaceCI :: String -> String -> String -> String regexReplaceBy :: String -> (String -> String) -> String -> String regexToCaseInsensitive :: String -> String regexSplit :: String -> String -> [String] regexMatchesRegexCompat :: String -> String -> Bool regexMatchesCIRegexCompat :: String -> String -> Bool splitAtElement :: Eq a => a -> [a] -> [[a]] root :: Tree a -> a subs :: Tree a -> Forest a branches :: Tree a -> Forest a -- | List just the leaf nodes of a tree leaves :: Tree a -> [a] -- | get the sub-tree rooted at the first (left-most, depth-first) -- occurrence of the specified node value subtreeat :: Eq a => a -> Tree a -> Maybe (Tree a) -- | get the sub-tree for the specified node value in the first tree in -- forest in which it occurs. subtreeinforest :: Eq a => a -> [Tree a] -> Maybe (Tree a) -- | remove all nodes past a certain depth treeprune :: Int -> Tree a -> Tree a -- | apply f to all tree nodes treemap :: (a -> b) -> Tree a -> Tree b -- | remove all subtrees whose nodes do not fulfill predicate treefilter :: (a -> Bool) -> Tree a -> Tree a -- | is predicate true in any node of tree ? treeany :: (a -> Bool) -> Tree a -> Bool -- | show a compact ascii representation of a tree showtree :: Show a => Tree a -> String -- | show a compact ascii representation of a forest showforest :: Show a => Forest a -> String -- | An efficient-to-build tree suggested by Cale Gibbard, probably better -- than accountNameTreeFrom. newtype FastTree a T :: (Map a (FastTree a)) -> FastTree a emptyTree :: FastTree a mergeTrees :: Ord a => FastTree a -> FastTree a -> FastTree a treeFromPath :: [a] -> FastTree a treeFromPaths :: Ord a => [[a]] -> FastTree a -- | trace (print on stdout at runtime) a showable expression (for easily -- tracing in the middle of a complex expression) strace :: Show a => a -> a -- | labelled trace showable - like strace, with a label prepended lstrace :: Show a => String -> a -> a -- | monadic trace - like strace, but works as a standalone line in a monad mtrace :: (Monad m, Show a) => a -> m a -- | trace an expression using a custom show function tracewith :: (a -> String) -> a -> a -- | Parsec trace - show the current parsec position and next input, and -- the provided string if it's non-null. ptrace :: String -> GenParser Char st () debugLevel :: Float -- | Print a message to the console if the global debugLevel is greater -- than the level we are called with. dbg :: Monad m => Float -> String -> m () -- | Print a message and parsec position info to the console if the global -- debugLevel is greater than the level we are called with. pdbg :: -- GenParser m => Float -> String -> m () pdbg :: Float -> String -> ParsecT [Char] st Identity () -- | Backtracking choice, use this when alternatives share a prefix. -- Consumes no input if all choices fail. choice' :: [GenParser tok st a] -> GenParser tok st a parsewith :: Parser a -> String -> Either ParseError a parseWithCtx :: b -> GenParser Char b a -> String -> Either ParseError a fromparse :: Either ParseError a -> a parseerror :: ParseError -> a showParseError :: ParseError -> String showDateParseError :: ParseError -> String nonspace :: GenParser Char st Char spacenonewline :: GenParser Char st Char restofline :: GenParser Char st String eolof :: GenParser Char st () getCurrentLocalTime :: IO LocalTime -- | Get a Test's label, or the empty string. testName :: Test -> String -- | Flatten a Test containing TestLists into a list of single tests. flattenTests :: Test -> [Test] -- | Filter TestLists in a Test, recursively, preserving the structure. filterTests :: (Test -> Bool) -> Test -> Test -- | Simple way to assert something is some expected value, with no label. is :: (Eq a, Show a) => a -> a -> Assertion -- | Assert a parse result is successful, printing the parse error on -- failure. assertParse :: (Either ParseError a) -> Assertion -- | Assert a parse result is successful, printing the parse error on -- failure. assertParseFailure :: (Either ParseError a) -> Assertion -- | Assert a parse result is some expected value, printing the parse error -- on failure. assertParseEqual :: (Show a, Eq a) => (Either ParseError a) -> a -> Assertion printParseError :: Show a => a -> IO () isLeft :: Either a b -> Bool isRight :: Either a b -> Bool -- | Apply a function the specified number of times. Possibly uses O(n) -- stack ? applyN :: Int -> (a -> a) -> a -> a -- | Convert a possibly relative, possibly tilde-containing file path to an -- absolute one, given the current directory. ~username is not supported. -- Leave - unchanged. expandPath :: MonadIO m => FilePath -> FilePath -> m FilePath firstJust :: Eq a => [Maybe a] -> Maybe a -- | Read a file in universal newline mode, handling whatever newline -- convention it may contain. readFile' :: FilePath -> IO String -- | The trace function outputs the trace message given as its first -- argument, before returning the second argument as its result. -- -- For example, this returns the value of f x but first outputs -- the message. -- --
--   trace ("calling f with x = " ++ show x) (f x)
--   
-- -- The trace function should only be used for debugging, or -- for monitoring execution. The function is not referentially -- transparent: its type indicates that it is a pure function but it has -- the side effect of outputting the trace message. trace :: String -> a -> a -- | A string received from or being passed to the operating system, such -- as a file path, command-line argument, or environment variable name or -- value. With GHC versions before 7.2 on some platforms (posix) these -- are typically encoded. When converting, we assume the encoding is -- UTF-8 (cf -- http://www.dwheeler.com/essays/fixing-unix-linux-filenames.html#UTF8). type SystemString = String -- | Convert a system string to an ordinary string, decoding from UTF-8 if -- it appears to be UTF8-encoded and GHC version is less than 7.2. fromSystemString :: SystemString -> String -- | Convert a unicode string to a system string, encoding with UTF-8 if we -- are on a posix platform with GHC < 7.2. toSystemString :: String -> SystemString -- | A SystemString-aware version of error. error' :: String -> a -- | A SystemString-aware version of userError. userError' :: String -> IOError -- | Convert a generic value into a pretty String, if possible. ppShow :: Show a => a -> String instance Show a => Show (FastTree a) instance Eq a => Eq (FastTree a) instance Ord a => Ord (FastTree a) -- | AccountNames are strings like assets:cash:petty, with -- multiple components separated by :. From a set of these we -- derive the account hierarchy. module Hledger.Data.AccountName acctsepchar :: Char accountNameComponents :: AccountName -> [String] accountNameFromComponents :: [String] -> AccountName accountLeafName :: AccountName -> String accountNameLevel :: AccountName -> Int accountNameDrop :: Int -> AccountName -> AccountName -- | expandAccountNames :: [AccountName] -> [AccountName] -- | a:b:c -> [a,a:b,a:b:c] expandAccountName :: AccountName -> [AccountName] -- | topAccountNames :: [AccountName] -> [AccountName] parentAccountName :: AccountName -> AccountName parentAccountNames :: AccountName -> [AccountName] isAccountNamePrefixOf :: AccountName -> AccountName -> Bool isSubAccountNameOf :: AccountName -> AccountName -> Bool -- | From a list of account names, select those which are direct -- subaccounts of the given account name. subAccountNamesFrom :: [AccountName] -> AccountName -> [AccountName] -- | Convert a list of account names to a tree. accountNameTreeFrom :: [AccountName] -> Tree AccountName nullaccountnametree :: Tree [Char] -- | Elide an account name to fit in the specified width. From the ledger -- 2.6 news: -- --
--      What Ledger now does is that if an account name is too long, it will
--      start abbreviating the first parts of the account name down to two
--      letters in length.  If this results in a string that is still too
--      long, the front will be elided -- not the end.  For example:
--   
--   Expenses:Cash           ; OK, not too long
--        Ex:Wednesday:Cash       ; Expenses was abbreviated to fit
--        Ex:We:Afternoon:Cash    ; Expenses and Wednesday abbreviated
--        ; Expenses:Wednesday:Afternoon:Lunch:Snack:Candy:Chocolate:Cash
--        ..:Af:Lu:Sn:Ca:Ch:Cash  ; Abbreviated and elided!
--   
elideAccountName :: Int -> AccountName -> AccountName clipAccountName :: Int -> AccountName -> AccountName -- | Convert an account name to a regular expression matching it and its -- subaccounts. accountNameToAccountRegex :: String -> String -- | Convert an account name to a regular expression matching it but not -- its subaccounts. accountNameToAccountOnlyRegex :: String -> String -- | Convert an exact account-matching regular expression to a plain -- account name. accountRegexToAccountName :: String -> String -- | Does this string look like an exact account-matching regular -- expression ? isAccountRegex :: String -> Bool tests_Hledger_Data_AccountName :: Test -- | A Commodity is a symbol representing a currency or some other -- kind of thing we are tracking, and some display preferences that tell -- how to display Amounts of the commodity - is the symbol on the -- left or right, are thousands separated by comma, significant decimal -- places and so on. module Hledger.Data.Commodity nonsimplecommoditychars :: String quoteCommoditySymbolIfNeeded :: [Char] -> [Char] commodity :: [Char] commoditysymbols :: [([Char], [Char])] -- | Look up one of the sample commodities' symbol by name. comm :: String -> Commodity -- | Find the conversion rate between two commodities. Currently returns 1. conversionRate :: Commodity -> Commodity -> Double tests_Hledger_Data_Commodity :: Test -- | A simple Amount is some quantity of money, shares, or anything -- else. It has a (possibly null) Commodity and a numeric -- quantity: -- --
--   $1 
--   £-50
--   EUR 3.44 
--   GOOG 500
--   1.5h
--   90 apples
--   0 
--   
-- -- It may also have an assigned Price, representing this amount's -- per-unit or total cost in a different commodity. If present, this is -- rendered like so: -- --
--   EUR 2 @ $1.50  (unit price)
--   EUR 2 @@ $3   (total price)
--   
-- -- A MixedAmount is zero or more simple amounts, so can represent -- multiple commodities; this is the type most often used: -- --
--   0
--   $50 + EUR 3
--   16h + $13.55 + AAPL 500 + 6 oranges
--   
-- -- When a mixed amount has been "normalised", it has no more than one -- amount in each commodity and no zero amounts; or it has just a single -- zero amount and no others. -- -- Limited arithmetic with simple and mixed amounts is supported, best -- used with similar amounts since it mostly ignores assigned prices and -- commodity exchange rates. module Hledger.Data.Amount -- | The empty simple amount. amount :: Amount -- | The empty simple amount. nullamt :: Amount -- | A temporary value for parsed transactions which had no amount -- specified. missingamt :: Amount num :: Quantity -> Amount usd :: Quantity -> Amount eur :: Quantity -> Amount gbp :: Quantity -> Amount hrs :: Quantity -> Amount -- | Set an amount's unit price. at :: Amount -> Amount -> Amount -- | Set an amount's total price. (@@) :: Amount -> Amount -> Amount -- | Convert an amount to the specified commodity, ignoring and discarding -- any assigned prices and assuming an exchange rate of 1. amountWithCommodity :: Commodity -> Amount -> Amount -- | Convert an amount to the commodity of its assigned price, if any. -- Notes: -- -- costOfAmount :: Amount -> Amount -- | Divide an amount's quantity by a constant. divideAmount :: Amount -> Double -> Amount -- | A more complete amount adding operation. sumAmounts :: [Amount] -> MixedAmount amountstyle :: AmountStyle -- | Get the string representation of an amount, based on its commodity's -- display settings. String representations equivalent to zero are -- converted to just "0". showAmount :: Amount -> String -- | Get the unambiguous string representation of an amount, for debugging. showAmountDebug :: Amount -> String -- | Get the string representation of an amount, without any @ price. showAmountWithoutPrice :: Amount -> String -- | For rendering: a special precision value which means show all -- available digits. maxprecision :: Int -- | For rendering: a special precision value which forces display of a -- decimal point. maxprecisionwithpoint :: Int -- | Set an amount's display precision. setAmountPrecision :: Int -> Amount -> Amount -- | Set an amount's display precision, flipped. withPrecision :: Amount -> Int -> Amount -- | Canonicalise an amount's display style using the provided commodity -- style map. canonicaliseAmount :: Map Commodity AmountStyle -> Amount -> Amount -- | Given a list of amounts in parse order, build a map from commodities -- to canonical display styles for amounts in that commodity. canonicalStyles :: [Amount] -> Map Commodity AmountStyle -- | The empty mixed amount. nullmixedamt :: MixedAmount missingmixedamt :: MixedAmount mixed :: Amount -> MixedAmount -- | Get a mixed amount's component amounts. amounts :: MixedAmount -> [Amount] -- | Simplify a mixed amount's component amounts: combine amounts with the -- same commodity, using the first amount's price for subsequent amounts -- in each commodity (ie, this function alters the amount and is best -- used as a rendering helper.). Also remove any zero amounts and replace -- an empty amount list with a single zero amount. normaliseMixedAmountPreservingFirstPrice :: MixedAmount -> MixedAmount -- | Simplify a mixed amount's component amounts: we can combine amounts -- with the same commodity and unit price. Also remove any zero or -- missing amounts and replace an empty amount list with a single zero -- amount. normaliseMixedAmountPreservingPrices :: MixedAmount -> MixedAmount -- | Convert a mixed amount's component amounts to the commodity of their -- assigned price, if any. costOfMixedAmount :: MixedAmount -> MixedAmount -- | Divide a mixed amount's quantities by a constant. divideMixedAmount :: MixedAmount -> Double -> MixedAmount -- | Is this mixed amount negative, if it can be normalised to a single -- commodity ? isNegativeMixedAmount :: MixedAmount -> Maybe Bool -- | Does this mixed amount appear to be zero when displayed with its given -- precision ? isZeroMixedAmount :: MixedAmount -> Bool -- | Is this mixed amount really zero ? See isReallyZeroAmount. isReallyZeroMixedAmount :: MixedAmount -> Bool -- | Is this mixed amount really zero, after converting to cost -- commodities where possible ? isReallyZeroMixedAmountCost :: MixedAmount -> Bool -- | Get the string representation of a mixed amount, showing each of its -- component amounts. NB a mixed amount can have an empty amounts list in -- which case it shows as "". showMixedAmount :: MixedAmount -> String -- | Get an unambiguous string representation of a mixed amount for -- debugging. showMixedAmountDebug :: MixedAmount -> String -- | Get the string representation of a mixed amount, but without any @ -- prices. showMixedAmountWithoutPrice :: MixedAmount -> String -- | Get the string representation of a mixed amount, showing each of its -- component amounts with the specified precision, ignoring their -- commoditys' display precision settings. showMixedAmountWithPrecision :: Int -> MixedAmount -> String -- | Set the display precision in the amount's commodities. setMixedAmountPrecision :: Int -> MixedAmount -> MixedAmount -- | Canonicalise a mixed amount's display styles using the provided -- commodity style map. canonicaliseMixedAmount :: Map Commodity AmountStyle -> MixedAmount -> MixedAmount -- | Compact labelled trace of a mixed amount. ltraceamount :: String -> MixedAmount -> MixedAmount tests_Hledger_Data_Amount :: Test instance Show HistoricalPrice instance Num MixedAmount instance Show MixedAmount instance Num Amount instance Show Amount -- | Date parsing and utilities for hledger. -- -- For date and time values, we use the standard Day and UTCTime types. -- -- A SmartDate is a date which may be partially-specified or -- relative. Eg 2008/12/31, but also 2008/12, 12/31, tomorrow, last week, -- next year. We represent these as a triple of strings like -- ("2008","12",""), ("","","tomorrow"), ("","last","week"). -- -- A DateSpan is the span of time between two specific calendar -- dates, or an open-ended span where one or both dates are unspecified. -- (A date span with both ends unspecified matches all dates.) -- -- An Interval is ledger's "reporting interval" - weekly, monthly, -- quarterly, etc. module Hledger.Data.Dates -- | Get the current local date. getCurrentDay :: IO Day -- | Get the current local month number. getCurrentMonth :: IO Int -- | Get the current local year. getCurrentYear :: IO Integer nulldate :: Day -- | Does the span include the given date ? spanContainsDate :: DateSpan -> Day -> Bool -- | Parse a couple of date string formats to a time type. parsedateM :: String -> Maybe Day -- | Parse a date string to a time type, or raise an error. parsedate :: String -> Day showDate :: Day -> String elapsedSeconds :: Fractional a => UTCTime -> UTCTime -> a prevday :: Day -> Day -- | Parse a period expression to an Interval and overall DateSpan using -- the provided reference date, or return a parse error. parsePeriodExpr :: Day -> String -> Either ParseError (Interval, DateSpan) nulldatespan :: DateSpan tests_Hledger_Data_Dates :: Test failIfInvalidYear :: Monad m => String -> m () datesepchar :: ParsecT [Char] u Identity Char datesepchars :: [Char] -- | Calculate the intersection of two datespans. spanIntersect :: DateSpan -> DateSpan -> DateSpan -- | Calculate the intersection of a number of datespans. spansIntersect :: [DateSpan] -> DateSpan -- | Calculate the union of two datespans. spanUnion :: DateSpan -> DateSpan -> DateSpan -- | Calculate the union of a number of datespans. spansUnion :: [DateSpan] -> DateSpan -- | Combine two datespans, filling any unspecified dates in the first with -- dates from the second. orDatesFrom :: DateSpan -> DateSpan -> DateSpan -- | Parse a date in any of the formats allowed in ledger's period -- expressions, and maybe some others: -- --
--   2004
--   2004/10
--   2004/10/1
--   10/1
--   21
--   october, oct
--   yesterday, today, tomorrow
--   this/next/last week/day/month/quarter/year
--   
-- -- Returns a SmartDate, to be converted to a full date later (see -- fixSmartDate). Assumes any text in the parse stream has been -- lowercased. smartdate :: GenParser Char st SmartDate -- | Split a DateSpan into one or more consecutive spans at the specified -- interval. splitSpan :: Interval -> DateSpan -> [DateSpan] -- | Convert a SmartDate to an absolute date using the provided reference -- date. fixSmartDate :: Day -> SmartDate -> Day -- | Convert a smart date string to an explicit yyyy/mm/dd string using the -- provided reference date, or raise an error. fixSmartDateStr :: Day -> String -> String -- | A safe version of fixSmartDateStr. fixSmartDateStrEither :: Day -> String -> Either ParseError String fixSmartDateStrEither' :: Day -> String -> Either ParseError Day -- | Count the days in a DateSpan, or if it is open-ended return Nothing. daysInSpan :: DateSpan -> Maybe Integer maybePeriod :: Day -> String -> Maybe (Interval, DateSpan) -- | Make a datespan from two valid date strings parseable by parsedate (or -- raise an error). Eg: mkdatespan "201111" "20111231". mkdatespan :: String -> String -> DateSpan -- | A Posting represents a change (by some MixedAmount) of -- the balance in some Account. Each Transaction contains -- two or more postings which should add up to 0. Postings reference -- their parent transaction, so we can look up the date or description -- there. module Hledger.Data.Posting nullposting :: Posting posting :: Posting post :: AccountName -> Amount -> Posting -- | Is this posting cleared? If this posting was individually marked as -- cleared, returns True. Otherwise, return the parent transaction's -- cleared status or, if there is no parent transaction, return False. postingCleared :: Posting -> Bool isReal :: Posting -> Bool isVirtual :: Posting -> Bool isBalancedVirtual :: Posting -> Bool isEmptyPosting :: Posting -> Bool hasAmount :: Posting -> Bool -- | Tags for this posting including any inherited from its parent -- transaction. postingAllTags :: Posting -> [Tag] -- | Tags for this transaction including any inherited from above, when -- that is implemented. transactionAllTags :: Transaction -> [Tag] relatedPostings :: Posting -> [Posting] -- | Get a posting's (primary) date - it's own primary date if specified, -- otherwise the parent transaction's primary date, or the null date if -- there is no parent transaction. postingDate :: Posting -> Day -- | Get a posting's secondary (secondary) date, which is the first of: -- posting's secondary date, transaction's secondary date, posting's -- primary date, transaction's primary date, or the null date if there is -- no parent transaction. postingDate2 :: Posting -> Day -- | Does this posting fall within the given date span ? isPostingInDateSpan :: DateSpan -> Posting -> Bool -- | Get the minimal date span which contains all the postings, or the null -- date span if there are none. postingsDateSpan :: [Posting] -> DateSpan accountNamesFromPostings :: [Posting] -> [AccountName] accountNamePostingType :: AccountName -> PostingType accountNameWithoutPostingType :: AccountName -> AccountName accountNameWithPostingType :: PostingType -> AccountName -> AccountName -- | Prefix one account name to another, preserving posting type indicators -- like concatAccountNames. joinAccountNames :: AccountName -> AccountName -> AccountName -- | Join account names into one. If any of them has () or [] posting type -- indicators, these (the first type encountered) will also be applied to -- the resulting account name. concatAccountNames :: [AccountName] -> AccountName -- | Rewrite an account name using the first applicable alias from the -- given list, if any. accountNameApplyAliases :: [(AccountName, AccountName)] -> AccountName -> AccountName sumPostings :: [Posting] -> MixedAmount showPosting :: Posting -> String showComment :: String -> String tests_Hledger_Data_Posting :: Test instance Show Posting -- | An Account has a name, a list of subaccounts, an optional -- parent account, and subaccounting-excluding and -including balances. module Hledger.Data.Account nullacct :: Account -- | Derive an account tree with balances from a set of postings. -- (*ledger's core feature.) The accounts are returned in a list, but -- retain their tree structure; the first one is the root of the tree. accountsFromPostings :: [Posting] -> [Account] -- | Convert an AccountName tree to an Account tree nameTreeToAccount :: AccountName -> FastTree AccountName -> Account -- | Tie the knot so all subaccounts' parents are set correctly. tieAccountParents :: Account -> Account -- | Get this account's parent accounts, from the nearest up to the root. parentAccounts :: Account -> [Account] -- | List the accounts at each level of the account tree. accountsLevels :: Account -> [[Account]] -- | Map a (non-tree-structure-modifying) function over this and sub -- accounts. mapAccounts :: (Account -> Account) -> Account -> Account -- | Is the predicate true on any of this account or its subaccounts ? anyAccounts :: (Account -> Bool) -> Account -> Bool -- | Add subaccount-inclusive balances to an account tree. -- , also noting -- -- whether it has an interesting balance or interesting subs to help -- -- with eliding later. sumAccounts :: Account -> Account -- | Remove all subaccounts below a certain depth. clipAccounts :: Int -> Account -> Account -- | Remove all leaf accounts and subtrees matching a predicate. pruneAccounts :: (Account -> Bool) -> Account -> Maybe Account -- | Flatten an account tree into a list, which is sometimes convenient. -- Note since accounts link to their parents/subs, the account tree -- remains intact and can still be used. It's a tree/list! flattenAccounts :: Account -> [Account] -- | Filter an account tree (to a list). filterAccounts :: (Account -> Bool) -> Account -> [Account] -- | Search an account list by name. lookupAccount :: AccountName -> [Account] -> Maybe Account printAccounts :: Account -> IO () showAccounts :: Account -> String showAccountsBoringFlag :: Account -> String showAccountDebug :: PrintfType ([Char] -> t) => Account -> t tests_Hledger_Data_Account :: Test instance Eq Account instance Show Account -- | A Transaction represents a movement of some commodity(ies) -- between two or more accounts. It consists of multiple account -- Postings which balance to zero, a date, and optional extras -- like description, cleared status, and tags. module Hledger.Data.Transaction nulltransaction :: Transaction -- | Ensure a transaction's postings refer back to it. txnTieKnot :: Transaction -> Transaction -- | Show an account name, clipped to the given width if any, and -- appropriately bracketed/parenthesised for the given posting type. showAccountName :: Maybe Int -> PostingType -> AccountName -> String hasRealPostings :: Transaction -> Bool realPostings :: Transaction -> [Posting] virtualPostings :: Transaction -> [Posting] balancedVirtualPostings :: Transaction -> [Posting] transactionsPostings :: [Transaction] -> [Posting] -- | Is this transaction balanced ? A balanced transaction's real -- (non-virtual) postings sum to 0, and any balanced virtual postings -- also sum to 0. isTransactionBalanced :: Maybe (Map Commodity AmountStyle) -> Transaction -> Bool transactionDate2 :: Transaction -> Day -- | Get the sums of a transaction's real, virtual, and balanced virtual -- postings. transactionPostingBalances :: Transaction -> (MixedAmount, MixedAmount, MixedAmount) -- | Ensure this transaction is balanced, possibly inferring a missing -- amount or conversion price, or return an error message. -- -- Balancing is affected by commodity display precisions, so those may be -- provided. -- -- We can infer a missing real amount when there are multiple real -- postings and exactly one of them is amountless (likewise for balanced -- virtual postings). Inferred amounts are converted to cost basis when -- possible. -- -- We can infer a conversion price when all real amounts are specified -- and the sum of real postings' amounts is exactly two -- non-explicitly-priced amounts in different commodities (likewise for -- balanced virtual postings). balanceTransaction :: Maybe (Map Commodity AmountStyle) -> Transaction -> Either String Transaction -- | Show a journal transaction, formatted for the print command. ledger -- 2.x's standard format looks like this: -- --
--   yyyymmdd[ *][ CODE] description.........          [  ; comment...............]
--       account name 1.....................  ...$amount1[  ; comment...............]
--       account name 2.....................  ..$-amount1[  ; comment...............]
--   
--   pcodewidth    = no limit -- 10          -- mimicking ledger layout.
--   pdescwidth    = no limit -- 20          -- I don't remember what these mean,
--   pacctwidth    = 35 minimum, no maximum  -- they were important at the time.
--   pamtwidth     = 11
--   pcommentwidth = no limit -- 22
--   
showTransaction :: Transaction -> String showTransactionUnelided :: Transaction -> String tests_Hledger_Data_Transaction :: Test instance Show PeriodicTransaction instance Show ModifierTransaction instance Show Transaction -- | A TimeLogEntry is a clock-in, clock-out, or other directive in -- a timelog file (see timeclock.el or the command-line version). These -- can be converted to Transactions and queried like a ledger. module Hledger.Data.TimeLog -- | Convert time log entries to journal transactions. When there is no -- clockout, add one with the provided current time. Sessions crossing -- midnight are split into days to give accurate per-day totals. timeLogEntriesToTransactions :: LocalTime -> [TimeLogEntry] -> [Transaction] -- | Convert a timelog clockin and clockout entry to an equivalent journal -- transaction, representing the time expenditure. Note this entry is not -- balanced, since we omit the "assets:time" transaction for simpler -- output. entryFromTimeLogInOut :: TimeLogEntry -> TimeLogEntry -> Transaction tests_Hledger_Data_TimeLog :: Test instance Read TimeLogCode instance Show TimeLogCode instance Show TimeLogEntry -- | A general query system for matching things (accounts, postings, -- transactions..) by various criteria, and a parser for query -- expressions. module Hledger.Query -- | A query is a composition of search criteria, which can be used to -- match postings, transactions, accounts and more. data Query -- | always match Any :: Query -- | never match None :: Query -- | negate this match Not :: Query -> Query -- | match if any of these match Or :: [Query] -> Query -- | match if all of these match And :: [Query] -> Query -- | match if code matches this regexp Code :: String -> Query -- | match if description matches this regexp Desc :: String -> Query -- | match postings whose account matches this regexp Acct :: String -> Query -- | match if primary date in this date span Date :: DateSpan -> Query -- | match if secondary date in this date span Date2 :: DateSpan -> Query -- | match if cleared status has this value Status :: Bool -> Query -- | match if realness (involves a real non-virtual account ?) has -- this value Real :: Bool -> Query -- | match if the amount's numeric quantity is less thangreater -- thanequal to some value Amt :: Ordering -> Quantity -> Query -- | if true, show zero-amount postings/accounts which are usually not -- shown more of a query option than a query criteria ? Empty :: Bool -> Query -- | match if account depth is less than or equal to this value Depth :: Int -> Query -- | match if a tag with this exact name, and with value matching the -- regexp if provided, exists Tag :: String -> (Maybe String) -> Query -- | A query option changes a query's/report's behaviour and output in some -- way. data QueryOpt -- | show an account register focussed on this account QueryOptInAcctOnly :: AccountName -> QueryOpt -- | as above but include sub-accounts in the account register | -- QueryOptCostBasis -- ^ show amounts converted to cost where possible | -- QueryOptDate2 -- ^ show secondary dates instead of primary dates QueryOptInAcct :: AccountName -> QueryOpt -- | Convert a query expression containing zero or more space-separated -- terms to a query and zero or more query options. A query term is -- either: -- --
    --
  1. a search pattern, which matches on one or more fields, eg:
  2. --
-- -- acct:REGEXP - match the account name with a regular expression -- desc:REGEXP - match the transaction description date:PERIODEXP - match -- the date with a period expression -- -- The prefix indicates the field to match, or if there is no prefix -- account name is assumed. -- --
    --
  1. a query option, which modifies the reporting behaviour in some -- way. There is currently one of these, which may appear only once:
  2. --
-- -- inacct:FULLACCTNAME -- -- The usual shell quoting rules are assumed. When a pattern contains -- whitespace, it (or the whole term including prefix) should be enclosed -- in single or double quotes. -- -- Period expressions may contain relative dates, so a reference date is -- required to fully parse these. -- -- Multiple terms are combined as follows: 1. multiple account patterns -- are OR'd together 2. multiple description patterns are OR'd together -- 3. then all terms are AND'd together parseQuery :: Day -> String -> (Query, [QueryOpt]) simplifyQuery :: Query -> Query -- | Remove query terms (or whole sub-expressions) not matching the given -- predicate from this query. XXX Semantics not yet clear. filterQuery :: (Query -> Bool) -> Query -> Query -- | Does this query match everything ? queryIsNull :: Query -> Bool queryIsDepth :: Query -> Bool queryIsDate :: Query -> Bool -- | Does this query specify a start date and nothing else (that would -- filter postings prior to the date) ? When the flag is true, look for a -- starting secondary date instead. queryIsStartDateOnly :: Bool -> Query -> Bool -- | What start date (or secondary date) does this query specify, if any ? -- For OR expressions, use the earliest of the dates. NOT is ignored. queryStartDate :: Bool -> Query -> Maybe Day -- | What date span (or secondary date span) does this query specify ? For -- OR expressions, use the widest possible span. NOT is ignored. queryDateSpan :: Bool -> Query -> DateSpan -- | The depth limit this query specifies, or a large number if none. queryDepth :: Query -> Int -- | The empty (zero amount) status specified by this query, defaulting to -- false. queryEmpty :: Query -> Bool -- | The account we are currently focussed on, if any, and whether -- subaccounts are included. Just looks at the first query option. inAccount :: [QueryOpt] -> Maybe (AccountName, Bool) -- | A query for the account(s) we are currently focussed on, if any. Just -- looks at the first query option. inAccountQuery :: [QueryOpt] -> Maybe Query -- | Does the match expression match this account ? A matching in: clause -- is also considered a match. matchesAccount :: Query -> AccountName -> Bool -- | Does the match expression match this posting ? matchesPosting :: Query -> Posting -> Bool -- | Does the match expression match this transaction ? matchesTransaction :: Query -> Transaction -> Bool tests_Hledger_Query :: Test instance Show Query instance Eq Query instance Show QueryOpt instance Eq QueryOpt -- | A Journal is a set of transactions, plus optional related data. -- This is hledger's primary data object. It is usually parsed from a -- journal file or other data format (see Hledger.Read). module Hledger.Data.Journal addHistoricalPrice :: HistoricalPrice -> Journal -> Journal addModifierTransaction :: ModifierTransaction -> Journal -> Journal addPeriodicTransaction :: PeriodicTransaction -> Journal -> Journal addTimeLogEntry :: TimeLogEntry -> Journal -> Journal addTransaction :: Transaction -> Journal -> Journal -- | Apply additional account aliases (eg from the command-line) to all -- postings in a journal. journalApplyAliases :: [(AccountName, AccountName)] -> Journal -> Journal -- | Fill in any missing amounts and check that all journal transactions -- balance, or return an error message. This is done after parsing all -- amounts and working out the canonical commodities, since balancing -- depends on display precision. Reports only the first error -- encountered. journalBalanceTransactions :: Journal -> Either String Journal -- | Convert all the journal's posting amounts (not price amounts) to their -- canonical display settings. Ie, all amounts in a given commodity will -- use (a) the display settings of the first, and (b) the greatest -- precision, of the posting amounts in that commodity. journalCanonicaliseAmounts :: Journal -> Journal -- | Convert all this journal's amounts to cost by applying their prices, -- if any. journalConvertAmountsToCost :: Journal -> Journal -- | Do post-parse processing on a journal to make it ready for use: check -- all transactions balance, canonicalise amount formats, close any open -- timelog entries and so on. journalFinalise :: ClockTime -> LocalTime -> FilePath -> String -> JournalContext -> Journal -> Either String Journal -- | Keep only postings matching the query expression. This can leave -- unbalanced transactions. filterJournalPostings :: Query -> Journal -> Journal -- | Keep only transactions matching the query expression. filterJournalTransactions :: Query -> Journal -> Journal journalAccountNames :: Journal -> [AccountName] -- | All account names used in this journal. journalAccountNamesUsed :: Journal -> [AccountName] -- | Get all this journal's component amounts, roughly in the order parsed. journalAmounts :: Journal -> [Amount] -- | The (fully specified) date span containing this journal's -- transactions, or DateSpan Nothing Nothing if there are none. journalDateSpan :: Journal -> DateSpan journalFilePath :: Journal -> FilePath journalFilePaths :: Journal -> [FilePath] journalPostings :: Journal -> [Posting] -- | A query for Asset, Liability & Equity accounts in this journal. Cf -- http://en.wikipedia.org/wiki/Chart_of_accounts#Balance_Sheet_Accounts. journalBalanceSheetAccountQuery :: Journal -> Query -- | A query for Profit & Loss accounts in this journal. Cf -- http://en.wikipedia.org/wiki/Chart_of_accounts#Profit_.26_Loss_accounts. journalProfitAndLossAccountQuery :: Journal -> Query -- | A query for Income (Revenue) accounts in this journal. This is -- currently hard-coded to the case-insensitive regex -- ^(income|revenue)s?(:|$). journalIncomeAccountQuery :: Journal -> Query -- | A query for Expense accounts in this journal. This is currently -- hard-coded to the case-insensitive regex ^expenses?(:|$). journalExpenseAccountQuery :: Journal -> Query -- | A query for Asset accounts in this journal. This is currently -- hard-coded to the case-insensitive regex ^assets?(:|$). journalAssetAccountQuery :: Journal -> Query -- | A query for Liability accounts in this journal. This is currently -- hard-coded to the case-insensitive regex -- ^liabilit(y|ies)(:|$). journalLiabilityAccountQuery :: Journal -> Query -- | A query for Equity accounts in this journal. This is currently -- hard-coded to the case-insensitive regex ^equity(:|$). journalEquityAccountQuery :: Journal -> Query -- | A query for Cash (-equivalent) accounts in this journal (ie, accounts -- which appear on the cashflow statement.) This is currently hard-coded -- to be all the Asset accounts except for those containing the -- case-insensitive regex (receivable|A/R). journalCashAccountQuery :: Journal -> Query -- | Check if a set of hledger account/description filter patterns matches -- the given account name or entry description. Patterns are -- case-insensitive regular expressions. Prefixed with not:, they become -- anti-patterns. matchpats :: [String] -> String -> Bool nullctx :: JournalContext nulljournal :: Journal samplejournal :: Journal tests_Hledger_Data_Journal :: Test instance Show Journal -- | A Ledger is derived from a Journal by applying a filter -- specification to select Transactions and Postings of -- interest. It contains the filtered journal and knows the resulting -- chart of accounts, account balances, and postings in each account. module Hledger.Data.Ledger nullledger :: Ledger -- | Filter a journal's transactions with the given query, then derive a -- ledger containing the chart of accounts and balances. If the query -- includes a depth limit, that will affect the ledger's journal but not -- the account tree. ledgerFromJournal :: Query -> Journal -> Ledger -- | List a ledger's account names. ledgerAccountNames :: Ledger -> [AccountName] -- | Get the named account from a ledger. ledgerAccount :: Ledger -> AccountName -> Maybe Account -- | Get this ledger's root account, which is a dummy root account -- above all others. This should always be first in the account list, if -- somehow not this returns a null account. ledgerRootAccount :: Ledger -> Account -- | List a ledger's top-level accounts (the ones below the root), in tree -- order. ledgerTopAccounts :: Ledger -> [Account] -- | List a ledger's bottom-level (subaccount-less) accounts, in tree -- order. ledgerLeafAccounts :: Ledger -> [Account] -- | Accounts in ledger whose name matches the pattern, in tree order. ledgerAccountsMatching :: [String] -> Ledger -> [Account] -- | List a ledger's postings, in the order parsed. ledgerPostings :: Ledger -> [Posting] -- | The (fully specified) date span containing all the ledger's (filtered) -- transactions, or DateSpan Nothing Nothing if there are none. ledgerDateSpan :: Ledger -> DateSpan -- | All commodities used in this ledger. ledgerCommodities :: Ledger -> [Commodity] tests_ledgerFromJournal :: [Test] tests_Hledger_Data_Ledger :: Test instance Show Ledger -- | The Hledger.Data library allows parsing and querying of C++ -- ledger-style journal files. It generally provides a compatible subset -- of C++ ledger's functionality. This package re-exports all the -- Hledger.Data.* modules (except UTF8, which requires an explicit -- import.) module Hledger.Data tests_Hledger_Data :: Test -- | A reader for hledger's journal file format -- (http://hledger.org/MANUAL.html#the-journal-file). hledger's -- journal format is a compatible subset of c++ ledger's -- (http://ledger-cli.org/3.0/doc/ledger3.html#Journal-Format), so -- this reader should handle many ledger files as well. Example: -- --
--   2012/3/24 gift
--       expenses:gifts  $10
--       assets:cash
--   
module Hledger.Read.JournalReader reader :: Reader -- | Given a JournalUpdate-generating parsec parser, file path and data -- string, parse and post-process a Journal so that it's ready to use, or -- give an error. parseJournalWith :: (GenParser Char JournalContext (JournalUpdate, JournalContext)) -> FilePath -> String -> ErrorT String IO Journal getParentAccount :: GenParser tok JournalContext String -- | Top-level journal parser. Returns a single composite, I/O performing, -- error-raising JournalUpdate (and final JournalContext) -- which can be applied to an empty journal to get the final result. journal :: GenParser Char JournalContext (JournalUpdate, JournalContext) directive :: GenParser Char JournalContext JournalUpdate defaultyeardirective :: GenParser Char JournalContext JournalUpdate historicalpricedirective :: GenParser Char JournalContext HistoricalPrice -- | Parse a date and time in YYYYMMDD HH:MM[:SS][+-ZZZZ] format. -- Any timezone will be ignored; the time is treated as local time. Fewer -- digits are allowed, except in the timezone. The year may be omitted if -- a default year has already been set. datetime :: GenParser Char JournalContext LocalTime code :: GenParser Char JournalContext String -- | Parse an account name. Account names may have single spaces inside -- them, and are terminated by two or more spaces. They should have one -- or more components of at least one character, separated by the account -- separator char. accountname :: GenParser Char st AccountName -- | Parse a single-commodity amount, with optional symbol on the left or -- right, optional unit or total price, and optional (ignored) -- ledger-style balance assertion or fixed lot price declaration. amountp :: GenParser Char JournalContext Amount -- | Parse an amount from a string, or get an error. amountp' :: String -> Amount -- | Parse a mixed amount from a string, or get an error. mamountp' :: String -> MixedAmount emptyline :: GenParser Char JournalContext () -- | A reader for the timelog file format generated by timeclock.el -- (http://www.emacswiki.org/emacs/TimeClock). Example: -- --
--   i 2007/03/10 12:26:00 hledger
--   o 2007/03/10 17:26:02
--   
-- -- From timeclock.el 2.6: -- --
--   A timelog contains data in the form of a single entry per line.
--   Each entry has the form:
--   
--   CODE YYYYMMDD HH:MM:SS [COMMENT]
--   
--   CODE is one of: b, h, i, o or O.  COMMENT is optional when the code is
--   i, o or O.  The meanings of the codes are:
--   
--   b  Set the current time balance, or "time debt".  Useful when
--        archiving old log data, when a debt must be carried forward.
--        The COMMENT here is the number of seconds of debt.
--   
--   h  Set the required working time for the given day.  This must
--        be the first entry for that day.  The COMMENT in this case is
--        the number of hours in this workday.  Floating point amounts
--        are allowed.
--   
--   i  Clock in.  The COMMENT in this case should be the name of the
--        project worked on.
--   
--   o  Clock out.  COMMENT is unnecessary, but can be used to provide
--        a description of how the period went, for example.
--   
--   O  Final clock out.  Whatever project was being worked on, it is
--        now finished.  Useful for creating summary reports.
--   
module Hledger.Read.TimelogReader reader :: Reader tests_Hledger_Read_TimelogReader :: Test -- | A reader for CSV data, using an extra rules file to help interpret the -- data. module Hledger.Read.CsvReader reader :: Reader type CsvRecord = [String] rulesFileFor :: FilePath -> FilePath parseRulesFile :: FilePath -> IO (Either ParseError CsvRules) transactionFromCsvRecord :: CsvRules -> CsvRecord -> Transaction tests_Hledger_Read_CsvReader :: Test instance Show CsvRules instance Eq CsvRules -- | This is the entry point to hledger's reading system, which can read -- Journals from various data formats. Use this module if you want to -- parse journal data or read journal files. Generally it should not be -- necessary to import modules below this one. module Hledger.Read -- | All the data formats we can read. formats = map rFormat readers -- -- Get the default journal file path specified by the environment. Like -- ledger, we look first for the LEDGER_FILE environment variable, and if -- that does not exist, for the legacy LEDGER environment variable. If -- neither is set, or the value is blank, return the hard-coded default, -- which is .hledger.journal in the users's home directory (or -- in the current directory, if we cannot determine a home directory). defaultJournalPath :: IO String -- | Read the default journal file specified by the environment, or raise -- an error. defaultJournal :: IO Journal -- | Read a journal from this string, trying whatever readers seem -- appropriate: -- -- -- -- A CSV conversion rules file may also be specified for use by the CSV -- reader. readJournal :: Maybe Format -> Maybe FilePath -> Maybe FilePath -> String -> IO (Either String Journal) -- | Read a journal from the given string, trying all known formats, or -- simply throw an error. readJournal' :: String -> IO Journal -- | Read a Journal from this file (or stdin if the filename is -) or give -- an error message, using the specified data format or trying all known -- formats. A CSV conversion rules file may be specified for better -- conversion of that format. readJournalFile :: Maybe Format -> Maybe FilePath -> FilePath -> IO (Either String Journal) -- | If the specified journal file does not exist, give a helpful error and -- quit. requireJournalFileExists :: FilePath -> IO () -- | Ensure there is a journal file at the given path, creating an empty -- one if needed. ensureJournalFileExists :: FilePath -> IO () -- | Parse an account name. Account names may have single spaces inside -- them, and are terminated by two or more spaces. They should have one -- or more components of at least one character, separated by the account -- separator char. accountname :: GenParser Char st AccountName -- | Parse a single-commodity amount, with optional symbol on the left or -- right, optional unit or total price, and optional (ignored) -- ledger-style balance assertion or fixed lot price declaration. amountp :: GenParser Char JournalContext Amount -- | Parse an amount from a string, or get an error. amountp' :: String -> Amount -- | Parse a mixed amount from a string, or get an error. mamountp' :: String -> MixedAmount code :: GenParser Char JournalContext String samplejournal :: IO Journal tests_Hledger_Read :: Test -- | Generate several common kinds of report from a journal, as "*Report" - -- simple intermediate data structures intended to be easily rendered as -- text, html, json, csv etc. by hledger commands, hamlet templates, -- javascript, or whatever. This is under Hledger.Cli since it depends on -- the command-line options, should move to hledger-lib later. module Hledger.Reports -- | Standard options for customising report filtering and output, -- corresponding to hledger's command-line options and query language -- arguments. Used in hledger-lib and above. data ReportOpts ReportOpts :: Maybe Day -> Maybe Day -> Maybe (Interval, DateSpan) -> Bool -> Bool -> Bool -> Maybe Int -> Maybe DisplayExp -> Bool -> Bool -> Bool -> Bool -> Bool -> Int -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Maybe FormatStr -> Bool -> String -> ReportOpts begin_ :: ReportOpts -> Maybe Day end_ :: ReportOpts -> Maybe Day period_ :: ReportOpts -> Maybe (Interval, DateSpan) cleared_ :: ReportOpts -> Bool uncleared_ :: ReportOpts -> Bool cost_ :: ReportOpts -> Bool depth_ :: ReportOpts -> Maybe Int display_ :: ReportOpts -> Maybe DisplayExp date2_ :: ReportOpts -> Bool empty_ :: ReportOpts -> Bool no_elide_ :: ReportOpts -> Bool real_ :: ReportOpts -> Bool flat_ :: ReportOpts -> Bool drop_ :: ReportOpts -> Int no_total_ :: ReportOpts -> Bool daily_ :: ReportOpts -> Bool weekly_ :: ReportOpts -> Bool monthly_ :: ReportOpts -> Bool quarterly_ :: ReportOpts -> Bool yearly_ :: ReportOpts -> Bool format_ :: ReportOpts -> Maybe FormatStr related_ :: ReportOpts -> Bool query_ :: ReportOpts -> String type DisplayExp = String type FormatStr = String defreportopts :: ReportOpts -- | Figure out the date span we should report on, based on any -- beginendperiod options provided. A period option will cause -- begin and end options to be ignored. dateSpanFromOpts :: Day -> ReportOpts -> DateSpan -- | Figure out the reporting interval, if any, specified by the options. -- --period overrides --daily overrides --weekly overrides --monthly etc. intervalFromOpts :: ReportOpts -> Interval -- | Get a maybe boolean representing the last cleared/uncleared option if -- any. clearedValueFromOpts :: ReportOpts -> Maybe Bool -- | Report which date we will report on based on --date2. whichDateFromOpts :: ReportOpts -> WhichDate -- | Convert this journal's postings' amounts to the cost basis amounts if -- specified by options. journalSelectingAmountFromOpts :: ReportOpts -> Journal -> Journal -- | Convert report options and arguments to a query. queryFromOpts :: Day -> ReportOpts -> Query -- | Convert report options and arguments to query options. queryOptsFromOpts :: Day -> ReportOpts -> [QueryOpt] -- | A journal entries report is a list of whole transactions as originally -- entered in the journal (mostly). Used by eg hledger's print command -- and hledger-web's journal entries view. type EntriesReport = [EntriesReportItem] type EntriesReportItem = Transaction -- | Select transactions for an entries report. entriesReport :: ReportOpts -> Query -> Journal -> EntriesReport -- | A postings report is a list of postings with a running total, a label -- for the total field, and a little extra transaction info to help with -- rendering. type PostingsReport = (String, [PostingsReportItem]) type PostingsReportItem = (Maybe Day, Maybe String, Posting, MixedAmount) -- | Select postings from the journal and add running balance and other -- information to make a postings report. Used by eg hledger's register -- command. postingsReport :: ReportOpts -> Query -> Journal -> PostingsReport -- | Generate one postings report line item, containing the posting, the -- current running balance, and optionally the posting date and/or the -- transaction description. mkpostingsReportItem :: Bool -> Bool -> WhichDate -> Posting -> MixedAmount -> PostingsReportItem -- | A transactions report includes a list of transactions -- (posting-filtered and unfiltered variants), a running balance, and -- some other information helpful for rendering a register view (a flag -- indicating multiple other accounts and a display string describing -- them) with or without a notion of current account(s). type TransactionsReport = (String, [TransactionsReportItem]) type TransactionsReportItem = (Transaction, Transaction, Bool, String, MixedAmount, MixedAmount) triDate :: (Transaction, t, t1, t2, t3, t4) -> Day triSimpleBalance :: (t, t1, t2, t3, t4, MixedAmount) -> [Char] transactionsReportByCommodity :: TransactionsReport -> [TransactionsReport] -- | Select transactions from the whole journal for a transactions report, -- with no "current" account. The end result is similar to -- postingsReport except it uses queries and transaction-based -- report items and the items are most recent first. Used by eg -- hledger-web's journal view. journalTransactionsReport :: ReportOpts -> Journal -> Query -> TransactionsReport -- | Select transactions within one or more "current" accounts, and make a -- transactions report relative to those account(s). This means: -- --
    --
  1. it shows transactions from the point of view of the current -- account(s). The transaction amount is the amount posted to the current -- account(s). The other accounts' names are provided.
  2. --
  3. With no transaction filtering in effect other than a start date, -- it shows the accurate historical running balance for the current -- account(s). Otherwise it shows a running total starting at 0.
  4. --
-- -- Currently, reporting intervals are not supported, and report items are -- most recent first. Used by eg hledger-web's account register view. accountTransactionsReport :: ReportOpts -> Journal -> Query -> Query -> TransactionsReport -- | An accounts report is a list of account names (full and short -- variants) with their balances, appropriate indentation for rendering -- as a hierarchy, and grand total. type AccountsReport = ([AccountsReportItem], MixedAmount) type AccountsReportItem = (AccountName, AccountName, Int, MixedAmount) -- | Select accounts, and get their balances at the end of the selected -- period, and misc. display information, for an accounts report. accountsReport :: ReportOpts -> Query -> Journal -> AccountsReport -- | Get the historical running inclusive balance of a particular account, -- from earliest to latest posting date. XXX Accounts should know the -- Ledger & Journal they came from accountBalanceHistory :: ReportOpts -> Journal -> Account -> [(Day, MixedAmount)] tests_Hledger_Reports :: Test instance Show ReportOpts instance Default ReportOpts module Hledger tests_Hledger :: Test