Hledger.Read.JournalReader

hledger-lib-1.41: A library providing the core functionality of hledger

Safe Haskell | None
Language | Haskell2010

Hledger.Read.JournalReader

Contents

- Reader-finding utils
- Reader
- Parsing utils
- Parsers used elsewhere
- Tests

Description

A reader for hledger's journal file format (http://hledger.org/hledger.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

Journal format supports the include directive which can read files in other formats, so the other file format readers need to be importable and invocable here.

Some important parts of journal parsing are therefore kept in Hledger.Read.Common, to avoid import cycles.

Synopsis

- findReader :: forall (m :: Type -> Type). MonadIO m => Maybe StorageFormat -> Maybe FilePath -> Maybe (Reader m)
- splitReaderPrefix :: PrefixedFilePath -> (Maybe StorageFormat, FilePath)
- reader :: forall (m :: Type -> Type). MonadIO m => Reader m
- parseAndFinaliseJournal :: ErroringJournalParser IO ParsedJournal -> InputOpts -> FilePath -> Text -> ExceptT String IO Journal
- runJournalParser :: Monad m => JournalParser m a -> Text -> m (Either HledgerParseErrors a)
- rjp :: Monad m => JournalParser m a -> Text -> m (Either HledgerParseErrors a)
- runErroringJournalParser :: Monad m => ErroringJournalParser m a -> Text -> m (Either FinalParseError (Either HledgerParseErrors a))
- rejp :: Monad m => ErroringJournalParser m a -> Text -> m (Either FinalParseError (Either HledgerParseErrors a))
- getParentAccount :: forall (m :: Type -> Type). JournalParser m AccountName
- journalp :: forall (m :: Type -> Type). MonadIO m => ErroringJournalParser m ParsedJournal
- directivep :: forall (m :: Type -> Type). MonadIO m => ErroringJournalParser m ()
- defaultyeardirectivep :: forall (m :: Type -> Type). JournalParser m ()
- marketpricedirectivep :: forall (m :: Type -> Type). JournalParser m PriceDirective
- datetimep :: forall (m :: Type -> Type). JournalParser m LocalTime
- datep :: forall (m :: Type -> Type). JournalParser m Day
- modifiedaccountnamep :: forall (m :: Type -> Type). JournalParser m AccountName
- tmpostingrulep :: forall (m :: Type -> Type). Maybe Year -> JournalParser m TMPostingRule
- statusp :: forall (m :: Type -> Type). TextParser m Status
- emptyorcommentlinep :: forall (m :: Type -> Type). TextParser m ()
- followingcommentp :: forall (m :: Type -> Type). TextParser m Text
- accountaliasp :: forall (m :: Type -> Type). TextParser m AccountAlias
- tests_JournalReader :: TestTree

# Reader-finding utils

findReader :: forall (m :: Type -> Type). MonadIO m => Maybe StorageFormat -> Maybe FilePath -> Maybe (Reader m) #

    findReader mformat mpath

Find the reader named by `mformat`, if provided. ("ssv" and "tsv" are recognised as alternate names for the csv reader, which also handles those formats.) Or, if a file path is provided, find the first reader that handles its file extension, if any.

splitReaderPrefix :: PrefixedFilePath -> (Maybe StorageFormat, FilePath) #

If a filepath is prefixed by one of the reader names and a colon, split that off. Eg "csv:-" -> (Just "csv", "-"). These reader prefixes can be used to force a specific reader, overriding the file extension.

# Reader

reader :: forall (m :: Type -> Type). MonadIO m => Reader m #

# Parsing utils

parseAndFinaliseJournal :: ErroringJournalParser IO ParsedJournal -> InputOpts -> FilePath -> Text -> ExceptT String IO Journal #

Given a parser to ParsedJournal, input options, file path and content: run the parser on the content, and finalise the result to get a Journal; or throw an error.

runJournalParser :: Monad m => JournalParser m a -> Text -> m (Either HledgerParseErrors a) #

Run a journal parser in some monad. See also: parseWithState.

rjp :: Monad m => JournalParser m a -> Text -> m (Either HledgerParseErrors a) #

Run a journal parser in some monad. See also: parseWithState.

runErroringJournalParser :: Monad m => ErroringJournalParser m a -> Text -> m (Either FinalParseError (Either HledgerParseErrors a)) #

Run an erroring journal parser in some monad. See also: parseWithState.

rejp :: Monad m => ErroringJournalParser m a -> Text -> m (Either FinalParseError (Either HledgerParseErrors a)) #

Run an erroring journal parser in some monad. See also: parseWithState.

# Parsers used elsewhere

getParentAccount :: forall (m :: Type -> Type). JournalParser m AccountName #

journalp :: forall (m :: Type -> Type). MonadIO m => ErroringJournalParser m ParsedJournal #

A journal parser. Accumulates and returns a ParsedJournal, which should be finalised/validated before use.

    >>> rejp (journalp <* eof) "2015/1/1\n a  0\n"
    Right (Right Journal (unknown) with 1 transactions, 1 accounts)

directivep :: forall (m :: Type -> Type). MonadIO m => ErroringJournalParser m () #

Parse any journal directive and update the parse state accordingly. Cf http://hledger.org/hledger.html#directives, http://ledger-cli.org/3.0/doc/ledger3.html#Command-Directives

defaultyeardirectivep :: forall (m :: Type -> Type). JournalParser m () #

marketpricedirectivep :: forall (m :: Type -> Type). JournalParser m PriceDirective #

datetimep :: forall (m :: Type -> Type). JournalParser m LocalTime #

Parse a date and time in YYYY-MM-DD HH:MM[:SS][+-ZZZZ] format. Slash (/) and period (.) are also allowed as date separators. The year may be omitted if a default year has been set. Seconds are optional. The timezone is optional and ignored (the time is always interpreted as a local time). Leading zeroes may be omitted (except in a timezone).

datep :: forall (m :: Type -> Type). JournalParser m Day #

Parse a date in YYYY-MM-DD format. Slash (/) and period (.) are also allowed as separators. The year may be omitted if a default year has been set. Leading zeroes may be omitted.

modifiedaccountnamep :: forall (m :: Type -> Type). JournalParser m AccountName #

Parse an account name (plus one following space if present), then apply any parent account prefix and/or account aliases currently in effect, in that order. (Ie first add the parent account prefix, then rewrite with aliases). This calls error if any account alias with an invalid regular expression exists.

tmpostingrulep :: forall (m :: Type -> Type). Maybe Year -> JournalParser m TMPostingRule #

statusp :: forall (m :: Type -> Type). TextParser m Status #

emptyorcommentlinep :: forall (m :: Type -> Type). TextParser m () #

A blank or comment line in journal format: a line that's empty or containing only whitespace or whose first non-whitespace character is semicolon, hash, or star. See also emptyorcommentlinep2.

followingcommentp :: forall (m :: Type -> Type). TextParser m Text #

Parse a comment following a journal item, possibly continued on multiple lines, and return the comment text.

    >>> rtp followingcommentp ""   -- no comment
    Right ""
    >>> rtp followingcommentp ";"    -- just a (empty) same-line comment. newline is added
    Right "\n"
    >>> rtp followingcommentp ";  \n"
    Right "\n"
    >>> rtp followingcommentp ";\n ;\n"  -- a same-line and a next-line comment
    Right "\n\n"
    >>> rtp followingcommentp "\n ;\n"  -- just a next-line comment. Insert an empty same-line comment so the next-line comment doesn't become a same-line comment.
    Right "\n\n"

accountaliasp :: forall (m :: Type -> Type). TextParser m AccountAlias #

# Tests

tests_JournalReader :: TestTree #