    --- * module
    --- ** doc
    -- In Emacs, use TAB on lines beginning with "-- *" to collapse/expand sections.
    {-|

    A reader for a CSV rules file.
    This reads the actual data from a file specified by a `source` rule
    or from a similarly-named file in the same directory.

    Most of the code for reading rules files and csv files is in this module.
    -}
    -- Lots of haddocks in this file are for non-exported types.
    -- Here's a command that will render them:
    -- stack haddock hledger-lib --fast --no-haddock-deps --haddock-arguments='--ignore-all-exports' --open

    --- ** language
    {-# LANGUAGE FlexibleInstances    #-}
    {-# LANGUAGE OverloadedStrings    #-}
    {-# LANGUAGE RecordWildCards      #-}
    {-# LANGUAGE ScopedTypeVariables  #-}
    {-# LANGUAGE ViewPatterns         #-}
    {-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}

    --- ** exports
    module Hledger.Read.RulesReader (
      -- * Reader
      reader,
      -- * Misc.
      readJournalFromCsv,
      -- readRulesFile,
      -- parseCsvRules,
      -- validateCsvRules,
      -- CsvRules,
      dataFileFor,
      rulesFileFor,
      -- * Tests
      tests_RulesReader,
    )
    where

    --- ** imports
    import Prelude hiding (Applicative(..))
    import Control.Applicative (Applicative(..))
    import Control.Monad              (unless, when, void)
    import Control.Monad.Except       (ExceptT(..), liftEither, throwError)
    import qualified Control.Monad.Fail as Fail
    import Control.Monad.IO.Class     (MonadIO, liftIO)
    import Control.Monad.State.Strict (StateT, get, modify', evalStateT)
    import Control.Monad.Trans.Class  (lift)
    import Data.Char                  (toLower, isDigit, isSpace, isAlphaNum, ord)
    import Data.Bifunctor             (first)
    import Data.Functor               ((<&>))
    import Data.List (elemIndex, foldl', mapAccumL, nub, sortOn)
    import Data.List.Extra (groupOn)
    import Data.Maybe (catMaybes, fromMaybe, isJust)
    import Data.MemoUgly (memo)
    import qualified Data.Set as S
    import Data.Text (Text)
    import qualified Data.Text as T
    import qualified Data.Text.Encoding as T
    import qualified Data.Text.IO as T
    import Data.Time ( Day, TimeZone, UTCTime, LocalTime, ZonedTime(ZonedTime),
      defaultTimeLocale, getCurrentTimeZone, localDay, parseTimeM, utcToLocalTime, localTimeToUTC, zonedTimeToUTC)
    import Safe (atMay, headMay, lastMay, readMay)
    import System.FilePath ((</>), takeDirectory, takeExtension, stripExtension, takeFileName)
    import qualified Data.Csv as Cassava
    import qualified Data.Csv.Parser.Megaparsec as CassavaMegaparsec
    import qualified Data.ByteString as B
    import qualified Data.ByteString.Lazy as BL
    import Data.Foldable (asum, toList)
    import Text.Megaparsec hiding (match, parse)
    import Text.Megaparsec.Char (char, newline, string, digitChar)
    import Text.Megaparsec.Custom (parseErrorAt)
    import Text.Printf (printf)

    import Hledger.Data
    import Hledger.Utils
    import Hledger.Read.Common (aliasesFromOpts, Reader(..), InputOpts(..), amountp, statusp, journalFinalise, accountnamep, commenttagsp )
    import Hledger.Read.CsvUtils
    import System.Directory (doesFileExist, getHomeDirectory)
    import Data.Either (fromRight)

    --- ** doctest setup
    -- $setup
    -- >>> :set -XOverloadedStrings

    --- ** reader
    _READER__________________________________________ :: a
    _READER__________________________________________ = a
    forall a. HasCallStack => a
    undefined  -- VSCode outline separator

    reader :: MonadIO m => Reader m
    reader :: forall (m :: * -> *). MonadIO m => Reader m
    reader = Reader
      {rFormat :: [Char]
    rFormat     = [Char]
    "rules"
      ,rExtensions :: [[Char]]
    rExtensions = [[Char]
    "rules"]
      ,rReadFn :: InputOpts -> [Char] -> CsvAmountString -> ExceptT [Char] IO Journal
    rReadFn     = InputOpts -> [Char] -> CsvAmountString -> ExceptT [Char] IO Journal
    parse
      ,rParser :: MonadIO m => ErroringJournalParser m Journal
    rParser     = [Char] -> ErroringJournalParser m Journal
    forall a. [Char] -> a
    error' [Char]
    "sorry, rules files can't be included"  -- PARTIAL:
      }

    isFileName :: [Char] -> Bool
    isFileName [Char]
    f = [Char] -> [Char]
    takeFileName [Char]
    f [Char] -> [Char] -> Bool
    forall a. Eq a => a -> a -> Bool
    == [Char]
    f

    getDownloadDir :: IO [Char]
    getDownloadDir = do
      [Char]
    home <- IO [Char]
    getHomeDirectory
      [Char] -> IO [Char]
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([Char] -> IO [Char]) -> [Char] -> IO [Char]
    forall a b. (a -> b) -> a -> b
    $ [Char]
    home [Char] -> [Char] -> [Char]
    </> [Char]
    "Downloads"  -- XXX

    -- | Parse and post-process a "Journal" from the given rules file path, or give an error.
    -- A data file is inferred from the @source@ rule, otherwise from a similarly-named file
    -- in the same directory.
    -- The source rule can specify a glob pattern and supports ~ for home directory.
    -- If it is a bare filename it will be relative to the defaut download directory
    -- on this system. If is a relative file path it will be relative to the rules
    -- file's directory. When a glob pattern matches multiple files, the alphabetically
    -- last is used. (Eg in case of multiple numbered downloads, the highest-numbered
    -- will be used.)
    -- The provided text, or a --rules-file option, are ignored by this reader.
    -- Balance assertions are not checked.
    parse :: InputOpts -> FilePath -> Text -> ExceptT String IO Journal
    parse :: InputOpts -> [Char] -> CsvAmountString -> ExceptT [Char] IO Journal
    parse InputOpts
    iopts [Char]
    f CsvAmountString
    _ = do
      CsvRules
    rules <- [Char] -> ExceptT [Char] IO CsvRules
    readRulesFile ([Char] -> ExceptT [Char] IO CsvRules)
    -> [Char] -> ExceptT [Char] IO CsvRules
    forall a b. (a -> b) -> a -> b
    $ [Char] -> [Char] -> [Char]
    forall a. Show a => [Char] -> a -> a
    dbg4 [Char]
    "reading rules file" [Char]
    f
      -- XXX higher-than usual debug level for file reading to bypass excessive noise from elsewhere, normally 6 or 7
      Maybe [Char]
    mdatafile <- IO (Maybe [Char]) -> ExceptT [Char] IO (Maybe [Char])
    forall a. IO a -> ExceptT [Char] IO a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (Maybe [Char]) -> ExceptT [Char] IO (Maybe [Char]))
    -> IO (Maybe [Char]) -> ExceptT [Char] IO (Maybe [Char])
    forall a b. (a -> b) -> a -> b
    $ do
        [Char]
    dldir <- IO [Char]
    getDownloadDir
        let rulesdir :: [Char]
    rulesdir = [Char] -> [Char]
    takeDirectory [Char]
    f
        let msource :: Maybe [Char]
    msource = CsvAmountString -> [Char]
    T.unpack (CsvAmountString -> [Char])
    -> Maybe CsvAmountString -> Maybe [Char]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CsvAmountString -> CsvRules -> Maybe CsvAmountString
    getDirective CsvAmountString
    "source" CsvRules
    rules
        [[Char]]
    fs <- case Maybe [Char]
    msource of
                Just [Char]
    src -> [Char] -> [Char] -> IO [[Char]]
    expandGlob [Char]
    dir ([Char] -> [Char] -> [Char]
    forall a. Show a => [Char] -> a -> a
    dbg4 [Char]
    "source" [Char]
    src) IO [[Char]] -> ([[Char]] -> IO [[Char]]) -> IO [[Char]]
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= [[Char]] -> IO [[Char]]
    sortByModTime IO [[Char]] -> ([[Char]] -> [[Char]]) -> IO [[Char]]
    forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
    <&> [Char] -> [[Char]] -> [[Char]]
    forall a. Show a => [Char] -> a -> a
    dbg4 ([Char]
    "matched files"[Char] -> [Char] -> [Char]
    forall a. Semigroup a => a -> a -> a
    <>[Char]
    desc[Char] -> [Char] -> [Char]
    forall a. Semigroup a => a -> a -> a
    <>[Char]
    ", newest first")
                  where ([Char]
    dir,[Char]
    desc) = if [Char] -> Bool
    isFileName [Char]
    src then ([Char]
    dldir,[Char]
    " in download directory") else ([Char]
    rulesdir,[Char]
    "")
                Maybe [Char]
    Nothing  -> [[Char]] -> IO [[Char]]
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return [[Char] -> ([Char] -> [Char]) -> Maybe [Char] -> [Char]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe [Char]
    forall {a}. a
    err ([Char] -> [Char] -> [Char]
    forall a. Show a => [Char] -> a -> a
    dbg4 [Char]
    "inferred source") (Maybe [Char] -> [Char]) -> Maybe [Char] -> [Char]
    forall a b. (a -> b) -> a -> b
    $ [Char] -> Maybe [Char]
    dataFileFor [Char]
    f]  -- shouldn't fail, f has .rules extension
                  where err :: a
    err = [Char] -> a
    forall a. [Char] -> a
    error' ([Char] -> a) -> [Char] -> a
    forall a b. (a -> b) -> a -> b
    $ [Char]
    "could not infer a data file for " [Char] -> [Char] -> [Char]
    forall a. Semigroup a => a -> a -> a
    <> [Char]
    f
        Maybe [Char] -> IO (Maybe [Char])
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe [Char] -> IO (Maybe [Char]))
    -> Maybe [Char] -> IO (Maybe [Char])
    forall a b. (a -> b) -> a -> b
    $ [Char] -> Maybe [Char] -> Maybe [Char]
    forall a. Show a => [Char] -> a -> a
    dbg4 [Char]
    "data file" (Maybe [Char] -> Maybe [Char]) -> Maybe [Char] -> Maybe [Char]
    forall a b. (a -> b) -> a -> b
    $ [[Char]] -> Maybe [Char]
    forall a. [a] -> Maybe a
    headMay [[Char]]
    fs
      case Maybe [Char]
    mdatafile of
        Maybe [Char]
    Nothing -> Journal -> ExceptT [Char] IO Journal
    forall a. a -> ExceptT [Char] IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Journal
    nulljournal  -- data file specified by source rule was not found
        Just [Char]
    dat -> do
          Bool
    exists <- IO Bool -> ExceptT [Char] IO Bool
    forall a. IO a -> ExceptT [Char] IO a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Bool -> ExceptT [Char] IO Bool)
    -> IO Bool -> ExceptT [Char] IO Bool
    forall a b. (a -> b) -> a -> b
    $ [Char] -> IO Bool
    doesFileExist [Char]
    dat
          if Bool -> Bool
    not ([Char]
    dat[Char] -> [Char] -> Bool
    forall a. Eq a => a -> a -> Bool
    ==[Char]
    "-" Bool -> Bool -> Bool
    || Bool
    exists)
          then Journal -> ExceptT [Char] IO Journal
    forall a. a -> ExceptT [Char] IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Journal
    nulljournal      -- data file inferred from rules file name was not found
          else do
            CsvAmountString
    t <- IO CsvAmountString -> ExceptT [Char] IO CsvAmountString
    forall a. IO a -> ExceptT [Char] IO a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CsvAmountString -> ExceptT [Char] IO CsvAmountString)
    -> IO CsvAmountString -> ExceptT [Char] IO CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ [Char] -> IO CsvAmountString
    readFileOrStdinPortably [Char]
    dat
            Maybe (Either CsvRules [Char])
    -> [Char] -> CsvAmountString -> ExceptT [Char] IO Journal
    readJournalFromCsv (Either CsvRules [Char] -> Maybe (Either CsvRules [Char])
    forall a. a -> Maybe a
    Just (Either CsvRules [Char] -> Maybe (Either CsvRules [Char]))
    -> Either CsvRules [Char] -> Maybe (Either CsvRules [Char])
    forall a b. (a -> b) -> a -> b
    $ CsvRules -> Either CsvRules [Char]
    forall a b. a -> Either a b
    Left CsvRules
    rules) [Char]
    dat CsvAmountString
    t
            -- apply any command line account aliases. Can fail with a bad replacement pattern.
            ExceptT [Char] IO Journal
    -> (Journal -> ExceptT [Char] IO Journal)
    -> ExceptT [Char] IO Journal
    forall a b.
    ExceptT [Char] IO a
    -> (a -> ExceptT [Char] IO b) -> ExceptT [Char] IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Either [Char] Journal -> ExceptT [Char] IO Journal
    forall e (m :: * -> *) a. MonadError e m => Either e a -> m a
    liftEither (Either [Char] Journal -> ExceptT [Char] IO Journal)
    -> (Journal -> Either [Char] Journal)
    -> Journal
    -> ExceptT [Char] IO Journal
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [AccountAlias] -> Journal -> Either [Char] Journal
    journalApplyAliases (InputOpts -> [AccountAlias]
    aliasesFromOpts InputOpts
    iopts)
                -- journalFinalise assumes the journal's items are
                -- reversed, as produced by JournalReader's parser.
                -- But here they are already properly ordered. So we'd
                -- better preemptively reverse them once more. XXX inefficient
                (Journal -> Either [Char] Journal)
    -> (Journal -> Journal) -> Journal -> Either [Char] Journal
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Journal -> Journal
    journalReverse
            ExceptT [Char] IO Journal
    -> (Journal -> ExceptT [Char] IO Journal)
    -> ExceptT [Char] IO Journal
    forall a b.
    ExceptT [Char] IO a
    -> (a -> ExceptT [Char] IO b) -> ExceptT [Char] IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= InputOpts
    -> [Char]
    -> CsvAmountString
    -> Journal
    -> ExceptT [Char] IO Journal
    journalFinalise InputOpts
    iopts{balancingopts_=(balancingopts_ iopts){ignore_assertions_=True}} [Char]
    f CsvAmountString
    ""

    --- ** reading rules files
    --- *** rules utilities
    _RULES_READING__________________________________________ :: a
    _RULES_READING__________________________________________ = a
    forall a. HasCallStack => a
    undefined

    -- | Given a rules file path, what would be the corresponding data file ?
    -- (Remove a .rules extension.)
    dataFileFor :: FilePath -> Maybe FilePath
    dataFileFor :: [Char] -> Maybe [Char]
    dataFileFor = [Char] -> [Char] -> Maybe [Char]
    stripExtension [Char]
    "rules"

    -- | Given a csv file path, what would be the corresponding rules file ?
    -- (Add a .rules extension.)
    rulesFileFor :: FilePath -> FilePath
    rulesFileFor :: [Char] -> [Char]
    rulesFileFor = ([Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [Char]
    ".rules")

    -- | An exception-throwing IO action that reads and validates
    -- the specified CSV rules file (which may include other rules files).
    readRulesFile :: FilePath -> ExceptT String IO CsvRules
    readRulesFile :: [Char] -> ExceptT [Char] IO CsvRules
    readRulesFile [Char]
    f =
      IO CsvAmountString -> ExceptT [Char] IO CsvAmountString
    forall a. IO a -> ExceptT [Char] IO a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (do
        [Char] -> [Char] -> IO ()
    forall (m :: * -> *) a. (MonadIO m, Show a) => [Char] -> a -> m ()
    dbg6IO [Char]
    "using conversion rules file" [Char]
    f
        [Char] -> IO CsvAmountString
    readFilePortably [Char]
    f IO CsvAmountString
    -> (CsvAmountString -> IO CsvAmountString) -> IO CsvAmountString
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= [Char] -> CsvAmountString -> IO CsvAmountString
    expandIncludes ([Char] -> [Char]
    takeDirectory [Char]
    f)
      ) ExceptT [Char] IO CsvAmountString
    -> (CsvAmountString -> ExceptT [Char] IO CsvRules)
    -> ExceptT [Char] IO CsvRules
    forall a b.
    ExceptT [Char] IO a
    -> (a -> ExceptT [Char] IO b) -> ExceptT [Char] IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= ([Char] -> ExceptT [Char] IO CsvRules)
    -> (CsvRules -> ExceptT [Char] IO CsvRules)
    -> Either [Char] CsvRules
    -> ExceptT [Char] IO CsvRules
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either [Char] -> ExceptT [Char] IO CsvRules
    forall a. [Char] -> ExceptT [Char] IO a
    forall e (m :: * -> *) a. MonadError e m => e -> m a
    throwError CsvRules -> ExceptT [Char] IO CsvRules
    forall a. a -> ExceptT [Char] IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Either [Char] CsvRules -> ExceptT [Char] IO CsvRules)
    -> (CsvAmountString -> Either [Char] CsvRules)
    -> CsvAmountString
    -> ExceptT [Char] IO CsvRules
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Char] -> CsvAmountString -> Either [Char] CsvRules
    parseAndValidateCsvRules [Char]
    f

    -- | Inline all files referenced by include directives in this hledger CSV rules text, recursively.
    -- Included file paths may be relative to the directory of the provided file path.
    -- This is done as a pre-parse step to simplify the CSV rules parser.
    expandIncludes :: FilePath -> Text -> IO Text
    expandIncludes :: [Char] -> CsvAmountString -> IO CsvAmountString
    expandIncludes [Char]
    dir0 CsvAmountString
    content = (CsvAmountString -> IO CsvAmountString)
    -> [CsvAmountString] -> IO [CsvAmountString]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM ([Char] -> CsvAmountString -> IO CsvAmountString
    expandLine [Char]
    dir0) (CsvAmountString -> [CsvAmountString]
    T.lines CsvAmountString
    content) IO [CsvAmountString]
    -> ([CsvAmountString] -> CsvAmountString) -> IO CsvAmountString
    forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
    <&> [CsvAmountString] -> CsvAmountString
    T.unlines
      where
        expandLine :: [Char] -> CsvAmountString -> IO CsvAmountString
    expandLine [Char]
    dir1 CsvAmountString
    line =
          case CsvAmountString
    line of
            (CsvAmountString -> CsvAmountString -> Maybe CsvAmountString
    T.stripPrefix CsvAmountString
    "include " -> Just CsvAmountString
    f) -> [Char] -> CsvAmountString -> IO CsvAmountString
    expandIncludes [Char]
    dir2 (CsvAmountString -> IO CsvAmountString)
    -> IO CsvAmountString -> IO CsvAmountString
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< [Char] -> IO CsvAmountString
    T.readFile [Char]
    f'
              where
                f' :: [Char]
    f' = [Char]
    dir1 [Char] -> [Char] -> [Char]
    </> CsvAmountString -> [Char]
    T.unpack ((Char -> Bool) -> CsvAmountString -> CsvAmountString
    T.dropWhile Char -> Bool
    isSpace CsvAmountString
    f)
                dir2 :: [Char]
    dir2 = [Char] -> [Char]
    takeDirectory [Char]
    f'
            CsvAmountString
    _ -> CsvAmountString -> IO CsvAmountString
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return CsvAmountString
    line

    -- defaultRulesText :: FilePath -> Text
    -- defaultRulesText _csvfile = T.pack $ unlines
    --   ["# hledger csv conversion rules" --  for " ++ csvFileFor (takeFileName csvfile)
    --   ,"# cf http://hledger.org/hledger.html#csv"
    --   ,""
    --   ,"account1 assets:bank:checking"
    --   ,""
    --   ,"fields date, description, amount1"
    --   ,""
    --   ,"#skip 1"
    --   ,"#newest-first"
    --   ,""
    --   ,"#date-format %-d/%-m/%Y"
    --   ,"#date-format %-m/%-d/%Y"
    --   ,"#date-format %Y-%h-%d"
    --   ,""
    --   ,"#currency $"
    --   ,""
    --   ,"if ITUNES"
    --   ," account2 expenses:entertainment"
    --   ,""
    --   ,"if (TO|FROM) SAVINGS"
    --   ," account2 assets:bank:savings\n"
    --   ]

    -- | An error-throwing IO action that parses this text as CSV conversion rules
    -- and runs some extra validation checks. The file path is used in error messages.
    parseAndValidateCsvRules :: FilePath -> T.Text -> Either String CsvRules
    parseAndValidateCsvRules :: [Char] -> CsvAmountString -> Either [Char] CsvRules
    parseAndValidateCsvRules [Char]
    rulesfile CsvAmountString
    s =
      case [Char]
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    parseCsvRules [Char]
    rulesfile CsvAmountString
    s of
        Left ParseErrorBundle CsvAmountString HledgerParseErrorData
    err    -> [Char] -> Either [Char] CsvRules
    forall a b. a -> Either a b
    Left ([Char] -> Either [Char] CsvRules)
    -> [Char] -> Either [Char] CsvRules
    forall a b. (a -> b) -> a -> b
    $ ParseErrorBundle CsvAmountString HledgerParseErrorData -> [Char]
    customErrorBundlePretty ParseErrorBundle CsvAmountString HledgerParseErrorData
    err
        Right CsvRules
    rules -> ([Char] -> [Char])
    -> Either [Char] CsvRules -> Either [Char] CsvRules
    forall a b c. (a -> b) -> Either a c -> Either b c
    forall (p :: * -> * -> *) a b c.
    Bifunctor p =>
    (a -> b) -> p a c -> p b c
    first [Char] -> [Char]
    makeFancyParseError (Either [Char] CsvRules -> Either [Char] CsvRules)
    -> Either [Char] CsvRules -> Either [Char] CsvRules
    forall a b. (a -> b) -> a -> b
    $ CsvRules -> Either [Char] CsvRules
    validateCsvRules CsvRules
    rules
      where
        makeFancyParseError :: String -> String
        makeFancyParseError :: [Char] -> [Char]
    makeFancyParseError [Char]
    errorString =
          ParseError CsvAmountString [Char] -> [Char]
    forall s e.
    (VisualStream s, ShowErrorComponent e) =>
    ParseError s e -> [Char]
    parseErrorPretty (CsvFieldIndex
    -> Set (ErrorFancy [Char]) -> ParseError CsvAmountString [Char]
    forall s e. CsvFieldIndex -> Set (ErrorFancy e) -> ParseError s e
    FancyError CsvFieldIndex
    0 (ErrorFancy [Char] -> Set (ErrorFancy [Char])
    forall a. a -> Set a
    S.singleton (ErrorFancy [Char] -> Set (ErrorFancy [Char]))
    -> ErrorFancy [Char] -> Set (ErrorFancy [Char])
    forall a b. (a -> b) -> a -> b
    $ [Char] -> ErrorFancy [Char]
    forall e. [Char] -> ErrorFancy e
    ErrorFail [Char]
    errorString) :: ParseError Text String)

    instance ShowErrorComponent String where
      showErrorComponent :: [Char] -> [Char]
    showErrorComponent = [Char] -> [Char]
    forall a. a -> a
    id

    -- | Parse this text as CSV conversion rules. The file path is for error messages.
    parseCsvRules :: FilePath -> T.Text -> Either (ParseErrorBundle T.Text HledgerParseErrorData) CsvRules
    -- parseCsvRules rulesfile s = runParser csvrulesfile nullrules{baseAccount=takeBaseName rulesfile} rulesfile s
    parseCsvRules :: [Char]
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    parseCsvRules = Parsec HledgerParseErrorData CsvAmountString CsvRules
    -> [Char]
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    forall e s a.
    Parsec e s a -> [Char] -> s -> Either (ParseErrorBundle s e) a
    runParser (StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvRules
    -> CsvRulesParsed
    -> Parsec HledgerParseErrorData CsvAmountString CsvRules
    forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
    evalStateT StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvRules
    rulesp CsvRulesParsed
    defrules)

    -- | Return the validated rules, or an error.
    validateCsvRules :: CsvRules -> Either String CsvRules
    validateCsvRules :: CsvRules -> Either [Char] CsvRules
    validateCsvRules CsvRules
    rules = do
      Bool -> Either [Char] () -> Either [Char] ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    unless (CsvAmountString -> Bool
    isAssigned CsvAmountString
    "date")   (Either [Char] () -> Either [Char] ())
    -> Either [Char] () -> Either [Char] ()
    forall a b. (a -> b) -> a -> b
    $ [Char] -> Either [Char] ()
    forall a b. a -> Either a b
    Left [Char]
    "Please specify (at top level) the date field. Eg: date %1"
      CsvRules -> Either [Char] CsvRules
    forall a b. b -> Either a b
    Right CsvRules
    rules
      where
        isAssigned :: CsvAmountString -> Bool
    isAssigned CsvAmountString
    f = Maybe CsvAmountString -> Bool
    forall a. Maybe a -> Bool
    isJust (Maybe CsvAmountString -> Bool) -> Maybe CsvAmountString -> Bool
    forall a b. (a -> b) -> a -> b
    $ CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    getEffectiveAssignment CsvRules
    rules [] CsvAmountString
    f

    --- *** rules types
    _RULES_TYPES__________________________________________ :: a
    _RULES_TYPES__________________________________________ = a
    forall a. HasCallStack => a
    undefined

    -- | A set of data definitions and account-matching patterns sufficient to
    -- convert a particular CSV data file into meaningful journal transactions.
    data CsvRules' a = CsvRules' {
      forall a. CsvRules' a -> [(CsvAmountString, CsvAmountString)]
    rdirectives        :: [(DirectiveName,Text)],
        -- ^ top-level rules, as (keyword, value) pairs
      forall a. CsvRules' a -> [(CsvAmountString, CsvFieldIndex)]
    rcsvfieldindexes   :: [(CsvFieldName, CsvFieldIndex)],
        -- ^ csv field names and their column number, if declared by a fields list
      forall a. CsvRules' a -> [(CsvAmountString, CsvAmountString)]
    rassignments       :: [(HledgerFieldName, FieldTemplate)],
        -- ^ top-level assignments to hledger fields, as (field name, value template) pairs
      forall a. CsvRules' a -> [ConditionalBlock]
    rconditionalblocks :: [ConditionalBlock],
        -- ^ conditional blocks, which containing additional assignments/rules to apply to matched csv records
      forall a. CsvRules' a -> a
    rblocksassigning :: a -- (String -> [ConditionalBlock])
        -- ^ all conditional blocks which can potentially assign field with a given name (memoized)
    }

    -- | Type used by parsers. Directives, assignments and conditional blocks
    -- are in the reverse order compared to what is in the file and rblocksassigning is non-functional,
    -- could not be used for processing CSV records yet
    type CsvRulesParsed = CsvRules' ()

    -- | Type used after parsing is done. Directives, assignments and conditional blocks
    -- are in the same order as they were in the input file and rblocksassigning is functional.
    -- Ready to be used for CSV record processing
    type CsvRules = CsvRules' (Text -> [ConditionalBlock])  -- XXX simplify

    instance Eq CsvRules where
      CsvRules
    r1 == :: CsvRules -> CsvRules -> Bool
    == CsvRules
    r2 = (CsvRules -> [(CsvAmountString, CsvAmountString)]
    forall a. CsvRules' a -> [(CsvAmountString, CsvAmountString)]
    rdirectives CsvRules
    r1, CsvRules -> [(CsvAmountString, CsvFieldIndex)]
    forall a. CsvRules' a -> [(CsvAmountString, CsvFieldIndex)]
    rcsvfieldindexes CsvRules
    r1, CsvRules -> [(CsvAmountString, CsvAmountString)]
    forall a. CsvRules' a -> [(CsvAmountString, CsvAmountString)]
    rassignments CsvRules
    r1) ([(CsvAmountString, CsvAmountString)],
     [(CsvAmountString, CsvFieldIndex)],
     [(CsvAmountString, CsvAmountString)])
    -> ([(CsvAmountString, CsvAmountString)],
        [(CsvAmountString, CsvFieldIndex)],
        [(CsvAmountString, CsvAmountString)])
    -> Bool
    forall a. Eq a => a -> a -> Bool
    ==
                 (CsvRules -> [(CsvAmountString, CsvAmountString)]
    forall a. CsvRules' a -> [(CsvAmountString, CsvAmountString)]
    rdirectives CsvRules
    r2, CsvRules -> [(CsvAmountString, CsvFieldIndex)]
    forall a. CsvRules' a -> [(CsvAmountString, CsvFieldIndex)]
    rcsvfieldindexes CsvRules
    r2, CsvRules -> [(CsvAmountString, CsvAmountString)]
    forall a. CsvRules' a -> [(CsvAmountString, CsvAmountString)]
    rassignments CsvRules
    r2)

    -- Custom Show instance used for debug output: omit the rblocksassigning field, which isn't showable.
    instance Show CsvRules where
      show :: CsvRules -> [Char]
    show CsvRules
    r = [Char]
    "CsvRules { rdirectives = " [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [(CsvAmountString, CsvAmountString)] -> [Char]
    forall a. Show a => a -> [Char]
    show (CsvRules -> [(CsvAmountString, CsvAmountString)]
    forall a. CsvRules' a -> [(CsvAmountString, CsvAmountString)]
    rdirectives CsvRules
    r) [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++
               [Char]
    ", rcsvfieldindexes = "     [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [(CsvAmountString, CsvFieldIndex)] -> [Char]
    forall a. Show a => a -> [Char]
    show (CsvRules -> [(CsvAmountString, CsvFieldIndex)]
    forall a. CsvRules' a -> [(CsvAmountString, CsvFieldIndex)]
    rcsvfieldindexes CsvRules
    r) [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++
               [Char]
    ", rassignments = "         [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [(CsvAmountString, CsvAmountString)] -> [Char]
    forall a. Show a => a -> [Char]
    show (CsvRules -> [(CsvAmountString, CsvAmountString)]
    forall a. CsvRules' a -> [(CsvAmountString, CsvAmountString)]
    rassignments CsvRules
    r) [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++
               [Char]
    ", rconditionalblocks = "   [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [ConditionalBlock] -> [Char]
    forall a. Show a => a -> [Char]
    show (CsvRules -> [ConditionalBlock]
    forall a. CsvRules' a -> [ConditionalBlock]
    rconditionalblocks CsvRules
    r) [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++
               [Char]
    " }"

    type CsvRulesParser a = StateT CsvRulesParsed SimpleTextParser a

    -- | The keyword of a CSV rule - "fields", "skip", "if", etc.
    type DirectiveName    = Text

    -- | CSV field name.
    type CsvFieldName     = Text

    -- | 1-based CSV column number.
    type CsvFieldIndex    = Int

    -- | Percent symbol followed by a CSV field name or column number. Eg: %date, %1.
    type CsvFieldReference = Text

    -- | One of the standard hledger fields or pseudo-fields that can be assigned to.
    -- Eg date, account1, amount, amount1-in, date-format.
    type HledgerFieldName = Text

    -- | A text value to be assigned to a hledger field, possibly
    -- containing csv field references to be interpolated.
    type FieldTemplate    = Text

    -- | A reference to a regular expression match group. Eg \1.
    type MatchGroupReference = Text

    -- | A strptime date parsing pattern, as supported by Data.Time.Format.
    type DateFormat       = Text

    -- | A prefix for a matcher test, either & or none (implicit or).
    data MatcherPrefix = And | Not | None
      deriving (CsvFieldIndex -> MatcherPrefix -> [Char] -> [Char]
    [MatcherPrefix] -> [Char] -> [Char]
    MatcherPrefix -> [Char]
    (CsvFieldIndex -> MatcherPrefix -> [Char] -> [Char])
    -> (MatcherPrefix -> [Char])
    -> ([MatcherPrefix] -> [Char] -> [Char])
    -> Show MatcherPrefix
    forall a.
    (CsvFieldIndex -> a -> [Char] -> [Char])
    -> (a -> [Char]) -> ([a] -> [Char] -> [Char]) -> Show a
    $cshowsPrec :: CsvFieldIndex -> MatcherPrefix -> [Char] -> [Char]
    showsPrec :: CsvFieldIndex -> MatcherPrefix -> [Char] -> [Char]
    $cshow :: MatcherPrefix -> [Char]
    show :: MatcherPrefix -> [Char]
    $cshowList :: [MatcherPrefix] -> [Char] -> [Char]
    showList :: [MatcherPrefix] -> [Char] -> [Char]
    Show, MatcherPrefix -> MatcherPrefix -> Bool
    (MatcherPrefix -> MatcherPrefix -> Bool)
    -> (MatcherPrefix -> MatcherPrefix -> Bool) -> Eq MatcherPrefix
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: MatcherPrefix -> MatcherPrefix -> Bool
    == :: MatcherPrefix -> MatcherPrefix -> Bool
    $c/= :: MatcherPrefix -> MatcherPrefix -> Bool
    /= :: MatcherPrefix -> MatcherPrefix -> Bool
    Eq)

    -- | A single test for matching a CSV record, in one way or another.
    data Matcher =
        RecordMatcher MatcherPrefix Regexp                          -- ^ match if this regexp matches the overall CSV record
      | FieldMatcher MatcherPrefix CsvFieldReference Regexp         -- ^ match if this regexp matches the referenced CSV field's value
      deriving (CsvFieldIndex -> Matcher -> [Char] -> [Char]
    [Matcher] -> [Char] -> [Char]
    Matcher -> [Char]
    (CsvFieldIndex -> Matcher -> [Char] -> [Char])
    -> (Matcher -> [Char])
    -> ([Matcher] -> [Char] -> [Char])
    -> Show Matcher
    forall a.
    (CsvFieldIndex -> a -> [Char] -> [Char])
    -> (a -> [Char]) -> ([a] -> [Char] -> [Char]) -> Show a
    $cshowsPrec :: CsvFieldIndex -> Matcher -> [Char] -> [Char]
    showsPrec :: CsvFieldIndex -> Matcher -> [Char] -> [Char]
    $cshow :: Matcher -> [Char]
    show :: Matcher -> [Char]
    $cshowList :: [Matcher] -> [Char] -> [Char]
    showList :: [Matcher] -> [Char] -> [Char]
    Show, Matcher -> Matcher -> Bool
    (Matcher -> Matcher -> Bool)
    -> (Matcher -> Matcher -> Bool) -> Eq Matcher
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Matcher -> Matcher -> Bool
    == :: Matcher -> Matcher -> Bool
    $c/= :: Matcher -> Matcher -> Bool
    /= :: Matcher -> Matcher -> Bool
    Eq)

    -- | A conditional block: a set of CSV record matchers, and a sequence
    -- of rules which will be enabled only if one or more of the matchers
    -- succeeds.
    --
    -- Three types of rule are allowed inside conditional blocks: field
    -- assignments, skip, end. (A skip or end rule is stored as if it was
    -- a field assignment, and executed in validateCsv. XXX)
    data ConditionalBlock = CB {
       ConditionalBlock -> [Matcher]
    cbMatchers    :: [Matcher]
      ,ConditionalBlock -> [(CsvAmountString, CsvAmountString)]
    cbAssignments :: [(HledgerFieldName, FieldTemplate)]
      } deriving (CsvFieldIndex -> ConditionalBlock -> [Char] -> [Char]
    [ConditionalBlock] -> [Char] -> [Char]
    ConditionalBlock -> [Char]
    (CsvFieldIndex -> ConditionalBlock -> [Char] -> [Char])
    -> (ConditionalBlock -> [Char])
    -> ([ConditionalBlock] -> [Char] -> [Char])
    -> Show ConditionalBlock
    forall a.
    (CsvFieldIndex -> a -> [Char] -> [Char])
    -> (a -> [Char]) -> ([a] -> [Char] -> [Char]) -> Show a
    $cshowsPrec :: CsvFieldIndex -> ConditionalBlock -> [Char] -> [Char]
    showsPrec :: CsvFieldIndex -> ConditionalBlock -> [Char] -> [Char]
    $cshow :: ConditionalBlock -> [Char]
    show :: ConditionalBlock -> [Char]
    $cshowList :: [ConditionalBlock] -> [Char] -> [Char]
    showList :: [ConditionalBlock] -> [Char] -> [Char]
    Show, ConditionalBlock -> ConditionalBlock -> Bool
    (ConditionalBlock -> ConditionalBlock -> Bool)
    -> (ConditionalBlock -> ConditionalBlock -> Bool)
    -> Eq ConditionalBlock
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ConditionalBlock -> ConditionalBlock -> Bool
    == :: ConditionalBlock -> ConditionalBlock -> Bool
    $c/= :: ConditionalBlock -> ConditionalBlock -> Bool
    /= :: ConditionalBlock -> ConditionalBlock -> Bool
    Eq)

    defrules :: CsvRulesParsed
    defrules :: CsvRulesParsed
    defrules = CsvRules' {
      rdirectives :: [(CsvAmountString, CsvAmountString)]
    rdirectives=[],
      rcsvfieldindexes :: [(CsvAmountString, CsvFieldIndex)]
    rcsvfieldindexes=[],
      rassignments :: [(CsvAmountString, CsvAmountString)]
    rassignments=[],
      rconditionalblocks :: [ConditionalBlock]
    rconditionalblocks=[],
      rblocksassigning :: ()
    rblocksassigning = ()
      }

    -- | Create CsvRules from the content parsed out of the rules file
    mkrules :: CsvRulesParsed -> CsvRules
    mkrules :: CsvRulesParsed -> CsvRules
    mkrules CsvRulesParsed
    rules =
      let conditionalblocks :: [ConditionalBlock]
    conditionalblocks = [ConditionalBlock] -> [ConditionalBlock]
    forall a. [a] -> [a]
    reverse ([ConditionalBlock] -> [ConditionalBlock])
    -> [ConditionalBlock] -> [ConditionalBlock]
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed -> [ConditionalBlock]
    forall a. CsvRules' a -> [ConditionalBlock]
    rconditionalblocks CsvRulesParsed
    rules
          maybeMemo :: (CsvAmountString -> b) -> CsvAmountString -> b
    maybeMemo = if [ConditionalBlock] -> CsvFieldIndex
    forall a. [a] -> CsvFieldIndex
    forall (t :: * -> *) a. Foldable t => t a -> CsvFieldIndex
    length [ConditionalBlock]
    conditionalblocks CsvFieldIndex -> CsvFieldIndex -> Bool
    forall a. Ord a => a -> a -> Bool
    >= CsvFieldIndex
    15 then (CsvAmountString -> b) -> CsvAmountString -> b
    forall a b. Ord a => (a -> b) -> a -> b
    memo else (CsvAmountString -> b) -> CsvAmountString -> b
    forall a. a -> a
    id
      in
        CsvRules' {
        rdirectives :: [(CsvAmountString, CsvAmountString)]
    rdirectives=[(CsvAmountString, CsvAmountString)]
    -> [(CsvAmountString, CsvAmountString)]
    forall a. [a] -> [a]
    reverse ([(CsvAmountString, CsvAmountString)]
     -> [(CsvAmountString, CsvAmountString)])
    -> [(CsvAmountString, CsvAmountString)]
    -> [(CsvAmountString, CsvAmountString)]
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed -> [(CsvAmountString, CsvAmountString)]
    forall a. CsvRules' a -> [(CsvAmountString, CsvAmountString)]
    rdirectives CsvRulesParsed
    rules,
        rcsvfieldindexes :: [(CsvAmountString, CsvFieldIndex)]
    rcsvfieldindexes=CsvRulesParsed -> [(CsvAmountString, CsvFieldIndex)]
    forall a. CsvRules' a -> [(CsvAmountString, CsvFieldIndex)]
    rcsvfieldindexes CsvRulesParsed
    rules,
        rassignments :: [(CsvAmountString, CsvAmountString)]
    rassignments=[(CsvAmountString, CsvAmountString)]
    -> [(CsvAmountString, CsvAmountString)]
    forall a. [a] -> [a]
    reverse ([(CsvAmountString, CsvAmountString)]
     -> [(CsvAmountString, CsvAmountString)])
    -> [(CsvAmountString, CsvAmountString)]
    -> [(CsvAmountString, CsvAmountString)]
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed -> [(CsvAmountString, CsvAmountString)]
    forall a. CsvRules' a -> [(CsvAmountString, CsvAmountString)]
    rassignments CsvRulesParsed
    rules,
        rconditionalblocks :: [ConditionalBlock]
    rconditionalblocks=[ConditionalBlock]
    conditionalblocks,
        rblocksassigning :: CsvAmountString -> [ConditionalBlock]
    rblocksassigning = (CsvAmountString -> [ConditionalBlock])
    -> CsvAmountString -> [ConditionalBlock]
    forall {b}. (CsvAmountString -> b) -> CsvAmountString -> b
    maybeMemo (\CsvAmountString
    f -> (ConditionalBlock -> Bool)
    -> [ConditionalBlock] -> [ConditionalBlock]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (((CsvAmountString, CsvAmountString) -> Bool)
    -> [(CsvAmountString, CsvAmountString)] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any ((CsvAmountString -> CsvAmountString -> Bool
    forall a. Eq a => a -> a -> Bool
    ==CsvAmountString
    f)(CsvAmountString -> Bool)
    -> ((CsvAmountString, CsvAmountString) -> CsvAmountString)
    -> (CsvAmountString, CsvAmountString)
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .(CsvAmountString, CsvAmountString) -> CsvAmountString
    forall a b. (a, b) -> a
    fst) ([(CsvAmountString, CsvAmountString)] -> Bool)
    -> (ConditionalBlock -> [(CsvAmountString, CsvAmountString)])
    -> ConditionalBlock
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ConditionalBlock -> [(CsvAmountString, CsvAmountString)]
    cbAssignments) [ConditionalBlock]
    conditionalblocks)
        }

    --- *** rules parsers
    _RULES_PARSING__________________________________________ :: a
    _RULES_PARSING__________________________________________ = a
    forall a. HasCallStack => a
    undefined

    {-
    Grammar for the CSV conversion rules, more or less:

    RULES: RULE*

    RULE: ( SOURCE | FIELD-LIST | FIELD-ASSIGNMENT | CONDITIONAL-BLOCK | SKIP | TIMEZONE | NEWEST-FIRST | INTRA-DAY-REVERSED | DATE-FORMAT | DECIMAL-MARK | COMMENT | BLANK ) NEWLINE

    SOURCE: source SPACE FILEPATH

    FIELD-LIST: fields SPACE FIELD-NAME ( SPACE? , SPACE? FIELD-NAME )*

    FIELD-NAME: QUOTED-FIELD-NAME | BARE-FIELD-NAME

    QUOTED-FIELD-NAME: " (any CHAR except double-quote)+ "

    BARE-FIELD-NAME: any CHAR except space, tab, #, ;

    FIELD-ASSIGNMENT: JOURNAL-FIELD ASSIGNMENT-SEPARATOR FIELD-VALUE

    JOURNAL-FIELD: date | date2 | status | code | description | comment | account1 | account2 | amount | JOURNAL-PSEUDO-FIELD

    JOURNAL-PSEUDO-FIELD: amount-in | amount-out | currency

    ASSIGNMENT-SEPARATOR: SPACE | ( : SPACE? )

    FIELD-VALUE: VALUE (possibly containing CSV-FIELD-REFERENCEs and REGEX-MATCHGROUP-REFERENCEs)

    CSV-FIELD-REFERENCE: % CSV-FIELD

    REGEX-MATCHGROUP-REFERENCE: \ DIGIT+

    CSV-FIELD: ( FIELD-NAME | FIELD-NUMBER ) (corresponding to a CSV field)

    FIELD-NUMBER: DIGIT+

    CONDITIONAL-BLOCK: if ( FIELD-MATCHER NEWLINE )+ INDENTED-BLOCK

    FIELD-MATCHER: ( CSV-FIELD-NAME SPACE? )? ( MATCHOP SPACE? )? PATTERNS

    MATCHOP: ~

    PATTERNS: ( NEWLINE REGEXP )* REGEXP

    INDENTED-BLOCK: ( SPACE ( FIELD-ASSIGNMENT | COMMENT ) NEWLINE )+

    REGEXP: ( NONSPACE CHAR* ) SPACE?

    VALUE: SPACE? ( CHAR* ) SPACE?

    COMMENT: SPACE? COMMENT-CHAR VALUE

    COMMENT-CHAR: # | ; | *

    NONSPACE: any CHAR not a SPACE-CHAR

    BLANK: SPACE?

    SPACE: SPACE-CHAR+

    SPACE-CHAR: space | tab

    CHAR: any character except newline

    DIGIT: 0-9

    -}

    addDirective :: (DirectiveName, Text) -> CsvRulesParsed -> CsvRulesParsed
    addDirective :: (CsvAmountString, CsvAmountString)
    -> CsvRulesParsed -> CsvRulesParsed
    addDirective (CsvAmountString, CsvAmountString)
    d CsvRulesParsed
    r = CsvRulesParsed
    r{rdirectives=d:rdirectives r}

    addAssignment :: (HledgerFieldName, FieldTemplate) -> CsvRulesParsed -> CsvRulesParsed
    addAssignment :: (CsvAmountString, CsvAmountString)
    -> CsvRulesParsed -> CsvRulesParsed
    addAssignment (CsvAmountString, CsvAmountString)
    a CsvRulesParsed
    r = CsvRulesParsed
    r{rassignments=a:rassignments r}

    setIndexesAndAssignmentsFromList :: [CsvFieldName] -> CsvRulesParsed -> CsvRulesParsed
    setIndexesAndAssignmentsFromList :: [CsvAmountString] -> CsvRulesParsed -> CsvRulesParsed
    setIndexesAndAssignmentsFromList [CsvAmountString]
    fs = [CsvAmountString] -> CsvRulesParsed -> CsvRulesParsed
    addAssignmentsFromList [CsvAmountString]
    fs (CsvRulesParsed -> CsvRulesParsed)
    -> (CsvRulesParsed -> CsvRulesParsed)
    -> CsvRulesParsed
    -> CsvRulesParsed
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [CsvAmountString] -> CsvRulesParsed -> CsvRulesParsed
    setCsvFieldIndexesFromList [CsvAmountString]
    fs
      where
        setCsvFieldIndexesFromList :: [CsvFieldName] -> CsvRulesParsed -> CsvRulesParsed
        setCsvFieldIndexesFromList :: [CsvAmountString] -> CsvRulesParsed -> CsvRulesParsed
    setCsvFieldIndexesFromList [CsvAmountString]
    fs' CsvRulesParsed
    r = CsvRulesParsed
    r{rcsvfieldindexes=zip fs' [1..]}

        addAssignmentsFromList :: [CsvFieldName] -> CsvRulesParsed -> CsvRulesParsed
        addAssignmentsFromList :: [CsvAmountString] -> CsvRulesParsed -> CsvRulesParsed
    addAssignmentsFromList [CsvAmountString]
    fs' CsvRulesParsed
    r = (CsvRulesParsed -> CsvAmountString -> CsvRulesParsed)
    -> CsvRulesParsed -> [CsvAmountString] -> CsvRulesParsed
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' CsvRulesParsed -> CsvAmountString -> CsvRulesParsed
    maybeAddAssignment CsvRulesParsed
    r [CsvAmountString]
    journalfieldnames
          where
            maybeAddAssignment :: CsvRulesParsed -> CsvAmountString -> CsvRulesParsed
    maybeAddAssignment CsvRulesParsed
    rules CsvAmountString
    f = ((CsvRulesParsed -> CsvRulesParsed)
    -> (CsvFieldIndex -> CsvRulesParsed -> CsvRulesParsed)
    -> Maybe CsvFieldIndex
    -> CsvRulesParsed
    -> CsvRulesParsed
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe CsvRulesParsed -> CsvRulesParsed
    forall a. a -> a
    id CsvFieldIndex -> CsvRulesParsed -> CsvRulesParsed
    forall {a}.
    (Show a, Num a) =>
    a -> CsvRulesParsed -> CsvRulesParsed
    addAssignmentFromIndex (Maybe CsvFieldIndex -> CsvRulesParsed -> CsvRulesParsed)
    -> Maybe CsvFieldIndex -> CsvRulesParsed -> CsvRulesParsed
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> [CsvAmountString] -> Maybe CsvFieldIndex
    forall a. Eq a => a -> [a] -> Maybe CsvFieldIndex
    elemIndex CsvAmountString
    f [CsvAmountString]
    fs') CsvRulesParsed
    rules
              where
                addAssignmentFromIndex :: a -> CsvRulesParsed -> CsvRulesParsed
    addAssignmentFromIndex a
    i = (CsvAmountString, CsvAmountString)
    -> CsvRulesParsed -> CsvRulesParsed
    addAssignment (CsvAmountString
    f, [Char] -> CsvAmountString
    T.pack ([Char] -> CsvAmountString) -> [Char] -> CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ Char
    '%'Char -> [Char] -> [Char]
    forall a. a -> [a] -> [a]
    :a -> [Char]
    forall a. Show a => a -> [Char]
    show (a
    ia -> a -> a
    forall a. Num a => a -> a -> a
    +a
    1))

    addConditionalBlock :: ConditionalBlock -> CsvRulesParsed -> CsvRulesParsed
    addConditionalBlock :: ConditionalBlock -> CsvRulesParsed -> CsvRulesParsed
    addConditionalBlock ConditionalBlock
    b CsvRulesParsed
    r = CsvRulesParsed
    r{rconditionalblocks=b:rconditionalblocks r}

    addConditionalBlocks :: [ConditionalBlock] -> CsvRulesParsed -> CsvRulesParsed
    addConditionalBlocks :: [ConditionalBlock] -> CsvRulesParsed -> CsvRulesParsed
    addConditionalBlocks [ConditionalBlock]
    bs CsvRulesParsed
    r = CsvRulesParsed
    r{rconditionalblocks=bs++rconditionalblocks r}

    rulesp :: CsvRulesParser CsvRules
    rulesp :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvRules
    rulesp = do
      [()]
    _ <- StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [()]
    forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
    many (StateT
       CsvRulesParsed
       (ParsecT HledgerParseErrorData CsvAmountString Identity)
       ()
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          [()])
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [()]
    forall a b. (a -> b) -> a -> b
    $ [StateT
       CsvRulesParsed
       (ParsecT HledgerParseErrorData CsvAmountString Identity)
       ()]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (f :: * -> *) (m :: * -> *) a.
    (Foldable f, Alternative m) =>
    f (m a) -> m a
    choice
        [StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    blankorcommentlinep                                                StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "blank or comment line"
        ,(CsvRulesParser (CsvAmountString, CsvAmountString)
    directivep        CsvRulesParser (CsvAmountString, CsvAmountString)
    -> ((CsvAmountString, CsvAmountString)
        -> StateT
             CsvRulesParsed
             (ParsecT HledgerParseErrorData CsvAmountString Identity)
             ())
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> (a
        -> StateT
             CsvRulesParsed
             (ParsecT HledgerParseErrorData CsvAmountString Identity)
             b)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= (CsvRulesParsed -> CsvRulesParsed)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
    modify' ((CsvRulesParsed -> CsvRulesParsed)
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> ((CsvAmountString, CsvAmountString)
        -> CsvRulesParsed -> CsvRulesParsed)
    -> (CsvAmountString, CsvAmountString)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (CsvAmountString, CsvAmountString)
    -> CsvRulesParsed -> CsvRulesParsed
    addDirective)                     StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "directive"
        ,(CsvRulesParser [CsvAmountString]
    fieldnamelistp    CsvRulesParser [CsvAmountString]
    -> ([CsvAmountString]
        -> StateT
             CsvRulesParsed
             (ParsecT HledgerParseErrorData CsvAmountString Identity)
             ())
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> (a
        -> StateT
             CsvRulesParsed
             (ParsecT HledgerParseErrorData CsvAmountString Identity)
             b)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= (CsvRulesParsed -> CsvRulesParsed)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
    modify' ((CsvRulesParsed -> CsvRulesParsed)
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> ([CsvAmountString] -> CsvRulesParsed -> CsvRulesParsed)
    -> [CsvAmountString]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [CsvAmountString] -> CsvRulesParsed -> CsvRulesParsed
    setIndexesAndAssignmentsFromList) StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "field name list"
        ,(CsvRulesParser (CsvAmountString, CsvAmountString)
    fieldassignmentp  CsvRulesParser (CsvAmountString, CsvAmountString)
    -> ((CsvAmountString, CsvAmountString)
        -> StateT
             CsvRulesParsed
             (ParsecT HledgerParseErrorData CsvAmountString Identity)
             ())
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> (a
        -> StateT
             CsvRulesParsed
             (ParsecT HledgerParseErrorData CsvAmountString Identity)
             b)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= (CsvRulesParsed -> CsvRulesParsed)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
    modify' ((CsvRulesParsed -> CsvRulesParsed)
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> ((CsvAmountString, CsvAmountString)
        -> CsvRulesParsed -> CsvRulesParsed)
    -> (CsvAmountString, CsvAmountString)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (CsvAmountString, CsvAmountString)
    -> CsvRulesParsed -> CsvRulesParsed
    addAssignment)                    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "field assignment"
        -- conditionalblockp backtracks because it shares "if" prefix with conditionaltablep.
        ,StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
    try (CsvRulesParser ConditionalBlock
    conditionalblockp CsvRulesParser ConditionalBlock
    -> (ConditionalBlock
        -> StateT
             CsvRulesParsed
             (ParsecT HledgerParseErrorData CsvAmountString Identity)
             ())
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> (a
        -> StateT
             CsvRulesParsed
             (ParsecT HledgerParseErrorData CsvAmountString Identity)
             b)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= (CsvRulesParsed -> CsvRulesParsed)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
    modify' ((CsvRulesParsed -> CsvRulesParsed)
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> (ConditionalBlock -> CsvRulesParsed -> CsvRulesParsed)
    -> ConditionalBlock
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ConditionalBlock -> CsvRulesParsed -> CsvRulesParsed
    addConditionalBlock)          StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "conditional block"
        -- 'reverse' is there to ensure that conditions are added in the order they listed in the file
        ,(CsvRulesParser [ConditionalBlock]
    conditionaltablep CsvRulesParser [ConditionalBlock]
    -> ([ConditionalBlock]
        -> StateT
             CsvRulesParsed
             (ParsecT HledgerParseErrorData CsvAmountString Identity)
             ())
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> (a
        -> StateT
             CsvRulesParsed
             (ParsecT HledgerParseErrorData CsvAmountString Identity)
             b)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= (CsvRulesParsed -> CsvRulesParsed)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
    modify' ((CsvRulesParsed -> CsvRulesParsed)
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> ([ConditionalBlock] -> CsvRulesParsed -> CsvRulesParsed)
    -> [ConditionalBlock]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [ConditionalBlock] -> CsvRulesParsed -> CsvRulesParsed
    addConditionalBlocks ([ConditionalBlock] -> CsvRulesParsed -> CsvRulesParsed)
    -> ([ConditionalBlock] -> [ConditionalBlock])
    -> [ConditionalBlock]
    -> CsvRulesParsed
    -> CsvRulesParsed
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [ConditionalBlock] -> [ConditionalBlock]
    forall a. [a] -> [a]
    reverse)   StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "conditional table"
        ]
      StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    forall e s (m :: * -> *). MonadParsec e s m => m ()
    eof
      CsvRulesParsed -> CsvRules
    mkrules (CsvRulesParsed -> CsvRules)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvRulesParsed
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvRules
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvRulesParsed
    forall s (m :: * -> *). MonadState s m => m s
    get

    blankorcommentlinep :: CsvRulesParser ()
    blankorcommentlinep :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    blankorcommentlinep = SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (CsvFieldIndex -> [Char] -> SimpleTextParser ()
    forall (m :: * -> *). CsvFieldIndex -> [Char] -> TextParser m ()
    dbgparse CsvFieldIndex
    8 [Char]
    "trying blankorcommentlinep") StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> [StateT
       CsvRulesParsed
       (ParsecT HledgerParseErrorData CsvAmountString Identity)
       ()]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall s (m :: * -> *) a.
    [StateT s (ParsecT HledgerParseErrorData CsvAmountString m) a]
    -> StateT s (ParsecT HledgerParseErrorData CsvAmountString m) a
    choiceInState [StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    blanklinep, StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    commentlinep]

    blanklinep :: CsvRulesParser ()
    blanklinep :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    blanklinep = SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall s (m :: * -> *).
    (Stream s, Token s ~ Char) =>
    ParsecT HledgerParseErrorData s m ()
    skipNonNewlineSpaces StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Char
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    m (Token s)
    newline StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return () StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "blank line"

    commentlinep :: CsvRulesParser ()
    commentlinep :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    commentlinep = SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall s (m :: * -> *).
    (Stream s, Token s ~ Char) =>
    ParsecT HledgerParseErrorData s m ()
    skipNonNewlineSpaces StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Char
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    commentcharp StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Char]
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> SimpleTextParser [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Char]
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser [Char]
    forall (m :: * -> *). TextParser m [Char]
    restofline StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return () StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "comment line"

    commentcharp :: CsvRulesParser Char
    commentcharp :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    commentcharp = [Token CsvAmountString]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Token CsvAmountString)
    forall (f :: * -> *) e s (m :: * -> *).
    (Foldable f, MonadParsec e s m) =>
    f (Token s) -> m (Token s)
    oneOf ([Char]
    ";#*" :: [Char])

    directivep :: CsvRulesParser (DirectiveName, Text)
    directivep :: CsvRulesParser (CsvAmountString, CsvAmountString)
    directivep = (do
      SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (SimpleTextParser ()
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [Char] -> SimpleTextParser ()
    forall (m :: * -> *). CsvFieldIndex -> [Char] -> TextParser m ()
    dbgparse CsvFieldIndex
    8 [Char]
    "trying directive"
      CsvAmountString
    d <- [StateT
       CsvRulesParsed
       (ParsecT HledgerParseErrorData CsvAmountString Identity)
       CsvAmountString]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall s (m :: * -> *) a.
    [StateT s (ParsecT HledgerParseErrorData CsvAmountString m) a]
    -> StateT s (ParsecT HledgerParseErrorData CsvAmountString m) a
    choiceInState ([StateT
        CsvRulesParsed
        (ParsecT HledgerParseErrorData CsvAmountString Identity)
        CsvAmountString]
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          CsvAmountString)
    -> [StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          CsvAmountString]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ (CsvAmountString
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          CsvAmountString)
    -> [CsvAmountString]
    -> [StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          CsvAmountString]
    forall a b. (a -> b) -> [a] -> [b]
    map (ParsecT
      HledgerParseErrorData CsvAmountString Identity CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (ParsecT
       HledgerParseErrorData CsvAmountString Identity CsvAmountString
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          CsvAmountString)
    -> (CsvAmountString
        -> ParsecT
             HledgerParseErrorData CsvAmountString Identity CsvAmountString)
    -> CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString
    -> ParsecT
         HledgerParseErrorData CsvAmountString Identity CsvAmountString
    Tokens CsvAmountString
    -> ParsecT
         HledgerParseErrorData
         CsvAmountString
         Identity
         (Tokens CsvAmountString)
    forall e s (m :: * -> *).
    MonadParsec e s m =>
    Tokens s -> m (Tokens s)
    string) [CsvAmountString]
    directives
      CsvAmountString
    v <- (((Token CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    Token s -> m (Token s)
    char Char
    Token CsvAmountString
    ':' StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Char]
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> SimpleTextParser [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Char]
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (SimpleTextParser Char -> SimpleTextParser [Char]
    forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
    many SimpleTextParser Char
    forall s (m :: * -> *).
    (Stream s, Char ~ Token s) =>
    ParsecT HledgerParseErrorData s m Char
    spacenonewline)) StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Char]
    forall a.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> SimpleTextParser [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Char]
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (SimpleTextParser Char -> SimpleTextParser [Char]
    forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
    some SimpleTextParser Char
    forall s (m :: * -> *).
    (Stream s, Char ~ Token s) =>
    ParsecT HledgerParseErrorData s m Char
    spacenonewline)) StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    directivevalp)
           StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall a.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> (StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe Char)
    forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
    optional (Token CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    Token s -> m (Token s)
    char Char
    Token CsvAmountString
    ':') StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      (Maybe Char)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall s (m :: * -> *).
    (Stream s, Token s ~ Char) =>
    ParsecT HledgerParseErrorData s m ()
    skipNonNewlineSpaces StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall (m :: * -> *). TextParser m ()
    eolof StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return CsvAmountString
    "")
      (CsvAmountString, CsvAmountString)
    -> CsvRulesParser (CsvAmountString, CsvAmountString)
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (CsvAmountString
    d, CsvAmountString
    v)
      ) CsvRulesParser (CsvAmountString, CsvAmountString)
    -> [Char] -> CsvRulesParser (CsvAmountString, CsvAmountString)
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "directive"

    directives :: [Text]
    directives :: [CsvAmountString]
    directives =
      [CsvAmountString
    "source"
      ,CsvAmountString
    "date-format"
      ,CsvAmountString
    "decimal-mark"
      ,CsvAmountString
    "separator"
      -- ,"default-account"
      -- ,"default-currency"
      ,CsvAmountString
    "skip"
      ,CsvAmountString
    "timezone"
      ,CsvAmountString
    "newest-first"
      ,CsvAmountString
    "intra-day-reversed"
      , CsvAmountString
    "balance-type"
      ]

    directivevalp :: CsvRulesParser Text
    directivevalp :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    directivevalp = [Char] -> CsvAmountString
    T.pack ([Char] -> CsvAmountString)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      (Token CsvAmountString)
    forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
    anySingle StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Char]
    forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
    `manyTill` SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall (m :: * -> *). TextParser m ()
    eolof

    fieldnamelistp :: CsvRulesParser [CsvFieldName]
    fieldnamelistp :: CsvRulesParser [CsvAmountString]
    fieldnamelistp = (do
      SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (SimpleTextParser ()
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [Char] -> SimpleTextParser ()
    forall (m :: * -> *). CsvFieldIndex -> [Char] -> TextParser m ()
    dbgparse CsvFieldIndex
    8 [Char]
    "trying fieldnamelist"
      Tokens CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Tokens CsvAmountString)
    forall e s (m :: * -> *).
    MonadParsec e s m =>
    Tokens s -> m (Tokens s)
    string Tokens CsvAmountString
    "fields"
      StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe Char)
    forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
    optional (StateT
       CsvRulesParsed
       (ParsecT HledgerParseErrorData CsvAmountString Identity)
       Char
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          (Maybe Char))
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe Char)
    forall a b. (a -> b) -> a -> b
    $ Token CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    Token s -> m (Token s)
    char Char
    Token CsvAmountString
    ':'
      SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall s (m :: * -> *).
    (Stream s, Token s ~ Char) =>
    ParsecT HledgerParseErrorData s m ()
    skipNonNewlineSpaces1
      let separator :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    separator = SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall s (m :: * -> *).
    (Stream s, Token s ~ Char) =>
    ParsecT HledgerParseErrorData s m ()
    skipNonNewlineSpaces StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Char
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Token CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    Token s -> m (Token s)
    char Char
    Token CsvAmountString
    ',' StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall s (m :: * -> *).
    (Stream s, Token s ~ Char) =>
    ParsecT HledgerParseErrorData s m ()
    skipNonNewlineSpaces
      CsvAmountString
    f <- CsvAmountString -> Maybe CsvAmountString -> CsvAmountString
    forall a. a -> Maybe a -> a
    fromMaybe CsvAmountString
    "" (Maybe CsvAmountString -> CsvAmountString)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe CsvAmountString)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe CsvAmountString)
    forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
    optional StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    fieldnamep
      [CsvAmountString]
    fs <- StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    -> CsvRulesParser [CsvAmountString]
    forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
    some (StateT
       CsvRulesParsed
       (ParsecT HledgerParseErrorData CsvAmountString Identity)
       CsvAmountString
     -> CsvRulesParser [CsvAmountString])
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    -> CsvRulesParser [CsvAmountString]
    forall a b. (a -> b) -> a -> b
    $ (StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    separator StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> CsvAmountString -> Maybe CsvAmountString -> CsvAmountString
    forall a. a -> Maybe a -> a
    fromMaybe CsvAmountString
    "" (Maybe CsvAmountString -> CsvAmountString)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe CsvAmountString)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe CsvAmountString)
    forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
    optional StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    fieldnamep)
      SimpleTextParser [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Char]
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser [Char]
    forall (m :: * -> *). TextParser m [Char]
    restofline
      [CsvAmountString] -> CsvRulesParser [CsvAmountString]
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([CsvAmountString] -> CsvRulesParser [CsvAmountString])
    -> ([CsvAmountString] -> [CsvAmountString])
    -> [CsvAmountString]
    -> CsvRulesParser [CsvAmountString]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (CsvAmountString -> CsvAmountString)
    -> [CsvAmountString] -> [CsvAmountString]
    forall a b. (a -> b) -> [a] -> [b]
    map CsvAmountString -> CsvAmountString
    T.toLower ([CsvAmountString] -> CsvRulesParser [CsvAmountString])
    -> [CsvAmountString] -> CsvRulesParser [CsvAmountString]
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString
    fCsvAmountString -> [CsvAmountString] -> [CsvAmountString]
    forall a. a -> [a] -> [a]
    :[CsvAmountString]
    fs
      ) CsvRulesParser [CsvAmountString]
    -> [Char] -> CsvRulesParser [CsvAmountString]
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "field name list"

    fieldnamep :: CsvRulesParser Text
    fieldnamep :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    fieldnamep = StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    quotedfieldnamep StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall a.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    barefieldnamep

    quotedfieldnamep :: CsvRulesParser Text
    quotedfieldnamep :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    quotedfieldnamep =
        Token CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    Token s -> m (Token s)
    char Char
    Token CsvAmountString
    '"' StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> Maybe [Char]
    -> (Token CsvAmountString -> Bool)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Tokens CsvAmountString)
    forall e s (m :: * -> *).
    MonadParsec e s m =>
    Maybe [Char] -> (Token s -> Bool) -> m (Tokens s)
    takeWhile1P Maybe [Char]
    forall a. Maybe a
    Nothing (Char -> [Char] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `notElem` ([Char]
    "\"\n:;#~" :: [Char])) StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* Token CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    Token s -> m (Token s)
    char Char
    Token CsvAmountString
    '"'

    barefieldnamep :: CsvRulesParser Text
    barefieldnamep :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    barefieldnamep = Maybe [Char]
    -> (Token CsvAmountString -> Bool)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Tokens CsvAmountString)
    forall e s (m :: * -> *).
    MonadParsec e s m =>
    Maybe [Char] -> (Token s -> Bool) -> m (Tokens s)
    takeWhile1P Maybe [Char]
    forall a. Maybe a
    Nothing (Char -> [Char] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `notElem` ([Char]
    " \t\n,;#~" :: [Char]))

    fieldassignmentp :: CsvRulesParser (HledgerFieldName, FieldTemplate)
    fieldassignmentp :: CsvRulesParser (CsvAmountString, CsvAmountString)
    fieldassignmentp = do
      SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (SimpleTextParser ()
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [Char] -> SimpleTextParser ()
    forall (m :: * -> *). CsvFieldIndex -> [Char] -> TextParser m ()
    dbgparse CsvFieldIndex
    8 [Char]
    "trying fieldassignmentp"
      CsvAmountString
    f <- StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    journalfieldnamep
      CsvAmountString
    v <- [StateT
       CsvRulesParsed
       (ParsecT HledgerParseErrorData CsvAmountString Identity)
       CsvAmountString]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall s (m :: * -> *) a.
    [StateT s (ParsecT HledgerParseErrorData CsvAmountString m) a]
    -> StateT s (ParsecT HledgerParseErrorData CsvAmountString m) a
    choiceInState [ StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    assignmentseparatorp StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    fieldvalp
                         , SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall (m :: * -> *). TextParser m ()
    eolof StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return CsvAmountString
    ""
                         ]
      (CsvAmountString, CsvAmountString)
    -> CsvRulesParser (CsvAmountString, CsvAmountString)
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (CsvAmountString
    f,CsvAmountString
    v)
      CsvRulesParser (CsvAmountString, CsvAmountString)
    -> [Char] -> CsvRulesParser (CsvAmountString, CsvAmountString)
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "field assignment"

    journalfieldnamep :: CsvRulesParser Text
    journalfieldnamep :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    journalfieldnamep = do
      SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (CsvFieldIndex -> [Char] -> SimpleTextParser ()
    forall (m :: * -> *). CsvFieldIndex -> [Char] -> TextParser m ()
    dbgparse CsvFieldIndex
    8 [Char]
    "trying journalfieldnamep")
      [StateT
       CsvRulesParsed
       (ParsecT HledgerParseErrorData CsvAmountString Identity)
       CsvAmountString]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall s (m :: * -> *) a.
    [StateT s (ParsecT HledgerParseErrorData CsvAmountString m) a]
    -> StateT s (ParsecT HledgerParseErrorData CsvAmountString m) a
    choiceInState ([StateT
        CsvRulesParsed
        (ParsecT HledgerParseErrorData CsvAmountString Identity)
        CsvAmountString]
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          CsvAmountString)
    -> [StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          CsvAmountString]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ (CsvAmountString
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          CsvAmountString)
    -> [CsvAmountString]
    -> [StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          CsvAmountString]
    forall a b. (a -> b) -> [a] -> [b]
    map (ParsecT
      HledgerParseErrorData CsvAmountString Identity CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (ParsecT
       HledgerParseErrorData CsvAmountString Identity CsvAmountString
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          CsvAmountString)
    -> (CsvAmountString
        -> ParsecT
             HledgerParseErrorData CsvAmountString Identity CsvAmountString)
    -> CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString
    -> ParsecT
         HledgerParseErrorData CsvAmountString Identity CsvAmountString
    Tokens CsvAmountString
    -> ParsecT
         HledgerParseErrorData
         CsvAmountString
         Identity
         (Tokens CsvAmountString)
    forall e s (m :: * -> *).
    MonadParsec e s m =>
    Tokens s -> m (Tokens s)
    string) [CsvAmountString]
    journalfieldnames

    maxpostings :: CsvFieldIndex
    maxpostings = CsvFieldIndex
    99

    -- Transaction fields and pseudo fields for CSV conversion.
    -- Names must precede any other name they contain, for the parser
    -- (amount-in before amount; date2 before date). TODO: fix
    journalfieldnames :: [CsvAmountString]
    journalfieldnames =
      [[CsvAmountString]] -> [CsvAmountString]
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    concat [[ CsvAmountString
    "account" CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    i
              ,CsvAmountString
    "amount" CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    i CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    "-in"
              ,CsvAmountString
    "amount" CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    i CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    "-out"
              ,CsvAmountString
    "amount" CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    i
              ,CsvAmountString
    "balance" CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    i
              ,CsvAmountString
    "comment" CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    i
              ,CsvAmountString
    "currency" CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    i
              ] | CsvFieldIndex
    x <- [CsvFieldIndex
    maxpostings, (CsvFieldIndex
    maxpostingsCsvFieldIndex -> CsvFieldIndex -> CsvFieldIndex
    forall a. Num a => a -> a -> a
    -CsvFieldIndex
    1)..CsvFieldIndex
    1], let i :: CsvAmountString
    i = [Char] -> CsvAmountString
    T.pack ([Char] -> CsvAmountString) -> [Char] -> CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [Char]
    forall a. Show a => a -> [Char]
    show CsvFieldIndex
    x]
      [CsvAmountString] -> [CsvAmountString] -> [CsvAmountString]
    forall a. [a] -> [a] -> [a]
    ++
      [CsvAmountString
    "amount-in"
      ,CsvAmountString
    "amount-out"
      ,CsvAmountString
    "amount"
      ,CsvAmountString
    "balance"
      ,CsvAmountString
    "code"
      ,CsvAmountString
    "comment"
      ,CsvAmountString
    "currency"
      ,CsvAmountString
    "date2"
      ,CsvAmountString
    "date"
      ,CsvAmountString
    "description"
      ,CsvAmountString
    "status"
      ,CsvAmountString
    "skip" -- skip and end are not really fields, but we list it here to allow conditional rules that skip records
      ,CsvAmountString
    "end"
      ]

    assignmentseparatorp :: CsvRulesParser ()
    assignmentseparatorp :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    assignmentseparatorp = do
      SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (SimpleTextParser ()
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [Char] -> SimpleTextParser ()
    forall (m :: * -> *). CsvFieldIndex -> [Char] -> TextParser m ()
    dbgparse CsvFieldIndex
    8 [Char]
    "trying assignmentseparatorp"
      ()
    _ <- [StateT
       CsvRulesParsed
       (ParsecT HledgerParseErrorData CsvAmountString Identity)
       ()]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall s (m :: * -> *) a.
    [StateT s (ParsecT HledgerParseErrorData CsvAmountString m) a]
    -> StateT s (ParsecT HledgerParseErrorData CsvAmountString m) a
    choiceInState [ SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall s (m :: * -> *).
    (Stream s, Token s ~ Char) =>
    ParsecT HledgerParseErrorData s m ()
    skipNonNewlineSpaces StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Char
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Token CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    Token s -> m (Token s)
    char Char
    Token CsvAmountString
    ':' StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall s (m :: * -> *).
    (Stream s, Token s ~ Char) =>
    ParsecT HledgerParseErrorData s m ()
    skipNonNewlineSpaces
                         , SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall s (m :: * -> *).
    (Stream s, Token s ~ Char) =>
    ParsecT HledgerParseErrorData s m ()
    skipNonNewlineSpaces1
                         ]
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

    fieldvalp :: CsvRulesParser Text
    fieldvalp :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    fieldvalp = do
      SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (SimpleTextParser ()
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [Char] -> SimpleTextParser ()
    forall (m :: * -> *). CsvFieldIndex -> [Char] -> TextParser m ()
    dbgparse CsvFieldIndex
    8 [Char]
    "trying fieldvalp"
      [Char] -> CsvAmountString
    T.pack ([Char] -> CsvAmountString)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      (Token CsvAmountString)
    forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
    anySingle StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Char]
    forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
    `manyTill` SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall (m :: * -> *). TextParser m ()
    eolof

    -- A conditional block: one or more matchers, one per line, followed by one or more indented rules.
    conditionalblockp :: CsvRulesParser ConditionalBlock
    conditionalblockp :: CsvRulesParser ConditionalBlock
    conditionalblockp = do
      SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (SimpleTextParser ()
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [Char] -> SimpleTextParser ()
    forall (m :: * -> *). CsvFieldIndex -> [Char] -> TextParser m ()
    dbgparse CsvFieldIndex
    8 [Char]
    "trying conditionalblockp"
      -- "if\nMATCHER" or "if    \nMATCHER" or "if MATCHER"
      CsvFieldIndex
    start <- StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvFieldIndex
    forall e s (m :: * -> *). MonadParsec e s m => m CsvFieldIndex
    getOffset
      Tokens CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Tokens CsvAmountString)
    forall e s (m :: * -> *).
    MonadParsec e s m =>
    Tokens s -> m (Tokens s)
    string Tokens CsvAmountString
    "if" StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      (Tokens CsvAmountString)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe Char)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe Char)
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> ( (StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    m (Token s)
    newline StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe Char)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe Char)
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Maybe Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe Char)
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe Char
    forall a. Maybe a
    Nothing)
                      StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      (Maybe Char)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe Char)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe Char)
    forall a.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> (SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall s (m :: * -> *).
    (Stream s, Token s ~ Char) =>
    ParsecT HledgerParseErrorData s m ()
    skipNonNewlineSpaces1 StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe Char)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe Char)
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe Char)
    forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
    optional StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    m (Token s)
    newline))
      [Matcher]
    ms <- StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Matcher
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Matcher]
    forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
    some StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Matcher
    matcherp
      [(CsvAmountString, CsvAmountString)]
    as <- [Maybe (CsvAmountString, CsvAmountString)]
    -> [(CsvAmountString, CsvAmountString)]
    forall a. [Maybe a] -> [a]
    catMaybes ([Maybe (CsvAmountString, CsvAmountString)]
     -> [(CsvAmountString, CsvAmountString)])
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Maybe (CsvAmountString, CsvAmountString)]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [(CsvAmountString, CsvAmountString)]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$>
        StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      (Maybe (CsvAmountString, CsvAmountString))
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Maybe (CsvAmountString, CsvAmountString)]
    forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
    many (SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall s (m :: * -> *).
    (Stream s, Token s ~ Char) =>
    ParsecT HledgerParseErrorData s m ()
    skipNonNewlineSpaces1 StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe (CsvAmountString, CsvAmountString))
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe (CsvAmountString, CsvAmountString))
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >>
              [StateT
       CsvRulesParsed
       (ParsecT HledgerParseErrorData CsvAmountString Identity)
       (Maybe (CsvAmountString, CsvAmountString))]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe (CsvAmountString, CsvAmountString))
    forall (f :: * -> *) (m :: * -> *) a.
    (Foldable f, Alternative m) =>
    f (m a) -> m a
    choice [ SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall (m :: * -> *). TextParser m ()
    eolof StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe (CsvAmountString, CsvAmountString))
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe (CsvAmountString, CsvAmountString))
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Maybe (CsvAmountString, CsvAmountString)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe (CsvAmountString, CsvAmountString))
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe (CsvAmountString, CsvAmountString)
    forall a. Maybe a
    Nothing
                     , ((CsvAmountString, CsvAmountString)
     -> Maybe (CsvAmountString, CsvAmountString))
    -> CsvRulesParser (CsvAmountString, CsvAmountString)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Maybe (CsvAmountString, CsvAmountString))
    forall a b.
    (a -> b)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (CsvAmountString, CsvAmountString)
    -> Maybe (CsvAmountString, CsvAmountString)
    forall a. a -> Maybe a
    Just CsvRulesParser (CsvAmountString, CsvAmountString)
    fieldassignmentp
                     ])
      Bool
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when ([(CsvAmountString, CsvAmountString)] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [(CsvAmountString, CsvAmountString)]
    as) (StateT
       CsvRulesParsed
       (ParsecT HledgerParseErrorData CsvAmountString Identity)
       ()
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b. (a -> b) -> a -> b
    $
        HledgerParseErrorData
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall e s (m :: * -> *) a. MonadParsec e s m => e -> m a
    customFailure (HledgerParseErrorData
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> HledgerParseErrorData
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [Char] -> HledgerParseErrorData
    parseErrorAt CsvFieldIndex
    start ([Char] -> HledgerParseErrorData)
    -> [Char] -> HledgerParseErrorData
    forall a b. (a -> b) -> a -> b
    $  [Char]
    "start of conditional block found, but no assignment rules afterward\n(assignment rules in a conditional block should be indented)"
      ConditionalBlock -> CsvRulesParser ConditionalBlock
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ConditionalBlock -> CsvRulesParser ConditionalBlock)
    -> ConditionalBlock -> CsvRulesParser ConditionalBlock
    forall a b. (a -> b) -> a -> b
    $ CB{cbMatchers :: [Matcher]
    cbMatchers=[Matcher]
    ms, cbAssignments :: [(CsvAmountString, CsvAmountString)]
    cbAssignments=[(CsvAmountString, CsvAmountString)]
    as}
      CsvRulesParser ConditionalBlock
    -> [Char] -> CsvRulesParser ConditionalBlock
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "conditional block"

    -- A conditional table: "if" followed by separator, followed by some field names,
    -- followed by many lines, each of which has:
    -- one matchers, followed by field assignments (as many as there were fields)
    conditionaltablep :: CsvRulesParser [ConditionalBlock]
    conditionaltablep :: CsvRulesParser [ConditionalBlock]
    conditionaltablep = do
      SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (SimpleTextParser ()
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [Char] -> SimpleTextParser ()
    forall (m :: * -> *). CsvFieldIndex -> [Char] -> TextParser m ()
    dbgparse CsvFieldIndex
    8 [Char]
    "trying conditionaltablep"
      CsvFieldIndex
    start <- StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvFieldIndex
    forall e s (m :: * -> *). MonadParsec e s m => m CsvFieldIndex
    getOffset
      Tokens CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Tokens CsvAmountString)
    forall e s (m :: * -> *).
    MonadParsec e s m =>
    Tokens s -> m (Tokens s)
    string Tokens CsvAmountString
    "if"
      Char
    sep <- SimpleTextParser Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Char
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (SimpleTextParser Char
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          Char)
    -> SimpleTextParser Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Char
    forall a b. (a -> b) -> a -> b
    $ (Token CsvAmountString -> Bool)
    -> ParsecT
         HledgerParseErrorData
         CsvAmountString
         Identity
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    MonadParsec e s m =>
    (Token s -> Bool) -> m (Token s)
    satisfy (\Token CsvAmountString
    c -> Bool -> Bool
    not (Char -> Bool
    isAlphaNum Char
    Token CsvAmountString
    c Bool -> Bool -> Bool
    || Char -> Bool
    isSpace Char
    Token CsvAmountString
    c))
      [CsvAmountString]
    fields <- StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    journalfieldnamep StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Char
    -> CsvRulesParser [CsvAmountString]
    forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
    `sepBy1` (Token CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    Token s -> m (Token s)
    char Char
    Token CsvAmountString
    sep)
      StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    m (Token s)
    newline
      [(Matcher, [CsvAmountString])]
    body <- (StateT
       CsvRulesParsed
       (ParsecT HledgerParseErrorData CsvAmountString Identity)
       (Matcher, [CsvAmountString])
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ()
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          [(Matcher, [CsvAmountString])])
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Matcher, [CsvAmountString])
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [(Matcher, [CsvAmountString])]
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      (Matcher, [CsvAmountString])
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [(Matcher, [CsvAmountString])]
    forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
    manyTill (SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall (m :: * -> *). TextParser m ()
    eolof) (StateT
       CsvRulesParsed
       (ParsecT HledgerParseErrorData CsvAmountString Identity)
       (Matcher, [CsvAmountString])
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          [(Matcher, [CsvAmountString])])
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Matcher, [CsvAmountString])
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [(Matcher, [CsvAmountString])]
    forall a b. (a -> b) -> a -> b
    $ do
        CsvFieldIndex
    off <- StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvFieldIndex
    forall e s (m :: * -> *). MonadParsec e s m => m CsvFieldIndex
    getOffset
        Matcher
    m <- StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    matcherp' (StateT
       CsvRulesParsed
       (ParsecT HledgerParseErrorData CsvAmountString Identity)
       ()
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          Matcher)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    forall a b. (a -> b) -> a -> b
    $ StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (StateT
       CsvRulesParsed
       (ParsecT HledgerParseErrorData CsvAmountString Identity)
       Char
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b. (a -> b) -> a -> b
    $ Token CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    Token s -> m (Token s)
    char Char
    Token CsvAmountString
    sep
        [CsvAmountString]
    vs <- (Char -> Bool) -> CsvAmountString -> [CsvAmountString]
    T.split (Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    ==Char
    sep) (CsvAmountString -> [CsvAmountString])
    -> ([Char] -> CsvAmountString) -> [Char] -> [CsvAmountString]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Char] -> CsvAmountString
    T.pack ([Char] -> [CsvAmountString])
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Char]
    -> CsvRulesParser [CsvAmountString]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> SimpleTextParser [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Char]
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser [Char]
    forall (m :: * -> *). TextParser m [Char]
    restofline
        if ([CsvAmountString] -> CsvFieldIndex
    forall a. [a] -> CsvFieldIndex
    forall (t :: * -> *) a. Foldable t => t a -> CsvFieldIndex
    length [CsvAmountString]
    vs CsvFieldIndex -> CsvFieldIndex -> Bool
    forall a. Eq a => a -> a -> Bool
    /= [CsvAmountString] -> CsvFieldIndex
    forall a. [a] -> CsvFieldIndex
    forall (t :: * -> *) a. Foldable t => t a -> CsvFieldIndex
    length [CsvAmountString]
    fields)
          then HledgerParseErrorData
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Matcher, [CsvAmountString])
    forall e s (m :: * -> *) a. MonadParsec e s m => e -> m a
    customFailure (HledgerParseErrorData
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          (Matcher, [CsvAmountString]))
    -> HledgerParseErrorData
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Matcher, [CsvAmountString])
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [Char] -> HledgerParseErrorData
    parseErrorAt CsvFieldIndex
    off ([Char] -> HledgerParseErrorData)
    -> [Char] -> HledgerParseErrorData
    forall a b. (a -> b) -> a -> b
    $ (([Char] -> CsvFieldIndex -> CsvFieldIndex -> [Char]
    forall r. PrintfType r => [Char] -> r
    printf [Char]
    "line of conditional table should have %d values, but this one has only %d" ([CsvAmountString] -> CsvFieldIndex
    forall a. [a] -> CsvFieldIndex
    forall (t :: * -> *) a. Foldable t => t a -> CsvFieldIndex
    length [CsvAmountString]
    fields) ([CsvAmountString] -> CsvFieldIndex
    forall a. [a] -> CsvFieldIndex
    forall (t :: * -> *) a. Foldable t => t a -> CsvFieldIndex
    length [CsvAmountString]
    vs)) :: String)
          else (Matcher, [CsvAmountString])
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Matcher, [CsvAmountString])
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Matcher
    m,[CsvAmountString]
    vs)
      Bool
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when ([(Matcher, [CsvAmountString])] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [(Matcher, [CsvAmountString])]
    body) (StateT
       CsvRulesParsed
       (ParsecT HledgerParseErrorData CsvAmountString Identity)
       ()
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b. (a -> b) -> a -> b
    $
        HledgerParseErrorData
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall e s (m :: * -> *) a. MonadParsec e s m => e -> m a
    customFailure (HledgerParseErrorData
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> HledgerParseErrorData
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [Char] -> HledgerParseErrorData
    parseErrorAt CsvFieldIndex
    start ([Char] -> HledgerParseErrorData)
    -> [Char] -> HledgerParseErrorData
    forall a b. (a -> b) -> a -> b
    $ [Char]
    "start of conditional table found, but no assignment rules afterward"
      [ConditionalBlock] -> CsvRulesParser [ConditionalBlock]
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([ConditionalBlock] -> CsvRulesParser [ConditionalBlock])
    -> [ConditionalBlock] -> CsvRulesParser [ConditionalBlock]
    forall a b. (a -> b) -> a -> b
    $ (((Matcher, [CsvAmountString]) -> ConditionalBlock)
     -> [(Matcher, [CsvAmountString])] -> [ConditionalBlock])
    -> [(Matcher, [CsvAmountString])]
    -> ((Matcher, [CsvAmountString]) -> ConditionalBlock)
    -> [ConditionalBlock]
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip ((Matcher, [CsvAmountString]) -> ConditionalBlock)
    -> [(Matcher, [CsvAmountString])] -> [ConditionalBlock]
    forall a b. (a -> b) -> [a] -> [b]
    map [(Matcher, [CsvAmountString])]
    body (((Matcher, [CsvAmountString]) -> ConditionalBlock)
     -> [ConditionalBlock])
    -> ((Matcher, [CsvAmountString]) -> ConditionalBlock)
    -> [ConditionalBlock]
    forall a b. (a -> b) -> a -> b
    $ \(Matcher
    m,[CsvAmountString]
    vs) ->
        CB{cbMatchers :: [Matcher]
    cbMatchers=[Matcher
    m], cbAssignments :: [(CsvAmountString, CsvAmountString)]
    cbAssignments=[CsvAmountString]
    -> [CsvAmountString] -> [(CsvAmountString, CsvAmountString)]
    forall a b. [a] -> [b] -> [(a, b)]
    zip [CsvAmountString]
    fields [CsvAmountString]
    vs}
      CsvRulesParser [ConditionalBlock]
    -> [Char] -> CsvRulesParser [ConditionalBlock]
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "conditional table"

    -- A single matcher, on one line.
    matcherp' :: CsvRulesParser () -> CsvRulesParser Matcher
    matcherp' :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    matcherp' StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    end = StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Matcher
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    forall a.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
    try (StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    fieldmatcherp StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    end) StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Matcher
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    forall a.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    recordmatcherp StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    end

    matcherp :: CsvRulesParser Matcher
    matcherp :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Matcher
    matcherp = StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    matcherp' (SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall (m :: * -> *). TextParser m ()
    eolof)

    -- A single whole-record matcher.
    -- A pattern on the whole line, not beginning with a csv field reference.
    recordmatcherp :: CsvRulesParser () -> CsvRulesParser Matcher
    recordmatcherp :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    recordmatcherp StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    end = do
      SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (SimpleTextParser ()
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [Char] -> SimpleTextParser ()
    forall (m :: * -> *). CsvFieldIndex -> [Char] -> TextParser m ()
    dbgparse CsvFieldIndex
    8 [Char]
    "trying recordmatcherp"
      -- pos <- currentPos
      -- _  <- optional (matchoperatorp >> lift skipNonNewlineSpaces >> optional newline)
      MatcherPrefix
    p <- CsvRulesParser MatcherPrefix
    matcherprefixp
      Regexp
    r <- StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> CsvRulesParser Regexp
    regexp StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    end
      Matcher
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Matcher
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          Matcher)
    -> Matcher
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    forall a b. (a -> b) -> a -> b
    $ MatcherPrefix -> Regexp -> Matcher
    RecordMatcher MatcherPrefix
    p Regexp
    r
      -- when (null ps) $
      --   Fail.fail "start of record matcher found, but no patterns afterward\n(patterns should not be indented)"
      StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Matcher
    -> [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "record matcher"

    -- | A single matcher for a specific field. A csv field reference
    -- (like %date or %1), and a pattern on the rest of the line,
    -- optionally space-separated. Eg:
    -- %description chez jacques
    fieldmatcherp :: CsvRulesParser () -> CsvRulesParser Matcher
    fieldmatcherp :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    fieldmatcherp StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    end = do
      SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (SimpleTextParser ()
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [Char] -> SimpleTextParser ()
    forall (m :: * -> *). CsvFieldIndex -> [Char] -> TextParser m ()
    dbgparse CsvFieldIndex
    8 [Char]
    "trying fieldmatcher"
      -- An optional fieldname (default: "all")
      -- f <- fromMaybe "all" `fmap` (optional $ do
      --        f' <- fieldnamep
      --        lift skipNonNewlineSpaces
      --        return f')
      MatcherPrefix
    p <- CsvRulesParser MatcherPrefix
    matcherprefixp
      CsvAmountString
    f <- StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    csvfieldreferencep StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall s (m :: * -> *).
    (Stream s, Token s ~ Char) =>
    ParsecT HledgerParseErrorData s m ()
    skipNonNewlineSpaces
      -- optional operator.. just ~ (case insensitive infix regex) for now
      -- _op <- fromMaybe "~" <$> optional matchoperatorp
      SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall s (m :: * -> *).
    (Stream s, Token s ~ Char) =>
    ParsecT HledgerParseErrorData s m ()
    skipNonNewlineSpaces
      Regexp
    r <- StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> CsvRulesParser Regexp
    regexp StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    end
      Matcher
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Matcher
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          Matcher)
    -> Matcher
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    forall a b. (a -> b) -> a -> b
    $ MatcherPrefix -> CsvAmountString -> Regexp -> Matcher
    FieldMatcher MatcherPrefix
    p CsvAmountString
    f Regexp
    r
      StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Matcher
    -> [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "field matcher"

    matcherprefixp :: CsvRulesParser MatcherPrefix
    matcherprefixp :: CsvRulesParser MatcherPrefix
    matcherprefixp = do
      SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (SimpleTextParser ()
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [Char] -> SimpleTextParser ()
    forall (m :: * -> *). CsvFieldIndex -> [Char] -> TextParser m ()
    dbgparse CsvFieldIndex
    8 [Char]
    "trying matcherprefixp"
      (Token CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    Token s -> m (Token s)
    char Char
    Token CsvAmountString
    '&' StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall s (m :: * -> *).
    (Stream s, Token s ~ Char) =>
    ParsecT HledgerParseErrorData s m ()
    skipNonNewlineSpaces StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> CsvRulesParser MatcherPrefix -> CsvRulesParser MatcherPrefix
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> MatcherPrefix -> CsvRulesParser MatcherPrefix
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return MatcherPrefix
    And) CsvRulesParser MatcherPrefix
    -> CsvRulesParser MatcherPrefix -> CsvRulesParser MatcherPrefix
    forall a.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> (Token CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    Token s -> m (Token s)
    char Char
    Token CsvAmountString
    '!' StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser ()
    forall s (m :: * -> *).
    (Stream s, Token s ~ Char) =>
    ParsecT HledgerParseErrorData s m ()
    skipNonNewlineSpaces StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> CsvRulesParser MatcherPrefix -> CsvRulesParser MatcherPrefix
    forall a b.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> MatcherPrefix -> CsvRulesParser MatcherPrefix
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return MatcherPrefix
    Not) CsvRulesParser MatcherPrefix
    -> CsvRulesParser MatcherPrefix -> CsvRulesParser MatcherPrefix
    forall a.
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> MatcherPrefix -> CsvRulesParser MatcherPrefix
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return MatcherPrefix
    None

    csvfieldreferencep :: CsvRulesParser CsvFieldReference
    csvfieldreferencep :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    csvfieldreferencep = do
      SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (SimpleTextParser ()
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [Char] -> SimpleTextParser ()
    forall (m :: * -> *). CsvFieldIndex -> [Char] -> TextParser m ()
    dbgparse CsvFieldIndex
    8 [Char]
    "trying csvfieldreferencep"
      Token CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    Token s -> m (Token s)
    char Char
    Token CsvAmountString
    '%'
      Char -> CsvAmountString -> CsvAmountString
    T.cons Char
    '%' (CsvAmountString -> CsvAmountString)
    -> (CsvAmountString -> CsvAmountString)
    -> CsvAmountString
    -> CsvAmountString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString -> CsvAmountString
    textQuoteIfNeeded (CsvAmountString -> CsvAmountString)
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    fieldnamep

    -- A single regular expression
    regexp :: CsvRulesParser () -> CsvRulesParser Regexp
    regexp :: StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    -> CsvRulesParser Regexp
    regexp StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    end = do
      SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (SimpleTextParser ()
     -> StateT
          CsvRulesParsed
          (ParsecT HledgerParseErrorData CsvAmountString Identity)
          ())
    -> SimpleTextParser ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [Char] -> SimpleTextParser ()
    forall (m :: * -> *). CsvFieldIndex -> [Char] -> TextParser m ()
    dbgparse CsvFieldIndex
    8 [Char]
    "trying regexp"
      -- notFollowedBy matchoperatorp
      Char
    c <- SimpleTextParser Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Char
    forall (m :: * -> *) a. Monad m => m a -> StateT CsvRulesParsed m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift SimpleTextParser Char
    forall (m :: * -> *). TextParser m Char
    nonspace
      [Char]
    cs <- StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      (Token CsvAmountString)
    forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
    anySingle StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Char
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         ()
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         [Char]
    forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m [a]
    `manyTill` StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      ()
    end
      case CsvAmountString -> Either [Char] Regexp
    toRegexCI (CsvAmountString -> Either [Char] Regexp)
    -> ([Char] -> CsvAmountString) -> [Char] -> Either [Char] Regexp
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString -> CsvAmountString
    T.strip (CsvAmountString -> CsvAmountString)
    -> ([Char] -> CsvAmountString) -> [Char] -> CsvAmountString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Char] -> CsvAmountString
    T.pack ([Char] -> Either [Char] Regexp) -> [Char] -> Either [Char] Regexp
    forall a b. (a -> b) -> a -> b
    $ Char
    cChar -> [Char] -> [Char]
    forall a. a -> [a] -> [a]
    :[Char]
    cs of
           Left [Char]
    x -> [Char] -> CsvRulesParser Regexp
    forall a.
    [Char]
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. MonadFail m => [Char] -> m a
    Fail.fail ([Char] -> CsvRulesParser Regexp)
    -> [Char] -> CsvRulesParser Regexp
    forall a b. (a -> b) -> a -> b
    $ [Char]
    "CSV parser: " [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [Char]
    x
           Right Regexp
    x -> Regexp -> CsvRulesParser Regexp
    forall a.
    a
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Regexp
    x

    -- -- A match operator, indicating the type of match to perform.
    -- -- Currently just ~ meaning case insensitive infix regex match.
    -- matchoperatorp :: CsvRulesParser String
    -- matchoperatorp = fmap T.unpack $ choiceInState $ map string
    --   ["~"
    --   -- ,"!~"
    --   -- ,"="
    --   -- ,"!="
    --   ]

    _RULES_LOOKUP__________________________________________ :: a
    _RULES_LOOKUP__________________________________________ = a
    forall a. HasCallStack => a
    undefined

    getDirective :: DirectiveName -> CsvRules -> Maybe FieldTemplate
    getDirective :: CsvAmountString -> CsvRules -> Maybe CsvAmountString
    getDirective CsvAmountString
    directivename = CsvAmountString
    -> [(CsvAmountString, CsvAmountString)] -> Maybe CsvAmountString
    forall a b. Eq a => a -> [(a, b)] -> Maybe b
    lookup CsvAmountString
    directivename ([(CsvAmountString, CsvAmountString)] -> Maybe CsvAmountString)
    -> (CsvRules -> [(CsvAmountString, CsvAmountString)])
    -> CsvRules
    -> Maybe CsvAmountString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvRules -> [(CsvAmountString, CsvAmountString)]
    forall a. CsvRules' a -> [(CsvAmountString, CsvAmountString)]
    rdirectives

    -- | Look up the value (template) of a csv rule by rule keyword.
    csvRule :: CsvRules -> DirectiveName -> Maybe FieldTemplate
    csvRule :: CsvRules -> CsvAmountString -> Maybe CsvAmountString
    csvRule CsvRules
    rules = (CsvAmountString -> CsvRules -> Maybe CsvAmountString
    `getDirective` CsvRules
    rules)

    -- | Look up the value template assigned to a hledger field by field
    -- list/field assignment rules, taking into account the current record and
    -- conditional rules.
    hledgerField :: CsvRules -> CsvRecord -> HledgerFieldName -> Maybe FieldTemplate
    hledgerField :: CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    hledgerField = CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    getEffectiveAssignment

    -- | Look up the final value assigned to a hledger field, with csv field
    -- references interpolated.
    hledgerFieldValue :: CsvRules -> CsvRecord -> HledgerFieldName -> Maybe Text
    hledgerFieldValue :: CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    hledgerFieldValue CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    f = ((CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString -> Maybe CsvAmountString
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (CsvRules
    -> [CsvAmountString]
    -> CsvAmountString
    -> CsvAmountString
    -> CsvAmountString
    renderTemplate CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    f) (Maybe CsvAmountString -> Maybe CsvAmountString)
    -> (CsvAmountString -> Maybe CsvAmountString)
    -> CsvAmountString
    -> Maybe CsvAmountString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    hledgerField CsvRules
    rules [CsvAmountString]
    record) CsvAmountString
    f

    maybeNegate :: MatcherPrefix -> Bool -> Bool
    maybeNegate :: MatcherPrefix -> Bool -> Bool
    maybeNegate MatcherPrefix
    Not Bool
    origbool = Bool -> Bool
    not Bool
    origbool
    maybeNegate MatcherPrefix
    _ Bool
    origbool = Bool
    origbool

    -- | Given the conversion rules, a CSV record and a hledger field name, find
    -- the value template ultimately assigned to this field, if any, by a field
    -- assignment at top level or in a conditional block matching this record.
    --
    -- Note conditional blocks' patterns are matched against an approximation of the
    -- CSV record: all the field values, without enclosing quotes, comma-separated.
    --
    getEffectiveAssignment :: CsvRules -> CsvRecord -> HledgerFieldName -> Maybe FieldTemplate
    getEffectiveAssignment :: CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    getEffectiveAssignment CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    f = [CsvAmountString] -> Maybe CsvAmountString
    forall a. [a] -> Maybe a
    lastMay ([CsvAmountString] -> Maybe CsvAmountString)
    -> [CsvAmountString] -> Maybe CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ ((CsvAmountString, CsvAmountString) -> CsvAmountString)
    -> [(CsvAmountString, CsvAmountString)] -> [CsvAmountString]
    forall a b. (a -> b) -> [a] -> [b]
    map (CsvAmountString, CsvAmountString) -> CsvAmountString
    forall a b. (a, b) -> b
    snd ([(CsvAmountString, CsvAmountString)] -> [CsvAmountString])
    -> [(CsvAmountString, CsvAmountString)] -> [CsvAmountString]
    forall a b. (a -> b) -> a -> b
    $ [(CsvAmountString, CsvAmountString)]
    assignments
      where
        -- all active assignments to field f, in order
        assignments :: [(CsvAmountString, CsvAmountString)]
    assignments = [Char]
    -> [(CsvAmountString, CsvAmountString)]
    -> [(CsvAmountString, CsvAmountString)]
    forall a. Show a => [Char] -> a -> a
    dbg9 [Char]
    "csv assignments" ([(CsvAmountString, CsvAmountString)]
     -> [(CsvAmountString, CsvAmountString)])
    -> [(CsvAmountString, CsvAmountString)]
    -> [(CsvAmountString, CsvAmountString)]
    forall a b. (a -> b) -> a -> b
    $ ((CsvAmountString, CsvAmountString) -> Bool)
    -> [(CsvAmountString, CsvAmountString)]
    -> [(CsvAmountString, CsvAmountString)]
    forall a. (a -> Bool) -> [a] -> [a]
    filter ((CsvAmountString -> CsvAmountString -> Bool
    forall a. Eq a => a -> a -> Bool
    ==CsvAmountString
    f)(CsvAmountString -> Bool)
    -> ((CsvAmountString, CsvAmountString) -> CsvAmountString)
    -> (CsvAmountString, CsvAmountString)
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .(CsvAmountString, CsvAmountString) -> CsvAmountString
    forall a b. (a, b) -> a
    fst) ([(CsvAmountString, CsvAmountString)]
     -> [(CsvAmountString, CsvAmountString)])
    -> [(CsvAmountString, CsvAmountString)]
    -> [(CsvAmountString, CsvAmountString)]
    forall a b. (a -> b) -> a -> b
    $ [(CsvAmountString, CsvAmountString)]
    toplevelassignments [(CsvAmountString, CsvAmountString)]
    -> [(CsvAmountString, CsvAmountString)]
    -> [(CsvAmountString, CsvAmountString)]
    forall a. [a] -> [a] -> [a]
    ++ [(CsvAmountString, CsvAmountString)]
    conditionalassignments
        -- all top level field assignments
        toplevelassignments :: [(CsvAmountString, CsvAmountString)]
    toplevelassignments    = CsvRules -> [(CsvAmountString, CsvAmountString)]
    forall a. CsvRules' a -> [(CsvAmountString, CsvAmountString)]
    rassignments CsvRules
    rules
        -- all field assignments in conditional blocks assigning to field f and active for the current csv record
        conditionalassignments :: [(CsvAmountString, CsvAmountString)]
    conditionalassignments = (ConditionalBlock -> [(CsvAmountString, CsvAmountString)])
    -> [ConditionalBlock] -> [(CsvAmountString, CsvAmountString)]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap ConditionalBlock -> [(CsvAmountString, CsvAmountString)]
    cbAssignments ([ConditionalBlock] -> [(CsvAmountString, CsvAmountString)])
    -> [ConditionalBlock] -> [(CsvAmountString, CsvAmountString)]
    forall a b. (a -> b) -> a -> b
    $ (ConditionalBlock -> Bool)
    -> [ConditionalBlock] -> [ConditionalBlock]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (CsvRules -> [CsvAmountString] -> ConditionalBlock -> Bool
    isBlockActive CsvRules
    rules [CsvAmountString]
    record) ([ConditionalBlock] -> [ConditionalBlock])
    -> [ConditionalBlock] -> [ConditionalBlock]
    forall a b. (a -> b) -> a -> b
    $ (CsvRules -> CsvAmountString -> [ConditionalBlock]
    forall a. CsvRules' a -> a
    rblocksassigning CsvRules
    rules) CsvAmountString
    f

    -- does this conditional block match the current csv record ?
    isBlockActive :: CsvRules -> CsvRecord -> ConditionalBlock -> Bool
    isBlockActive :: CsvRules -> [CsvAmountString] -> ConditionalBlock -> Bool
    isBlockActive CsvRules
    rules [CsvAmountString]
    record CB{[(CsvAmountString, CsvAmountString)]
    [Matcher]
    cbMatchers :: ConditionalBlock -> [Matcher]
    cbAssignments :: ConditionalBlock -> [(CsvAmountString, CsvAmountString)]
    cbMatchers :: [Matcher]
    cbAssignments :: [(CsvAmountString, CsvAmountString)]
    ..} = ([Matcher] -> Bool) -> [[Matcher]] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any ((Matcher -> Bool) -> [Matcher] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    all Matcher -> Bool
    matcherMatches) ([[Matcher]] -> Bool) -> [[Matcher]] -> Bool
    forall a b. (a -> b) -> a -> b
    $ [Matcher] -> [[Matcher]]
    groupedMatchers [Matcher]
    cbMatchers
      where
        -- does this individual matcher match the current csv record ?
        matcherMatches :: Matcher -> Bool
        matcherMatches :: Matcher -> Bool
    matcherMatches (RecordMatcher MatcherPrefix
    prefix Regexp
    pat) = MatcherPrefix -> Bool -> Bool
    maybeNegate MatcherPrefix
    prefix Bool
    origbool
          where
            pat' :: Regexp
    pat' = [Char] -> Regexp -> Regexp
    forall a. Show a => [Char] -> a -> a
    dbg7 [Char]
    "regex" Regexp
    pat
            -- A synthetic whole CSV record to match against. Note, this can be
            -- different from the original CSV data:
            -- - any whitespace surrounding field values is preserved
            -- - any quotes enclosing field values are removed
            -- - and the field separator is always comma
            -- which means that a field containing a comma will look like two fields.
            wholecsvline :: CsvAmountString
    wholecsvline = [Char] -> CsvAmountString -> CsvAmountString
    forall a. Show a => [Char] -> a -> a
    dbg7 [Char]
    "wholecsvline" (CsvAmountString -> CsvAmountString)
    -> CsvAmountString -> CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> [CsvAmountString] -> CsvAmountString
    T.intercalate CsvAmountString
    "," [CsvAmountString]
    record
            origbool :: Bool
    origbool = Regexp -> CsvAmountString -> Bool
    regexMatchText Regexp
    pat' CsvAmountString
    wholecsvline
        matcherMatches (FieldMatcher MatcherPrefix
    prefix CsvAmountString
    csvfieldref Regexp
    pat) = MatcherPrefix -> Bool -> Bool
    maybeNegate MatcherPrefix
    prefix Bool
    origbool
          where
            -- the value of the referenced CSV field to match against.
            csvfieldvalue :: CsvAmountString
    csvfieldvalue = [Char] -> CsvAmountString -> CsvAmountString
    forall a. Show a => [Char] -> a -> a
    dbg7 [Char]
    "csvfieldvalue" (CsvAmountString -> CsvAmountString)
    -> CsvAmountString -> CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ CsvRules -> [CsvAmountString] -> CsvAmountString -> CsvAmountString
    replaceCsvFieldReference CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    csvfieldref
            origbool :: Bool
    origbool = Regexp -> CsvAmountString -> Bool
    regexMatchText Regexp
    pat CsvAmountString
    csvfieldvalue

        -- | Group matchers into associative pairs based on prefix, e.g.:
        --   A
        --   & B
        --   C
        --   D
        --   & E
        --   => [[A, B], [C], [D, E]]
        groupedMatchers :: [Matcher] -> [[Matcher]]
        groupedMatchers :: [Matcher] -> [[Matcher]]
    groupedMatchers [] = []
        groupedMatchers (Matcher
    x:[Matcher]
    xs) = (Matcher
    xMatcher -> [Matcher] -> [Matcher]
    forall a. a -> [a] -> [a]
    :[Matcher]
    ys) [Matcher] -> [[Matcher]] -> [[Matcher]]
    forall a. a -> [a] -> [a]
    : [Matcher] -> [[Matcher]]
    groupedMatchers [Matcher]
    zs
          where
            ([Matcher]
    ys, [Matcher]
    zs) = (Matcher -> Bool) -> [Matcher] -> ([Matcher], [Matcher])
    forall a. (a -> Bool) -> [a] -> ([a], [a])
    span (\Matcher
    y -> Matcher -> MatcherPrefix
    matcherPrefix Matcher
    y MatcherPrefix -> MatcherPrefix -> Bool
    forall a. Eq a => a -> a -> Bool
    == MatcherPrefix
    And) [Matcher]
    xs
            matcherPrefix :: Matcher -> MatcherPrefix
            matcherPrefix :: Matcher -> MatcherPrefix
    matcherPrefix (RecordMatcher MatcherPrefix
    prefix Regexp
    _) = MatcherPrefix
    prefix
            matcherPrefix (FieldMatcher MatcherPrefix
    prefix CsvAmountString
    _ Regexp
    _) = MatcherPrefix
    prefix

    -- | Render a field assignment's template, possibly interpolating referenced
    -- CSV field values or match groups. Outer whitespace is removed from interpolated values.
    renderTemplate ::  CsvRules -> CsvRecord -> HledgerFieldName -> FieldTemplate -> Text
    renderTemplate :: CsvRules
    -> [CsvAmountString]
    -> CsvAmountString
    -> CsvAmountString
    -> CsvAmountString
    renderTemplate CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    f CsvAmountString
    t =
      CsvAmountString
    -> ([CsvAmountString] -> CsvAmountString)
    -> Maybe [CsvAmountString]
    -> CsvAmountString
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe CsvAmountString
    t [CsvAmountString] -> CsvAmountString
    forall a. Monoid a => [a] -> a
    mconcat (Maybe [CsvAmountString] -> CsvAmountString)
    -> Maybe [CsvAmountString] -> CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ Parsec HledgerParseErrorData CsvAmountString [CsvAmountString]
    -> CsvAmountString -> Maybe [CsvAmountString]
    forall e s a. (Ord e, Stream s) => Parsec e s a -> s -> Maybe a
    parseMaybe
        (ParsecT
      HledgerParseErrorData CsvAmountString Identity CsvAmountString
    -> Parsec HledgerParseErrorData CsvAmountString [CsvAmountString]
    forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
    many
          (   ParsecT
      HledgerParseErrorData CsvAmountString Identity CsvAmountString
    literaltextp
          ParsecT
      HledgerParseErrorData CsvAmountString Identity CsvAmountString
    -> ParsecT
         HledgerParseErrorData CsvAmountString Identity CsvAmountString
    -> ParsecT
         HledgerParseErrorData CsvAmountString Identity CsvAmountString
    forall a.
    ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> ParsecT HledgerParseErrorData CsvAmountString Identity a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> (ParsecT
      HledgerParseErrorData CsvAmountString Identity CsvAmountString
    matchrefp ParsecT
      HledgerParseErrorData CsvAmountString Identity CsvAmountString
    -> (CsvAmountString -> CsvAmountString)
    -> ParsecT
         HledgerParseErrorData CsvAmountString Identity CsvAmountString
    forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
    <&> CsvRules
    -> [CsvAmountString]
    -> CsvAmountString
    -> CsvAmountString
    -> CsvAmountString
    replaceRegexGroupReference CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    f)
          ParsecT
      HledgerParseErrorData CsvAmountString Identity CsvAmountString
    -> ParsecT
         HledgerParseErrorData CsvAmountString Identity CsvAmountString
    -> ParsecT
         HledgerParseErrorData CsvAmountString Identity CsvAmountString
    forall a.
    ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> ParsecT HledgerParseErrorData CsvAmountString Identity a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> (ParsecT
      HledgerParseErrorData CsvAmountString Identity CsvAmountString
    fieldrefp ParsecT
      HledgerParseErrorData CsvAmountString Identity CsvAmountString
    -> (CsvAmountString -> CsvAmountString)
    -> ParsecT
         HledgerParseErrorData CsvAmountString Identity CsvAmountString
    forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
    <&> CsvRules -> [CsvAmountString] -> CsvAmountString -> CsvAmountString
    replaceCsvFieldReference   CsvRules
    rules [CsvAmountString]
    record)
          )
        )
        CsvAmountString
    t
      where
        literaltextp :: SimpleTextParser Text
        literaltextp :: ParsecT
      HledgerParseErrorData CsvAmountString Identity CsvAmountString
    literaltextp = SimpleTextParser Char -> SimpleTextParser [Char]
    forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
    some (SimpleTextParser Char
    ParsecT
      HledgerParseErrorData
      CsvAmountString
      Identity
      (Token CsvAmountString)
    nonBackslashOrPercent SimpleTextParser Char
    -> SimpleTextParser Char -> SimpleTextParser Char
    forall a.
    ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> ParsecT HledgerParseErrorData CsvAmountString Identity a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> SimpleTextParser Char
    nonRefBackslash SimpleTextParser Char
    -> SimpleTextParser Char -> SimpleTextParser Char
    forall a.
    ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> ParsecT HledgerParseErrorData CsvAmountString Identity a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> SimpleTextParser Char
    nonRefPercent) SimpleTextParser [Char]
    -> ([Char] -> CsvAmountString)
    -> ParsecT
         HledgerParseErrorData CsvAmountString Identity CsvAmountString
    forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
    <&> [Char] -> CsvAmountString
    T.pack
          where
            nonBackslashOrPercent :: ParsecT
      HledgerParseErrorData
      CsvAmountString
      Identity
      (Token CsvAmountString)
    nonBackslashOrPercent = [Token CsvAmountString]
    -> ParsecT
         HledgerParseErrorData
         CsvAmountString
         Identity
         (Token CsvAmountString)
    forall (f :: * -> *) e s (m :: * -> *).
    (Foldable f, MonadParsec e s m) =>
    f (Token s) -> m (Token s)
    noneOf [Char
    '\\', Char
    '%'] ParsecT
      HledgerParseErrorData
      CsvAmountString
      Identity
      (Token CsvAmountString)
    -> [Char]
    -> ParsecT
         HledgerParseErrorData
         CsvAmountString
         Identity
         (Token CsvAmountString)
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "character other than backslash or percent"
            nonRefBackslash :: SimpleTextParser Char
    nonRefBackslash = SimpleTextParser Char -> SimpleTextParser Char
    forall a.
    ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> ParsecT HledgerParseErrorData CsvAmountString Identity a
    forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
    try (Token CsvAmountString
    -> ParsecT
         HledgerParseErrorData
         CsvAmountString
         Identity
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    Token s -> m (Token s)
    char Char
    Token CsvAmountString
    '\\' SimpleTextParser Char
    -> SimpleTextParser () -> SimpleTextParser Char
    forall a b.
    ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> ParsecT HledgerParseErrorData CsvAmountString Identity b
    -> ParsecT HledgerParseErrorData CsvAmountString Identity a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* SimpleTextParser Char -> SimpleTextParser ()
    forall a.
    ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> SimpleTextParser ()
    forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m ()
    notFollowedBy SimpleTextParser Char
    ParsecT
      HledgerParseErrorData
      CsvAmountString
      Identity
      (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    m (Token s)
    digitChar) SimpleTextParser Char -> [Char] -> SimpleTextParser Char
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "backslash that does not begin a match group reference"
            nonRefPercent :: SimpleTextParser Char
    nonRefPercent   = SimpleTextParser Char -> SimpleTextParser Char
    forall a.
    ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> ParsecT HledgerParseErrorData CsvAmountString Identity a
    forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
    try (Token CsvAmountString
    -> ParsecT
         HledgerParseErrorData
         CsvAmountString
         Identity
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    Token s -> m (Token s)
    char Char
    Token CsvAmountString
    '%'  SimpleTextParser Char
    -> SimpleTextParser () -> SimpleTextParser Char
    forall a b.
    ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> ParsecT HledgerParseErrorData CsvAmountString Identity b
    -> ParsecT HledgerParseErrorData CsvAmountString Identity a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* ParsecT
      HledgerParseErrorData
      CsvAmountString
      Identity
      (Token CsvAmountString)
    -> SimpleTextParser ()
    forall a.
    ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> SimpleTextParser ()
    forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m ()
    notFollowedBy ((Token CsvAmountString -> Bool)
    -> ParsecT
         HledgerParseErrorData
         CsvAmountString
         Identity
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    MonadParsec e s m =>
    (Token s -> Bool) -> m (Token s)
    satisfy Char -> Bool
    Token CsvAmountString -> Bool
    isFieldNameChar)) SimpleTextParser Char -> [Char] -> SimpleTextParser Char
    forall e s (m :: * -> *) a.
    MonadParsec e s m =>
    m a -> [Char] -> m a
    <?> [Char]
    "percent that does not begin a field reference"
        matchrefp :: ParsecT
      HledgerParseErrorData CsvAmountString Identity CsvAmountString
    matchrefp    = (Char -> CsvAmountString -> CsvAmountString)
    -> SimpleTextParser Char
    -> ParsecT
         HledgerParseErrorData CsvAmountString Identity CsvAmountString
    -> ParsecT
         HledgerParseErrorData CsvAmountString Identity CsvAmountString
    forall a b c.
    (a -> b -> c)
    -> ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> ParsecT HledgerParseErrorData CsvAmountString Identity b
    -> ParsecT HledgerParseErrorData CsvAmountString Identity c
    forall (f :: * -> *) a b c.
    Applicative f =>
    (a -> b -> c) -> f a -> f b -> f c
    liftA2 Char -> CsvAmountString -> CsvAmountString
    T.cons (Token CsvAmountString
    -> ParsecT
         HledgerParseErrorData
         CsvAmountString
         Identity
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    Token s -> m (Token s)
    char Char
    Token CsvAmountString
    '\\') (Maybe [Char]
    -> (Token CsvAmountString -> Bool)
    -> ParsecT
         HledgerParseErrorData
         CsvAmountString
         Identity
         (Tokens CsvAmountString)
    forall e s (m :: * -> *).
    MonadParsec e s m =>
    Maybe [Char] -> (Token s -> Bool) -> m (Tokens s)
    takeWhile1P ([Char] -> Maybe [Char]
    forall a. a -> Maybe a
    Just [Char]
    "matchref")  Char -> Bool
    Token CsvAmountString -> Bool
    isDigit)
        fieldrefp :: ParsecT
      HledgerParseErrorData CsvAmountString Identity CsvAmountString
    fieldrefp    = (Char -> CsvAmountString -> CsvAmountString)
    -> SimpleTextParser Char
    -> ParsecT
         HledgerParseErrorData CsvAmountString Identity CsvAmountString
    -> ParsecT
         HledgerParseErrorData CsvAmountString Identity CsvAmountString
    forall a b c.
    (a -> b -> c)
    -> ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> ParsecT HledgerParseErrorData CsvAmountString Identity b
    -> ParsecT HledgerParseErrorData CsvAmountString Identity c
    forall (f :: * -> *) a b c.
    Applicative f =>
    (a -> b -> c) -> f a -> f b -> f c
    liftA2 Char -> CsvAmountString -> CsvAmountString
    T.cons (Token CsvAmountString
    -> ParsecT
         HledgerParseErrorData
         CsvAmountString
         Identity
         (Token CsvAmountString)
    forall e s (m :: * -> *).
    (MonadParsec e s m, Token s ~ Char) =>
    Token s -> m (Token s)
    char Char
    Token CsvAmountString
    '%')  (Maybe [Char]
    -> (Token CsvAmountString -> Bool)
    -> ParsecT
         HledgerParseErrorData
         CsvAmountString
         Identity
         (Tokens CsvAmountString)
    forall e s (m :: * -> *).
    MonadParsec e s m =>
    Maybe [Char] -> (Token s -> Bool) -> m (Tokens s)
    takeWhile1P ([Char] -> Maybe [Char]
    forall a. a -> Maybe a
    Just [Char]
    "reference") Char -> Bool
    Token CsvAmountString -> Bool
    isFieldNameChar)
        isFieldNameChar :: Char -> Bool
    isFieldNameChar Char
    c = Char -> Bool
    isAlphaNum Char
    c Bool -> Bool -> Bool
    || Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    '_' Bool -> Bool -> Bool
    || Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    '-'

    -- | Replace something that looks like a Regex match group reference with the
    -- resulting match group value after applying the Regex.
    replaceRegexGroupReference :: CsvRules -> CsvRecord -> HledgerFieldName -> MatchGroupReference -> Text
    replaceRegexGroupReference :: CsvRules
    -> [CsvAmountString]
    -> CsvAmountString
    -> CsvAmountString
    -> CsvAmountString
    replaceRegexGroupReference CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    f CsvAmountString
    s = case CsvAmountString -> Maybe (Char, CsvAmountString)
    T.uncons CsvAmountString
    s of
        Just (Char
    '\\', CsvAmountString
    group) -> CsvAmountString -> Maybe CsvAmountString -> CsvAmountString
    forall a. a -> Maybe a -> a
    fromMaybe CsvAmountString
    "" (Maybe CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString -> CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ CsvRules
    -> [CsvAmountString]
    -> CsvAmountString
    -> CsvAmountString
    -> Maybe CsvAmountString
    regexMatchValue CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    f CsvAmountString
    group
        Maybe (Char, CsvAmountString)
    _                  -> CsvAmountString
    s

    regexMatchValue :: CsvRules -> CsvRecord -> HledgerFieldName -> Text -> Maybe Text
    regexMatchValue :: CsvRules
    -> [CsvAmountString]
    -> CsvAmountString
    -> CsvAmountString
    -> Maybe CsvAmountString
    regexMatchValue CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    f CsvAmountString
    sgroup = let
      matchgroups :: [CsvAmountString]
    matchgroups  = (Matcher -> [CsvAmountString]) -> [Matcher] -> [CsvAmountString]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap (CsvRules -> [CsvAmountString] -> Matcher -> [CsvAmountString]
    getMatchGroups CsvRules
    rules [CsvAmountString]
    record)
                   ([Matcher] -> [CsvAmountString]) -> [Matcher] -> [CsvAmountString]
    forall a b. (a -> b) -> a -> b
    $ (ConditionalBlock -> [Matcher]) -> [ConditionalBlock] -> [Matcher]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap ConditionalBlock -> [Matcher]
    cbMatchers
                   ([ConditionalBlock] -> [Matcher])
    -> [ConditionalBlock] -> [Matcher]
    forall a b. (a -> b) -> a -> b
    $ (ConditionalBlock -> Bool)
    -> [ConditionalBlock] -> [ConditionalBlock]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (CsvRules -> [CsvAmountString] -> ConditionalBlock -> Bool
    isBlockActive CsvRules
    rules [CsvAmountString]
    record)
                   ([ConditionalBlock] -> [ConditionalBlock])
    -> [ConditionalBlock] -> [ConditionalBlock]
    forall a b. (a -> b) -> a -> b
    $ CsvRules -> CsvAmountString -> [ConditionalBlock]
    forall a. CsvRules' a -> a
    rblocksassigning CsvRules
    rules CsvAmountString
    f
      group :: CsvFieldIndex
    group = ([Char] -> CsvFieldIndex
    forall a. Read a => [Char] -> a
    read (CsvAmountString -> [Char]
    T.unpack CsvAmountString
    sgroup) :: Int) CsvFieldIndex -> CsvFieldIndex -> CsvFieldIndex
    forall a. Num a => a -> a -> a
    - CsvFieldIndex
    1 -- adjust to 0-indexing
      in [CsvAmountString] -> CsvFieldIndex -> Maybe CsvAmountString
    forall a. [a] -> CsvFieldIndex -> Maybe a
    atMay [CsvAmountString]
    matchgroups CsvFieldIndex
    group

    getMatchGroups :: CsvRules -> CsvRecord -> Matcher -> [Text]
    getMatchGroups :: CsvRules -> [CsvAmountString] -> Matcher -> [CsvAmountString]
    getMatchGroups CsvRules
    _ [CsvAmountString]
    record (RecordMatcher MatcherPrefix
    _ Regexp
    regex)  = let
      txt :: CsvAmountString
    txt = CsvAmountString -> [CsvAmountString] -> CsvAmountString
    T.intercalate CsvAmountString
    "," [CsvAmountString]
    record -- see caveats of wholecsvline, in `isBlockActive`
      in Regexp -> CsvAmountString -> [CsvAmountString]
    regexMatchTextGroups Regexp
    regex CsvAmountString
    txt
    getMatchGroups CsvRules
    rules [CsvAmountString]
    record (FieldMatcher MatcherPrefix
    _ CsvAmountString
    fieldref Regexp
    regex) = let
      txt :: CsvAmountString
    txt = CsvRules -> [CsvAmountString] -> CsvAmountString -> CsvAmountString
    replaceCsvFieldReference CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    fieldref
      in Regexp -> CsvAmountString -> [CsvAmountString]
    regexMatchTextGroups Regexp
    regex CsvAmountString
    txt

    -- | Replace something that looks like a reference to a csv field ("%date" or "%1)
    -- with that field's value. If it doesn't look like a field reference, or if we
    -- can't find such a field, replace it with the empty string.
    replaceCsvFieldReference :: CsvRules -> CsvRecord -> CsvFieldReference -> Text
    replaceCsvFieldReference :: CsvRules -> [CsvAmountString] -> CsvAmountString -> CsvAmountString
    replaceCsvFieldReference CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    s = case CsvAmountString -> Maybe (Char, CsvAmountString)
    T.uncons CsvAmountString
    s of
        Just (Char
    '%', CsvAmountString
    fieldname) -> CsvAmountString -> Maybe CsvAmountString -> CsvAmountString
    forall a. a -> Maybe a -> a
    fromMaybe CsvAmountString
    "" (Maybe CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString -> CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    csvFieldValue CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    fieldname
        Maybe (Char, CsvAmountString)
    _                     -> CsvAmountString
    s

    -- | Get the (whitespace-stripped) value of a CSV field, identified by its name or
    -- column number, ("date" or "1"), from the given CSV record, if such a field exists.
    csvFieldValue :: CsvRules -> CsvRecord -> CsvFieldName -> Maybe Text
    csvFieldValue :: CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    csvFieldValue CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    fieldname = do
      CsvFieldIndex
    fieldindex <-
        if (Char -> Bool) -> CsvAmountString -> Bool
    T.all Char -> Bool
    isDigit CsvAmountString
    fieldname
        then [Char] -> Maybe CsvFieldIndex
    forall a. Read a => [Char] -> Maybe a
    readMay ([Char] -> Maybe CsvFieldIndex) -> [Char] -> Maybe CsvFieldIndex
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> [Char]
    T.unpack CsvAmountString
    fieldname
        else CsvAmountString
    -> [(CsvAmountString, CsvFieldIndex)] -> Maybe CsvFieldIndex
    forall a b. Eq a => a -> [(a, b)] -> Maybe b
    lookup (CsvAmountString -> CsvAmountString
    T.toLower CsvAmountString
    fieldname) ([(CsvAmountString, CsvFieldIndex)] -> Maybe CsvFieldIndex)
    -> [(CsvAmountString, CsvFieldIndex)] -> Maybe CsvFieldIndex
    forall a b. (a -> b) -> a -> b
    $ CsvRules -> [(CsvAmountString, CsvFieldIndex)]
    forall a. CsvRules' a -> [(CsvAmountString, CsvFieldIndex)]
    rcsvfieldindexes CsvRules
    rules
      CsvAmountString -> CsvAmountString
    T.strip (CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString -> Maybe CsvAmountString
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> [CsvAmountString] -> CsvFieldIndex -> Maybe CsvAmountString
    forall a. [a] -> CsvFieldIndex -> Maybe a
    atMay [CsvAmountString]
    record (CsvFieldIndex
    fieldindexCsvFieldIndex -> CsvFieldIndex -> CsvFieldIndex
    forall a. Num a => a -> a -> a
    -CsvFieldIndex
    1)

    _CSV_READING__________________________________________ :: a
    _CSV_READING__________________________________________ = a
    forall a. HasCallStack => a
    undefined

    -- | Read a Journal from the given CSV data (and filename, used for error
    -- messages), or return an error. Proceed as follows:
    --
    -- 1. Conversion rules are provided, or they are parsed from the specified
    --    rules file, or from the default rules file for the CSV data file.
    --    If rules parsing fails, or the required rules file does not exist, throw an error.
    --
    -- 2. Parse the CSV data using the rules, or throw an error.
    --
    -- 3. Convert the CSV records to hledger transactions using the rules.
    --
    -- 4. Return the transactions as a Journal.
    --
    readJournalFromCsv :: Maybe (Either CsvRules FilePath) -> FilePath -> Text -> ExceptT String IO Journal
    readJournalFromCsv :: Maybe (Either CsvRules [Char])
    -> [Char] -> CsvAmountString -> ExceptT [Char] IO Journal
    readJournalFromCsv Maybe (Either CsvRules [Char])
    Nothing [Char]
    "-" CsvAmountString
    _ = [Char] -> ExceptT [Char] IO Journal
    forall a. [Char] -> ExceptT [Char] IO a
    forall e (m :: * -> *) a. MonadError e m => e -> m a
    throwError [Char]
    "please use --rules-file when reading CSV from stdin"
    readJournalFromCsv Maybe (Either CsvRules [Char])
    merulesfile [Char]
    csvfile CsvAmountString
    csvtext = do
        -- for now, correctness is the priority here, efficiency not so much

        CsvRules
    rules <- case Maybe (Either CsvRules [Char])
    merulesfile of
          Just (Left CsvRules
    rs)         -> CsvRules -> ExceptT [Char] IO CsvRules
    forall a. a -> ExceptT [Char] IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return CsvRules
    rs
          Just (Right [Char]
    rulesfile) -> [Char] -> ExceptT [Char] IO CsvRules
    readRulesFile [Char]
    rulesfile
          Maybe (Either CsvRules [Char])
    Nothing                -> [Char] -> ExceptT [Char] IO CsvRules
    readRulesFile ([Char] -> ExceptT [Char] IO CsvRules)
    -> [Char] -> ExceptT [Char] IO CsvRules
    forall a b. (a -> b) -> a -> b
    $ [Char] -> [Char]
    rulesFileFor [Char]
    csvfile
        [Char] -> CsvRules -> ExceptT [Char] IO ()
    forall (m :: * -> *) a. (MonadIO m, Show a) => [Char] -> a -> m ()
    dbg6IO [Char]
    "csv rules" CsvRules
    rules

        -- convert the csv data to lines and remove all empty/blank lines
        let csvlines1 :: [CsvAmountString]
    csvlines1 = [Char] -> [CsvAmountString] -> [CsvAmountString]
    forall a. Show a => [Char] -> a -> a
    dbg9 [Char]
    "csvlines1" ([CsvAmountString] -> [CsvAmountString])
    -> [CsvAmountString] -> [CsvAmountString]
    forall a b. (a -> b) -> a -> b
    $ (CsvAmountString -> Bool) -> [CsvAmountString] -> [CsvAmountString]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (Bool -> Bool
    not (Bool -> Bool)
    -> (CsvAmountString -> Bool) -> CsvAmountString -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString -> Bool
    T.null (CsvAmountString -> Bool)
    -> (CsvAmountString -> CsvAmountString) -> CsvAmountString -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString -> CsvAmountString
    T.strip) ([CsvAmountString] -> [CsvAmountString])
    -> [CsvAmountString] -> [CsvAmountString]
    forall a b. (a -> b) -> a -> b
    $ [Char] -> [CsvAmountString] -> [CsvAmountString]
    forall a. Show a => [Char] -> a -> a
    dbg9 [Char]
    "csvlines0" ([CsvAmountString] -> [CsvAmountString])
    -> [CsvAmountString] -> [CsvAmountString]
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> [CsvAmountString]
    T.lines CsvAmountString
    csvtext

        -- if there is a top-level skip rule, skip the specified number of non-empty lines
        CsvFieldIndex
    skiplines <- case CsvAmountString -> CsvRules -> Maybe CsvAmountString
    getDirective CsvAmountString
    "skip" CsvRules
    rules of
                          Maybe CsvAmountString
    Nothing -> CsvFieldIndex -> ExceptT [Char] IO CsvFieldIndex
    forall a. a -> ExceptT [Char] IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return CsvFieldIndex
    0
                          Just CsvAmountString
    "" -> CsvFieldIndex -> ExceptT [Char] IO CsvFieldIndex
    forall a. a -> ExceptT [Char] IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return CsvFieldIndex
    1
                          Just CsvAmountString
    s  -> ExceptT [Char] IO CsvFieldIndex
    -> (CsvFieldIndex -> ExceptT [Char] IO CsvFieldIndex)
    -> Maybe CsvFieldIndex
    -> ExceptT [Char] IO CsvFieldIndex
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe ([Char] -> ExceptT [Char] IO CsvFieldIndex
    forall a. [Char] -> ExceptT [Char] IO a
    forall e (m :: * -> *) a. MonadError e m => e -> m a
    throwError ([Char] -> ExceptT [Char] IO CsvFieldIndex)
    -> [Char] -> ExceptT [Char] IO CsvFieldIndex
    forall a b. (a -> b) -> a -> b
    $ [Char]
    "could not parse skip value: " [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ CsvAmountString -> [Char]
    forall a. Show a => a -> [Char]
    show CsvAmountString
    s) CsvFieldIndex -> ExceptT [Char] IO CsvFieldIndex
    forall a. a -> ExceptT [Char] IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe CsvFieldIndex -> ExceptT [Char] IO CsvFieldIndex)
    -> ([Char] -> Maybe CsvFieldIndex)
    -> [Char]
    -> ExceptT [Char] IO CsvFieldIndex
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Char] -> Maybe CsvFieldIndex
    forall a. Read a => [Char] -> Maybe a
    readMay ([Char] -> ExceptT [Char] IO CsvFieldIndex)
    -> [Char] -> ExceptT [Char] IO CsvFieldIndex
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> [Char]
    T.unpack CsvAmountString
    s
        let csvlines2 :: [CsvAmountString]
    csvlines2 = [Char] -> [CsvAmountString] -> [CsvAmountString]
    forall a. Show a => [Char] -> a -> a
    dbg9 [Char]
    "csvlines2" ([CsvAmountString] -> [CsvAmountString])
    -> [CsvAmountString] -> [CsvAmountString]
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [CsvAmountString] -> [CsvAmountString]
    forall a. CsvFieldIndex -> [a] -> [a]
    drop CsvFieldIndex
    skiplines [CsvAmountString]
    csvlines1

        -- convert back to text and parse as csv records
        let
          csvtext1 :: CsvAmountString
    csvtext1 = [CsvAmountString] -> CsvAmountString
    T.unlines [CsvAmountString]
    csvlines2
          separator :: Char
    separator =
            case CsvAmountString -> CsvRules -> Maybe CsvAmountString
    getDirective CsvAmountString
    "separator" CsvRules
    rules Maybe CsvAmountString
    -> (CsvAmountString -> Maybe Char) -> Maybe Char
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= CsvAmountString -> Maybe Char
    parseSeparator of
              Just Char
    c           -> Char
    c
              Maybe Char
    _ | [Char]
    ext [Char] -> [Char] -> Bool
    forall a. Eq a => a -> a -> Bool
    == [Char]
    "ssv" -> Char
    ';'
              Maybe Char
    _ | [Char]
    ext [Char] -> [Char] -> Bool
    forall a. Eq a => a -> a -> Bool
    == [Char]
    "tsv" -> Char
    '\t'
              Maybe Char
    _                -> Char
    ','
              where
                ext :: [Char]
    ext = (Char -> Char) -> [Char] -> [Char]
    forall a b. (a -> b) -> [a] -> [b]
    map Char -> Char
    toLower ([Char] -> [Char]) -> [Char] -> [Char]
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [Char] -> [Char]
    forall a. CsvFieldIndex -> [a] -> [a]
    drop CsvFieldIndex
    1 ([Char] -> [Char]) -> [Char] -> [Char]
    forall a b. (a -> b) -> a -> b
    $ [Char] -> [Char]
    takeExtension [Char]
    csvfile
          -- parsec seemed to fail if you pass it "-" here   -- TODO: try again with megaparsec
          parsecfilename :: [Char]
    parsecfilename = if [Char]
    csvfile [Char] -> [Char] -> Bool
    forall a. Eq a => a -> a -> Bool
    == [Char]
    "-" then [Char]
    "(stdin)" else [Char]
    csvfile
        [Char] -> Char -> ExceptT [Char] IO ()
    forall (m :: * -> *) a. (MonadIO m, Show a) => [Char] -> a -> m ()
    dbg6IO [Char]
    "using separator" Char
    separator
        -- parse csv records
        [[CsvAmountString]]
    csvrecords0 <- [Char] -> [[CsvAmountString]] -> [[CsvAmountString]]
    forall a. Show a => [Char] -> a -> a
    dbg7 [Char]
    "parseCsv" ([[CsvAmountString]] -> [[CsvAmountString]])
    -> ExceptT [Char] IO [[CsvAmountString]]
    -> ExceptT [Char] IO [[CsvAmountString]]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Char
    -> [Char]
    -> CsvAmountString
    -> ExceptT [Char] IO [[CsvAmountString]]
    parseCsv Char
    separator [Char]
    parsecfilename CsvAmountString
    csvtext1
        -- remove any records skipped by conditional skip or end rules
        let csvrecords1 :: [[CsvAmountString]]
    csvrecords1 = CsvRules -> [[CsvAmountString]] -> [[CsvAmountString]]
    applyConditionalSkips CsvRules
    rules [[CsvAmountString]]
    csvrecords0
        -- and check the remaining records for any obvious problems
        [[CsvAmountString]]
    csvrecords <- Either [Char] [[CsvAmountString]]
    -> ExceptT [Char] IO [[CsvAmountString]]
    forall e (m :: * -> *) a. MonadError e m => Either e a -> m a
    liftEither (Either [Char] [[CsvAmountString]]
     -> ExceptT [Char] IO [[CsvAmountString]])
    -> Either [Char] [[CsvAmountString]]
    -> ExceptT [Char] IO [[CsvAmountString]]
    forall a b. (a -> b) -> a -> b
    $ [Char] -> [[CsvAmountString]] -> [[CsvAmountString]]
    forall a. Show a => [Char] -> a -> a
    dbg7 [Char]
    "validateCsv" ([[CsvAmountString]] -> [[CsvAmountString]])
    -> Either [Char] [[CsvAmountString]]
    -> Either [Char] [[CsvAmountString]]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> [[CsvAmountString]] -> Either [Char] [[CsvAmountString]]
    validateCsv [[CsvAmountString]]
    csvrecords1
        [Char] -> [[CsvAmountString]] -> ExceptT [Char] IO ()
    forall (m :: * -> *) a. (MonadIO m, Show a) => [Char] -> a -> m ()
    dbg6IO [Char]
    "first 3 csv records" ([[CsvAmountString]] -> ExceptT [Char] IO ())
    -> [[CsvAmountString]] -> ExceptT [Char] IO ()
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [[CsvAmountString]] -> [[CsvAmountString]]
    forall a. CsvFieldIndex -> [a] -> [a]
    take CsvFieldIndex
    3 [[CsvAmountString]]
    csvrecords

        -- XXX identify header lines some day ?
        -- let (headerlines, datalines) = identifyHeaderLines csvrecords'
        --     mfieldnames = lastMay headerlines

        TimeZone
    tzout <- IO TimeZone -> ExceptT [Char] IO TimeZone
    forall a. IO a -> ExceptT [Char] IO a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO TimeZone
    getCurrentTimeZone
        Maybe TimeZone
    mtzin <- case CsvAmountString -> CsvRules -> Maybe CsvAmountString
    getDirective CsvAmountString
    "timezone" CsvRules
    rules of
                  Maybe CsvAmountString
    Nothing -> Maybe TimeZone -> ExceptT [Char] IO (Maybe TimeZone)
    forall a. a -> ExceptT [Char] IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe TimeZone
    forall a. Maybe a
    Nothing
                  Just CsvAmountString
    s  ->
                    ExceptT [Char] IO (Maybe TimeZone)
    -> (TimeZone -> ExceptT [Char] IO (Maybe TimeZone))
    -> Maybe TimeZone
    -> ExceptT [Char] IO (Maybe TimeZone)
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe ([Char] -> ExceptT [Char] IO (Maybe TimeZone)
    forall a. [Char] -> ExceptT [Char] IO a
    forall e (m :: * -> *) a. MonadError e m => e -> m a
    throwError ([Char] -> ExceptT [Char] IO (Maybe TimeZone))
    -> [Char] -> ExceptT [Char] IO (Maybe TimeZone)
    forall a b. (a -> b) -> a -> b
    $ [Char]
    "could not parse time zone: " [Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ CsvAmountString -> [Char]
    T.unpack CsvAmountString
    s) (Maybe TimeZone -> ExceptT [Char] IO (Maybe TimeZone)
    forall a. a -> ExceptT [Char] IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return(Maybe TimeZone -> ExceptT [Char] IO (Maybe TimeZone))
    -> (TimeZone -> Maybe TimeZone)
    -> TimeZone
    -> ExceptT [Char] IO (Maybe TimeZone)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .TimeZone -> Maybe TimeZone
    forall a. a -> Maybe a
    Just) (Maybe TimeZone -> ExceptT [Char] IO (Maybe TimeZone))
    -> Maybe TimeZone -> ExceptT [Char] IO (Maybe TimeZone)
    forall a b. (a -> b) -> a -> b
    $
                    Bool -> TimeLocale -> [Char] -> [Char] -> Maybe TimeZone
    forall (m :: * -> *) t.
    (MonadFail m, ParseTime t) =>
    Bool -> TimeLocale -> [Char] -> [Char] -> m t
    parseTimeM Bool
    False TimeLocale
    defaultTimeLocale [Char]
    "%Z" ([Char] -> Maybe TimeZone) -> [Char] -> Maybe TimeZone
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> [Char]
    T.unpack CsvAmountString
    s
        let
          -- convert CSV records to transactions, saving the CSV line numbers for error positions
          txns :: [Transaction]
    txns = [Char] -> [Transaction] -> [Transaction]
    forall a. Show a => [Char] -> a -> a
    dbg7 [Char]
    "csv txns" ([Transaction] -> [Transaction]) -> [Transaction] -> [Transaction]
    forall a b. (a -> b) -> a -> b
    $ (SourcePos, [Transaction]) -> [Transaction]
    forall a b. (a, b) -> b
    snd ((SourcePos, [Transaction]) -> [Transaction])
    -> (SourcePos, [Transaction]) -> [Transaction]
    forall a b. (a -> b) -> a -> b
    $ (SourcePos -> [CsvAmountString] -> (SourcePos, Transaction))
    -> SourcePos -> [[CsvAmountString]] -> (SourcePos, [Transaction])
    forall (t :: * -> *) s a b.
    Traversable t =>
    (s -> a -> (s, b)) -> s -> t a -> (s, t b)
    mapAccumL
                         (\SourcePos
    pos [CsvAmountString]
    r ->
                            let
                              SourcePos [Char]
    name Pos
    line Pos
    col = SourcePos
    pos
                              line' :: Pos
    line' = (CsvFieldIndex -> Pos
    mkPos (CsvFieldIndex -> Pos) -> (Pos -> CsvFieldIndex) -> Pos -> Pos
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (CsvFieldIndex -> CsvFieldIndex -> CsvFieldIndex
    forall a. Num a => a -> a -> a
    +CsvFieldIndex
    1) (CsvFieldIndex -> CsvFieldIndex)
    -> (Pos -> CsvFieldIndex) -> Pos -> CsvFieldIndex
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Pos -> CsvFieldIndex
    unPos) Pos
    line
                              pos' :: SourcePos
    pos' = [Char] -> Pos -> Pos -> SourcePos
    SourcePos [Char]
    name Pos
    line' Pos
    col
                            in
                              (SourcePos
    pos', Bool
    -> Maybe TimeZone
    -> TimeZone
    -> SourcePos
    -> CsvRules
    -> [CsvAmountString]
    -> Transaction
    transactionFromCsvRecord Bool
    timesarezoned Maybe TimeZone
    mtzin TimeZone
    tzout SourcePos
    pos CsvRules
    rules [CsvAmountString]
    r)
                         )
                         ([Char] -> SourcePos
    initialPos [Char]
    parsecfilename) [[CsvAmountString]]
    csvrecords
            where
              timesarezoned :: Bool
    timesarezoned =
                case CsvRules -> CsvAmountString -> Maybe CsvAmountString
    csvRule CsvRules
    rules CsvAmountString
    "date-format" of
                  Just CsvAmountString
    f | (CsvAmountString -> Bool) -> [CsvAmountString] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any (CsvAmountString -> CsvAmountString -> Bool
    `T.isInfixOf` CsvAmountString
    f) [CsvAmountString
    "%Z",CsvAmountString
    "%z",CsvAmountString
    "%EZ",CsvAmountString
    "%Ez"] -> Bool
    True
                  Maybe CsvAmountString
    _ -> Bool
    False

          -- Do our best to ensure transactions will be ordered chronologically,
          -- from oldest to newest. This is done in several steps:
          -- 1. Intra-day order: if there's an "intra-day-reversed" rule,
          -- assume each day's CSV records were ordered in reverse of the overall date order,
          -- so reverse each day's txns.
          intradayreversed :: Bool
    intradayreversed = [Char] -> Bool -> Bool
    forall a. Show a => [Char] -> a -> a
    dbg6 [Char]
    "intra-day-reversed" (Bool -> Bool) -> Bool -> Bool
    forall a b. (a -> b) -> a -> b
    $ Maybe CsvAmountString -> Bool
    forall a. Maybe a -> Bool
    isJust (Maybe CsvAmountString -> Bool) -> Maybe CsvAmountString -> Bool
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> CsvRules -> Maybe CsvAmountString
    getDirective CsvAmountString
    "intra-day-reversed" CsvRules
    rules
          txns1 :: [Transaction]
    txns1 = [Char] -> [Transaction] -> [Transaction]
    forall a. Show a => [Char] -> a -> a
    dbg7 [Char]
    "txns1" ([Transaction] -> [Transaction]) -> [Transaction] -> [Transaction]
    forall a b. (a -> b) -> a -> b
    $
            (if Bool
    intradayreversed then ([Transaction] -> [Transaction])
    -> [[Transaction]] -> [Transaction]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap [Transaction] -> [Transaction]
    forall a. [a] -> [a]
    reverse ([[Transaction]] -> [Transaction])
    -> ([Transaction] -> [[Transaction]])
    -> [Transaction]
    -> [Transaction]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Transaction -> Day) -> [Transaction] -> [[Transaction]]
    forall k a. Eq k => (a -> k) -> [a] -> [[a]]
    groupOn Transaction -> Day
    tdate else [Transaction] -> [Transaction]
    forall a. a -> a
    id) [Transaction]
    txns
          -- 2. Overall date order: now if there's a "newest-first" rule,
          -- or if there's multiple dates and the first is more recent than the last,
          -- assume CSV records were ordered newest dates first,
          -- so reverse all txns.
          newestfirst :: Bool
    newestfirst = [Char] -> Bool -> Bool
    forall a. Show a => [Char] -> a -> a
    dbg6 [Char]
    "newest-first" (Bool -> Bool) -> Bool -> Bool
    forall a b. (a -> b) -> a -> b
    $ Maybe CsvAmountString -> Bool
    forall a. Maybe a -> Bool
    isJust (Maybe CsvAmountString -> Bool) -> Maybe CsvAmountString -> Bool
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> CsvRules -> Maybe CsvAmountString
    getDirective CsvAmountString
    "newest-first" CsvRules
    rules
          mdatalooksnewestfirst :: Maybe Bool
    mdatalooksnewestfirst = [Char] -> Maybe Bool -> Maybe Bool
    forall a. Show a => [Char] -> a -> a
    dbg6 [Char]
    "mdatalooksnewestfirst" (Maybe Bool -> Maybe Bool) -> Maybe Bool -> Maybe Bool
    forall a b. (a -> b) -> a -> b
    $
            case [Day] -> [Day]
    forall a. Eq a => [a] -> [a]
    nub ([Day] -> [Day]) -> [Day] -> [Day]
    forall a b. (a -> b) -> a -> b
    $ (Transaction -> Day) -> [Transaction] -> [Day]
    forall a b. (a -> b) -> [a] -> [b]
    map Transaction -> Day
    tdate [Transaction]
    txns of
              [Day]
    ds | [Day] -> CsvFieldIndex
    forall a. [a] -> CsvFieldIndex
    forall (t :: * -> *) a. Foldable t => t a -> CsvFieldIndex
    length [Day]
    ds CsvFieldIndex -> CsvFieldIndex -> Bool
    forall a. Ord a => a -> a -> Bool
    > CsvFieldIndex
    1 -> Bool -> Maybe Bool
    forall a. a -> Maybe a
    Just (Bool -> Maybe Bool) -> Bool -> Maybe Bool
    forall a b. (a -> b) -> a -> b
    $ [Day] -> Day
    forall a. HasCallStack => [a] -> a
    head [Day]
    ds Day -> Day -> Bool
    forall a. Ord a => a -> a -> Bool
    > [Day] -> Day
    forall a. HasCallStack => [a] -> a
    last [Day]
    ds
              [Day]
    _                  -> Maybe Bool
    forall a. Maybe a
    Nothing
          txns2 :: [Transaction]
    txns2 = [Char] -> [Transaction] -> [Transaction]
    forall a. Show a => [Char] -> a -> a
    dbg7 [Char]
    "txns2" ([Transaction] -> [Transaction]) -> [Transaction] -> [Transaction]
    forall a b. (a -> b) -> a -> b
    $
            (if Bool
    newestfirst Bool -> Bool -> Bool
    || Maybe Bool
    mdatalooksnewestfirst Maybe Bool -> Maybe Bool -> Bool
    forall a. Eq a => a -> a -> Bool
    == Bool -> Maybe Bool
    forall a. a -> Maybe a
    Just Bool
    True then [Transaction] -> [Transaction]
    forall a. [a] -> [a]
    reverse else [Transaction] -> [Transaction]
    forall a. a -> a
    id) [Transaction]
    txns1
          -- 3. Disordered dates: in case the CSV records were ordered by chaos,
          -- do a final sort by date. If it was only a few records out of order,
          -- this will hopefully refine any good ordering done by steps 1 and 2.
          txns3 :: [Transaction]
    txns3 = [Char] -> [Transaction] -> [Transaction]
    forall a. Show a => [Char] -> a -> a
    dbg7 [Char]
    "date-sorted csv txns" ([Transaction] -> [Transaction]) -> [Transaction] -> [Transaction]
    forall a b. (a -> b) -> a -> b
    $ (Transaction -> Day) -> [Transaction] -> [Transaction]
    forall b a. Ord b => (a -> b) -> [a] -> [a]
    sortOn Transaction -> Day
    tdate [Transaction]
    txns2

        Journal -> ExceptT [Char] IO Journal
    forall a. a -> ExceptT [Char] IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Journal
    nulljournal{jtxns=txns3}

    -- | Parse special separator names TAB and SPACE, or return the first
    -- character. Return Nothing on empty string
    parseSeparator :: Text -> Maybe Char
    parseSeparator :: CsvAmountString -> Maybe Char
    parseSeparator = CsvAmountString -> Maybe Char
    specials (CsvAmountString -> Maybe Char)
    -> (CsvAmountString -> CsvAmountString)
    -> CsvAmountString
    -> Maybe Char
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString -> CsvAmountString
    T.toLower
      where specials :: CsvAmountString -> Maybe Char
    specials CsvAmountString
    "space" = Char -> Maybe Char
    forall a. a -> Maybe a
    Just Char
    ' '
            specials CsvAmountString
    "tab"   = Char -> Maybe Char
    forall a. a -> Maybe a
    Just Char
    '\t'
            specials CsvAmountString
    xs      = (Char, CsvAmountString) -> Char
    forall a b. (a, b) -> a
    fst ((Char, CsvAmountString) -> Char)
    -> Maybe (Char, CsvAmountString) -> Maybe Char
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CsvAmountString -> Maybe (Char, CsvAmountString)
    T.uncons CsvAmountString
    xs

    -- Call parseCassava on a file or stdin, converting the result to ExceptT.
    parseCsv :: Char -> FilePath -> Text -> ExceptT String IO [CsvRecord]
    parseCsv :: Char
    -> [Char]
    -> CsvAmountString
    -> ExceptT [Char] IO [[CsvAmountString]]
    parseCsv Char
    separator [Char]
    filePath CsvAmountString
    csvtext = IO (Either [Char] [[CsvAmountString]])
    -> ExceptT [Char] IO [[CsvAmountString]]
    forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
    ExceptT (IO (Either [Char] [[CsvAmountString]])
     -> ExceptT [Char] IO [[CsvAmountString]])
    -> IO (Either [Char] [[CsvAmountString]])
    -> ExceptT [Char] IO [[CsvAmountString]]
    forall a b. (a -> b) -> a -> b
    $
      case [Char]
    filePath of
        [Char]
    "-" -> Char
    -> [Char] -> CsvAmountString -> Either [Char] [[CsvAmountString]]
    parseCassava Char
    separator [Char]
    "(stdin)" (CsvAmountString -> Either [Char] [[CsvAmountString]])
    -> IO CsvAmountString -> IO (Either [Char] [[CsvAmountString]])
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> IO CsvAmountString
    T.getContents
        [Char]
    _   -> Either [Char] [[CsvAmountString]]
    -> IO (Either [Char] [[CsvAmountString]])
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Either [Char] [[CsvAmountString]]
     -> IO (Either [Char] [[CsvAmountString]]))
    -> Either [Char] [[CsvAmountString]]
    -> IO (Either [Char] [[CsvAmountString]])
    forall a b. (a -> b) -> a -> b
    $ if CsvAmountString -> Bool
    T.null CsvAmountString
    csvtext then [[CsvAmountString]] -> Either [Char] [[CsvAmountString]]
    forall a b. b -> Either a b
    Right [[CsvAmountString]]
    forall a. Monoid a => a
    mempty else Char
    -> [Char] -> CsvAmountString -> Either [Char] [[CsvAmountString]]
    parseCassava Char
    separator [Char]
    filePath CsvAmountString
    csvtext

    -- Parse text into CSV records, using Cassava and the given field separator.
    parseCassava :: Char -> FilePath -> Text -> Either String [CsvRecord]
    parseCassava :: Char
    -> [Char] -> CsvAmountString -> Either [Char] [[CsvAmountString]]
    parseCassava Char
    separator [Char]
    path CsvAmountString
    content =
      -- XXX we now remove all blank lines before parsing; will Cassava will still produce [""] records ?
      -- filter (/=[""])
      (ParseErrorBundle ByteString ConversionError
     -> Either [Char] [[CsvAmountString]])
    -> (Vector (Vector ByteString)
        -> Either [Char] [[CsvAmountString]])
    -> Either
         (ParseErrorBundle ByteString ConversionError)
         (Vector (Vector ByteString))
    -> Either [Char] [[CsvAmountString]]
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either ([Char] -> Either [Char] [[CsvAmountString]]
    forall a b. a -> Either a b
    Left ([Char] -> Either [Char] [[CsvAmountString]])
    -> (ParseErrorBundle ByteString ConversionError -> [Char])
    -> ParseErrorBundle ByteString ConversionError
    -> Either [Char] [[CsvAmountString]]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ParseErrorBundle ByteString ConversionError -> [Char]
    forall s e.
    (VisualStream s, TraversableStream s, ShowErrorComponent e) =>
    ParseErrorBundle s e -> [Char]
    errorBundlePretty) ([[CsvAmountString]] -> Either [Char] [[CsvAmountString]]
    forall a b. b -> Either a b
    Right ([[CsvAmountString]] -> Either [Char] [[CsvAmountString]])
    -> (Vector (Vector ByteString) -> [[CsvAmountString]])
    -> Vector (Vector ByteString)
    -> Either [Char] [[CsvAmountString]]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Vector (Vector ByteString) -> [[CsvAmountString]]
    forall (t :: * -> *).
    (Foldable t, Functor t) =>
    t (t ByteString) -> [[CsvAmountString]]
    parseResultToCsv) (Either
       (ParseErrorBundle ByteString ConversionError)
       (Vector (Vector ByteString))
     -> Either [Char] [[CsvAmountString]])
    -> (ByteString
        -> Either
             (ParseErrorBundle ByteString ConversionError)
             (Vector (Vector ByteString)))
    -> ByteString
    -> Either [Char] [[CsvAmountString]]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$>
      DecodeOptions
    -> HasHeader
    -> [Char]
    -> ByteString
    -> Either
         (ParseErrorBundle ByteString ConversionError)
         (Vector (Vector ByteString))
    forall a.
    FromRecord a =>
    DecodeOptions
    -> HasHeader
    -> [Char]
    -> ByteString
    -> Either (ParseErrorBundle ByteString ConversionError) (Vector a)
    CassavaMegaparsec.decodeWith DecodeOptions
    decodeOptions HasHeader
    Cassava.NoHeader [Char]
    path (ByteString -> Either [Char] [[CsvAmountString]])
    -> ByteString -> Either [Char] [[CsvAmountString]]
    forall a b. (a -> b) -> a -> b
    $
      ByteString -> ByteString
    BL.fromStrict (ByteString -> ByteString) -> ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> ByteString
    T.encodeUtf8 CsvAmountString
    content
      where
        decodeOptions :: DecodeOptions
    decodeOptions = DecodeOptions
    Cassava.defaultDecodeOptions {
                          Cassava.decDelimiter = fromIntegral (ord separator)
                        }
        parseResultToCsv :: (Foldable t, Functor t) => t (t B.ByteString) -> [CsvRecord]
        parseResultToCsv :: forall (t :: * -> *).
    (Foldable t, Functor t) =>
    t (t ByteString) -> [[CsvAmountString]]
    parseResultToCsv = t (t CsvAmountString) -> [[CsvAmountString]]
    forall {a}. t (t a) -> [[a]]
    toListList (t (t CsvAmountString) -> [[CsvAmountString]])
    -> (t (t ByteString) -> t (t CsvAmountString))
    -> t (t ByteString)
    -> [[CsvAmountString]]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . t (t ByteString) -> t (t CsvAmountString)
    unpackFields
          where
            toListList :: t (t a) -> [[a]]
    toListList = t [a] -> [[a]]
    forall a. t a -> [a]
    forall (t :: * -> *) a. Foldable t => t a -> [a]
    toList (t [a] -> [[a]]) -> (t (t a) -> t [a]) -> t (t a) -> [[a]]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (t a -> [a]) -> t (t a) -> t [a]
    forall a b. (a -> b) -> t a -> t b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap t a -> [a]
    forall a. t a -> [a]
    forall (t :: * -> *) a. Foldable t => t a -> [a]
    toList
            unpackFields :: t (t ByteString) -> t (t CsvAmountString)
    unpackFields  = ((t ByteString -> t CsvAmountString)
    -> t (t ByteString) -> t (t CsvAmountString)
    forall a b. (a -> b) -> t a -> t b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((t ByteString -> t CsvAmountString)
     -> t (t ByteString) -> t (t CsvAmountString))
    -> ((ByteString -> CsvAmountString)
        -> t ByteString -> t CsvAmountString)
    -> (ByteString -> CsvAmountString)
    -> t (t ByteString)
    -> t (t CsvAmountString)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ByteString -> CsvAmountString)
    -> t ByteString -> t CsvAmountString
    forall a b. (a -> b) -> t a -> t b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap) ByteString -> CsvAmountString
    T.decodeUtf8

    -- | Scan for csv records where a conditional `skip` or `end` rule applies,
    -- and apply that rule, removing one or more following records.
    applyConditionalSkips :: CsvRules -> [CsvRecord] -> [CsvRecord]
    applyConditionalSkips :: CsvRules -> [[CsvAmountString]] -> [[CsvAmountString]]
    applyConditionalSkips CsvRules
    _ [] = []
    applyConditionalSkips CsvRules
    rules ([CsvAmountString]
    r:[[CsvAmountString]]
    rest) =
      case [CsvAmountString] -> Maybe CsvFieldIndex
    forall {a}.
    (Bounded a, Num a, Read a) =>
    [CsvAmountString] -> Maybe a
    skipnum [CsvAmountString]
    r of
        Maybe CsvFieldIndex
    Nothing -> [CsvAmountString]
    r [CsvAmountString] -> [[CsvAmountString]] -> [[CsvAmountString]]
    forall a. a -> [a] -> [a]
    : CsvRules -> [[CsvAmountString]] -> [[CsvAmountString]]
    applyConditionalSkips CsvRules
    rules [[CsvAmountString]]
    rest
        Just CsvFieldIndex
    cnt -> CsvRules -> [[CsvAmountString]] -> [[CsvAmountString]]
    applyConditionalSkips CsvRules
    rules ([[CsvAmountString]] -> [[CsvAmountString]])
    -> [[CsvAmountString]] -> [[CsvAmountString]]
    forall a b. (a -> b) -> a -> b
    $ CsvFieldIndex -> [[CsvAmountString]] -> [[CsvAmountString]]
    forall a. CsvFieldIndex -> [a] -> [a]
    drop (CsvFieldIndex
    cntCsvFieldIndex -> CsvFieldIndex -> CsvFieldIndex
    forall a. Num a => a -> a -> a
    -CsvFieldIndex
    1) [[CsvAmountString]]
    rest
      where
        skipnum :: [CsvAmountString] -> Maybe a
    skipnum [CsvAmountString]
    r1 =
          case (CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    getEffectiveAssignment CsvRules
    rules [CsvAmountString]
    r1 CsvAmountString
    "end", CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    getEffectiveAssignment CsvRules
    rules [CsvAmountString]
    r1 CsvAmountString
    "skip") of
            (Maybe CsvAmountString
    Nothing, Maybe CsvAmountString
    Nothing) -> Maybe a
    forall a. Maybe a
    Nothing
            (Just CsvAmountString
    _, Maybe CsvAmountString
    _) -> a -> Maybe a
    forall a. a -> Maybe a
    Just a
    forall a. Bounded a => a
    maxBound
            (Maybe CsvAmountString
    Nothing, Just CsvAmountString
    "") -> a -> Maybe a
    forall a. a -> Maybe a
    Just a
    1
            (Maybe CsvAmountString
    Nothing, Just CsvAmountString
    x) -> a -> Maybe a
    forall a. a -> Maybe a
    Just ([Char] -> a
    forall a. Read a => [Char] -> a
    read ([Char] -> a) -> [Char] -> a
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> [Char]
    T.unpack CsvAmountString
    x)

    -- | Do some validation on the parsed CSV records:
    -- check that they all have at least two fields.
    validateCsv :: [CsvRecord] -> Either String [CsvRecord]
    validateCsv :: [[CsvAmountString]] -> Either [Char] [[CsvAmountString]]
    validateCsv [] = [[CsvAmountString]] -> Either [Char] [[CsvAmountString]]
    forall a b. b -> Either a b
    Right []
    validateCsv rs :: [[CsvAmountString]]
    rs@([CsvAmountString]
    _first:[[CsvAmountString]]
    _) =
      case Maybe [CsvAmountString]
    lessthan2 of
        Just [CsvAmountString]
    r  -> [Char] -> Either [Char] [[CsvAmountString]]
    forall a b. a -> Either a b
    Left ([Char] -> Either [Char] [[CsvAmountString]])
    -> [Char] -> Either [Char] [[CsvAmountString]]
    forall a b. (a -> b) -> a -> b
    $ [Char] -> [Char] -> [Char]
    forall r. PrintfType r => [Char] -> r
    printf [Char]
    "CSV record %s has less than two fields" ([CsvAmountString] -> [Char]
    forall a. Show a => a -> [Char]
    show [CsvAmountString]
    r)
        Maybe [CsvAmountString]
    Nothing -> [[CsvAmountString]] -> Either [Char] [[CsvAmountString]]
    forall a b. b -> Either a b
    Right [[CsvAmountString]]
    rs
      where
        lessthan2 :: Maybe [CsvAmountString]
    lessthan2 = [[CsvAmountString]] -> Maybe [CsvAmountString]
    forall a. [a] -> Maybe a
    headMay ([[CsvAmountString]] -> Maybe [CsvAmountString])
    -> [[CsvAmountString]] -> Maybe [CsvAmountString]
    forall a b. (a -> b) -> a -> b
    $ ([CsvAmountString] -> Bool)
    -> [[CsvAmountString]] -> [[CsvAmountString]]
    forall a. (a -> Bool) -> [a] -> [a]
    filter ((CsvFieldIndex -> CsvFieldIndex -> Bool
    forall a. Ord a => a -> a -> Bool
    <CsvFieldIndex
    2)(CsvFieldIndex -> Bool)
    -> ([CsvAmountString] -> CsvFieldIndex)
    -> [CsvAmountString]
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .[CsvAmountString] -> CsvFieldIndex
    forall a. [a] -> CsvFieldIndex
    forall (t :: * -> *) a. Foldable t => t a -> CsvFieldIndex
    length) [[CsvAmountString]]
    rs

    -- -- | The highest (0-based) field index referenced in the field
    -- -- definitions, or -1 if no fields are defined.
    -- maxFieldIndex :: CsvRules -> Int
    -- maxFieldIndex r = maximumDef (-1) $ catMaybes [
    --                    dateField r
    --                   ,statusField r
    --                   ,codeField r
    --                   ,amountField r
    --                   ,amountInField r
    --                   ,amountOutField r
    --                   ,currencyField r
    --                   ,accountField r
    --                   ,account2Field r
    --                   ,date2Field r
    --                   ]

    --- ** converting csv records to transactions

    transactionFromCsvRecord :: Bool -> Maybe TimeZone -> TimeZone -> SourcePos -> CsvRules -> CsvRecord -> Transaction
    transactionFromCsvRecord :: Bool
    -> Maybe TimeZone
    -> TimeZone
    -> SourcePos
    -> CsvRules
    -> [CsvAmountString]
    -> Transaction
    transactionFromCsvRecord Bool
    timesarezoned Maybe TimeZone
    mtzin TimeZone
    tzout SourcePos
    sourcepos CsvRules
    rules [CsvAmountString]
    record = Transaction
    t
      where
        ----------------------------------------------------------------------
        -- 1. Define some helpers:

        rule :: CsvAmountString -> Maybe CsvAmountString
    rule     = CsvRules -> CsvAmountString -> Maybe CsvAmountString
    csvRule           CsvRules
    rules        :: DirectiveName    -> Maybe FieldTemplate
        -- ruleval  = csvRuleValue      rules record :: DirectiveName    -> Maybe String
        field :: CsvAmountString -> Maybe CsvAmountString
    field    = CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    hledgerField      CsvRules
    rules [CsvAmountString]
    record :: HledgerFieldName -> Maybe FieldTemplate
        fieldval :: CsvAmountString -> Maybe CsvAmountString
    fieldval = CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    hledgerFieldValue CsvRules
    rules [CsvAmountString]
    record :: HledgerFieldName -> Maybe Text
        mdateformat :: Maybe CsvAmountString
    mdateformat = CsvAmountString -> Maybe CsvAmountString
    rule CsvAmountString
    "date-format"
        parsedate :: CsvAmountString -> Maybe Day
    parsedate = Bool
    -> Maybe TimeZone
    -> TimeZone
    -> Maybe CsvAmountString
    -> CsvAmountString
    -> Maybe Day
    parseDateWithCustomOrDefaultFormats Bool
    timesarezoned Maybe TimeZone
    mtzin TimeZone
    tzout Maybe CsvAmountString
    mdateformat
        mkdateerror :: CsvAmountString
    -> CsvAmountString -> Maybe CsvAmountString -> [Char]
    mkdateerror CsvAmountString
    datefield CsvAmountString
    datevalue Maybe CsvAmountString
    mdateformat' = CsvAmountString -> [Char]
    T.unpack (CsvAmountString -> [Char]) -> CsvAmountString -> [Char]
    forall a b. (a -> b) -> a -> b
    $ [CsvAmountString] -> CsvAmountString
    T.unlines
          [CsvAmountString
    "error: could not parse \""CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    datevalueCsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    "\" as a date using date format "
            CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    -> (CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString
    -> CsvAmountString
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe CsvAmountString
    "\"YYYY/M/D\", \"YYYY-M-D\" or \"YYYY.M.D\"" ([Char] -> CsvAmountString
    T.pack ([Char] -> CsvAmountString)
    -> (CsvAmountString -> [Char])
    -> CsvAmountString
    -> CsvAmountString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString -> [Char]
    forall a. Show a => a -> [Char]
    show) Maybe CsvAmountString
    mdateformat'
          ,[CsvAmountString] -> CsvAmountString
    showRecord [CsvAmountString]
    record
          ,CsvAmountString
    "the "CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    datefieldCsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    " rule is:   "CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>(CsvAmountString -> Maybe CsvAmountString -> CsvAmountString
    forall a. a -> Maybe a -> a
    fromMaybe CsvAmountString
    "required, but missing" (Maybe CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString -> CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> Maybe CsvAmountString
    field CsvAmountString
    datefield)
          ,CsvAmountString
    "the date-format is: "CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString -> Maybe CsvAmountString -> CsvAmountString
    forall a. a -> Maybe a -> a
    fromMaybe CsvAmountString
    "unspecified" Maybe CsvAmountString
    mdateformat'
          ,CsvAmountString
    "you may need to "
            CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    "change your "CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    datefieldCsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    " rule, "
            CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    -> (CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString
    -> CsvAmountString
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe CsvAmountString
    "add a" (CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a b. a -> b -> a
    const CsvAmountString
    "change your") Maybe CsvAmountString
    mdateformat'CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    " date-format rule, "
            CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    "or "CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    -> (CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString
    -> CsvAmountString
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe CsvAmountString
    "add a" (CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a b. a -> b -> a
    const CsvAmountString
    "change your") Maybe CsvAmountString
    mskipCsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    " skip rule"
          ,CsvAmountString
    "for m/d/y or d/m/y dates, use date-format %-m/%-d/%Y or date-format %-d/%-m/%Y"
          ]
          where
            mskip :: Maybe CsvAmountString
    mskip = CsvAmountString -> Maybe CsvAmountString
    rule CsvAmountString
    "skip"

        ----------------------------------------------------------------------
        -- 2. Gather values needed for the transaction itself, by evaluating the
        -- field assignment rules using the CSV record's data, and parsing a bit
        -- more where needed (dates, status).

        date :: CsvAmountString
    date        = CsvAmountString -> Maybe CsvAmountString -> CsvAmountString
    forall a. a -> Maybe a -> a
    fromMaybe CsvAmountString
    "" (Maybe CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString -> CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> Maybe CsvAmountString
    fieldval CsvAmountString
    "date"
        -- PARTIAL:
        date' :: Day
    date'       = Day -> Maybe Day -> Day
    forall a. a -> Maybe a -> a
    fromMaybe ([Char] -> Day
    forall a. [Char] -> a
    error' ([Char] -> Day) -> [Char] -> Day
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString
    -> CsvAmountString -> Maybe CsvAmountString -> [Char]
    mkdateerror CsvAmountString
    "date" CsvAmountString
    date Maybe CsvAmountString
    mdateformat) (Maybe Day -> Day) -> Maybe Day -> Day
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> Maybe Day
    parsedate CsvAmountString
    date
        mdate2 :: Maybe CsvAmountString
    mdate2      = CsvAmountString -> Maybe CsvAmountString
    fieldval CsvAmountString
    "date2"
        mdate2' :: Maybe Day
    mdate2'     = (Maybe Day -> (Day -> Maybe Day) -> Maybe Day -> Maybe Day
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe ([Char] -> Maybe Day
    forall a. [Char] -> a
    error' ([Char] -> Maybe Day) -> [Char] -> Maybe Day
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString
    -> CsvAmountString -> Maybe CsvAmountString -> [Char]
    mkdateerror CsvAmountString
    "date2" (CsvAmountString -> Maybe CsvAmountString -> CsvAmountString
    forall a. a -> Maybe a -> a
    fromMaybe CsvAmountString
    "" Maybe CsvAmountString
    mdate2) Maybe CsvAmountString
    mdateformat) Day -> Maybe Day
    forall a. a -> Maybe a
    Just (Maybe Day -> Maybe Day)
    -> (CsvAmountString -> Maybe Day) -> CsvAmountString -> Maybe Day
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString -> Maybe Day
    parsedate) (CsvAmountString -> Maybe Day)
    -> Maybe CsvAmountString -> Maybe Day
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Maybe CsvAmountString
    mdate2
        status :: Status
    status      =
          case CsvAmountString -> Maybe CsvAmountString
    fieldval CsvAmountString
    "status" of
            Maybe CsvAmountString
    Nothing -> Status
    Unmarked
            Just CsvAmountString
    s  -> (ParseErrorBundle CsvAmountString HledgerParseErrorData -> Status)
    -> (Status -> Status)
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Status
    -> Status
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either ParseErrorBundle CsvAmountString HledgerParseErrorData -> Status
    forall {c}.
    ParseErrorBundle CsvAmountString HledgerParseErrorData -> c
    statuserror Status -> Status
    forall a. a -> a
    id (Either
       (ParseErrorBundle CsvAmountString HledgerParseErrorData) Status
     -> Status)
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Status
    -> Status
    forall a b. (a -> b) -> a -> b
    $ Parsec HledgerParseErrorData CsvAmountString Status
    -> [Char]
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Status
    forall e s a.
    Parsec e s a -> [Char] -> s -> Either (ParseErrorBundle s e) a
    runParser (Parsec HledgerParseErrorData CsvAmountString Status
    forall (m :: * -> *). TextParser m Status
    statusp Parsec HledgerParseErrorData CsvAmountString Status
    -> SimpleTextParser ()
    -> Parsec HledgerParseErrorData CsvAmountString Status
    forall a b.
    ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> ParsecT HledgerParseErrorData CsvAmountString Identity b
    -> ParsecT HledgerParseErrorData CsvAmountString Identity a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* SimpleTextParser ()
    forall e s (m :: * -> *). MonadParsec e s m => m ()
    eof) [Char]
    "" CsvAmountString
    s
              where
                statuserror :: ParseErrorBundle CsvAmountString HledgerParseErrorData -> c
    statuserror ParseErrorBundle CsvAmountString HledgerParseErrorData
    err = [Char] -> c
    forall a. [Char] -> a
    error' ([Char] -> c)
    -> (CsvAmountString -> [Char]) -> CsvAmountString -> c
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString -> [Char]
    T.unpack (CsvAmountString -> c) -> CsvAmountString -> c
    forall a b. (a -> b) -> a -> b
    $ [CsvAmountString] -> CsvAmountString
    T.unlines
                  [CsvAmountString
    "error: could not parse \""CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    sCsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    "\" as a cleared status (should be *, ! or empty)"
                  ,CsvAmountString
    "the parse error is:      "CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>[Char] -> CsvAmountString
    T.pack (ParseErrorBundle CsvAmountString HledgerParseErrorData -> [Char]
    customErrorBundlePretty ParseErrorBundle CsvAmountString HledgerParseErrorData
    err)
                  ]
        code :: CsvAmountString
    code        = CsvAmountString
    -> (CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString
    -> CsvAmountString
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe CsvAmountString
    "" CsvAmountString -> CsvAmountString
    singleline' (Maybe CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString -> CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> Maybe CsvAmountString
    fieldval CsvAmountString
    "code"
        description :: CsvAmountString
    description = CsvAmountString
    -> (CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString
    -> CsvAmountString
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe CsvAmountString
    "" CsvAmountString -> CsvAmountString
    singleline' (Maybe CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString -> CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> Maybe CsvAmountString
    fieldval CsvAmountString
    "description"
        comment :: CsvAmountString
    comment     = CsvAmountString
    -> (CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString
    -> CsvAmountString
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe CsvAmountString
    "" CsvAmountString -> CsvAmountString
    unescapeNewlines (Maybe CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString -> CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> Maybe CsvAmountString
    fieldval CsvAmountString
    "comment"
        ttags :: [(CsvAmountString, CsvAmountString)]
    ttags       = [(CsvAmountString, CsvAmountString)]
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         [(CsvAmountString, CsvAmountString)]
    -> [(CsvAmountString, CsvAmountString)]
    forall b a. b -> Either a b -> b
    fromRight [] (Either
       (ParseErrorBundle CsvAmountString HledgerParseErrorData)
       [(CsvAmountString, CsvAmountString)]
     -> [(CsvAmountString, CsvAmountString)])
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         [(CsvAmountString, CsvAmountString)]
    -> [(CsvAmountString, CsvAmountString)]
    forall a b. (a -> b) -> a -> b
    $ TextParser Identity [(CsvAmountString, CsvAmountString)]
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         [(CsvAmountString, CsvAmountString)]
    forall a.
    TextParser Identity a
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) a
    rtp TextParser Identity [(CsvAmountString, CsvAmountString)]
    forall (m :: * -> *).
    TextParser m [(CsvAmountString, CsvAmountString)]
    commenttagsp CsvAmountString
    comment
        precomment :: CsvAmountString
    precomment  = CsvAmountString
    -> (CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString
    -> CsvAmountString
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe CsvAmountString
    "" CsvAmountString -> CsvAmountString
    unescapeNewlines (Maybe CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString -> CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> Maybe CsvAmountString
    fieldval CsvAmountString
    "precomment"

        singleline' :: CsvAmountString -> CsvAmountString
    singleline' = [CsvAmountString] -> CsvAmountString
    T.unwords ([CsvAmountString] -> CsvAmountString)
    -> (CsvAmountString -> [CsvAmountString])
    -> CsvAmountString
    -> CsvAmountString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (CsvAmountString -> Bool) -> [CsvAmountString] -> [CsvAmountString]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (Bool -> Bool
    not (Bool -> Bool)
    -> (CsvAmountString -> Bool) -> CsvAmountString -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString -> Bool
    T.null) ([CsvAmountString] -> [CsvAmountString])
    -> (CsvAmountString -> [CsvAmountString])
    -> CsvAmountString
    -> [CsvAmountString]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (CsvAmountString -> CsvAmountString)
    -> [CsvAmountString] -> [CsvAmountString]
    forall a b. (a -> b) -> [a] -> [b]
    map CsvAmountString -> CsvAmountString
    T.strip ([CsvAmountString] -> [CsvAmountString])
    -> (CsvAmountString -> [CsvAmountString])
    -> CsvAmountString
    -> [CsvAmountString]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString -> [CsvAmountString]
    T.lines
        unescapeNewlines :: CsvAmountString -> CsvAmountString
    unescapeNewlines = CsvAmountString -> [CsvAmountString] -> CsvAmountString
    T.intercalate CsvAmountString
    "\n" ([CsvAmountString] -> CsvAmountString)
    -> (CsvAmountString -> [CsvAmountString])
    -> CsvAmountString
    -> CsvAmountString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . HasCallStack =>
    CsvAmountString -> CsvAmountString -> [CsvAmountString]
    CsvAmountString -> CsvAmountString -> [CsvAmountString]
    T.splitOn CsvAmountString
    "\\n"

        ----------------------------------------------------------------------
        -- 3. Generate the postings for which an account has been assigned
        -- (possibly indirectly due to an amount or balance assignment)

        p1IsVirtual :: Bool
    p1IsVirtual = (CsvAmountString -> PostingType
    accountNamePostingType (CsvAmountString -> PostingType)
    -> Maybe CsvAmountString -> Maybe PostingType
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CsvAmountString -> Maybe CsvAmountString
    fieldval CsvAmountString
    "account1") Maybe PostingType -> Maybe PostingType -> Bool
    forall a. Eq a => a -> a -> Bool
    == PostingType -> Maybe PostingType
    forall a. a -> Maybe a
    Just PostingType
    VirtualPosting
        ps :: [Posting]
    ps = [Posting
    p | CsvFieldIndex
    n <- [CsvFieldIndex
    1..CsvFieldIndex
    maxpostings]
             ,let cmt :: CsvAmountString
    cmt  = CsvAmountString
    -> (CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString
    -> CsvAmountString
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe CsvAmountString
    "" CsvAmountString -> CsvAmountString
    unescapeNewlines (Maybe CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString -> CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> Maybe CsvAmountString
    fieldval (CsvAmountString
    "comment"CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> [Char] -> CsvAmountString
    T.pack (CsvFieldIndex -> [Char]
    forall a. Show a => a -> [Char]
    show CsvFieldIndex
    n))
             ,let ptags :: [(CsvAmountString, CsvAmountString)]
    ptags = [(CsvAmountString, CsvAmountString)]
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         [(CsvAmountString, CsvAmountString)]
    -> [(CsvAmountString, CsvAmountString)]
    forall b a. b -> Either a b -> b
    fromRight [] (Either
       (ParseErrorBundle CsvAmountString HledgerParseErrorData)
       [(CsvAmountString, CsvAmountString)]
     -> [(CsvAmountString, CsvAmountString)])
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         [(CsvAmountString, CsvAmountString)]
    -> [(CsvAmountString, CsvAmountString)]
    forall a b. (a -> b) -> a -> b
    $ TextParser Identity [(CsvAmountString, CsvAmountString)]
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         [(CsvAmountString, CsvAmountString)]
    forall a.
    TextParser Identity a
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) a
    rtp TextParser Identity [(CsvAmountString, CsvAmountString)]
    forall (m :: * -> *).
    TextParser m [(CsvAmountString, CsvAmountString)]
    commenttagsp CsvAmountString
    cmt
             ,let currency :: CsvAmountString
    currency = CsvAmountString -> Maybe CsvAmountString -> CsvAmountString
    forall a. a -> Maybe a -> a
    fromMaybe CsvAmountString
    "" (CsvAmountString -> Maybe CsvAmountString
    fieldval (CsvAmountString
    "currency"CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> [Char] -> CsvAmountString
    T.pack (CsvFieldIndex -> [Char]
    forall a. Show a => a -> [Char]
    show CsvFieldIndex
    n)) Maybe CsvAmountString
    -> Maybe CsvAmountString -> Maybe CsvAmountString
    forall a. Maybe a -> Maybe a -> Maybe a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> CsvAmountString -> Maybe CsvAmountString
    fieldval CsvAmountString
    "currency")
             ,let mamount :: Maybe MixedAmount
    mamount  = CsvRules
    -> [CsvAmountString]
    -> CsvAmountString
    -> Bool
    -> CsvFieldIndex
    -> Maybe MixedAmount
    getAmount CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    currency Bool
    p1IsVirtual CsvFieldIndex
    n
             ,let mbalance :: Maybe (Amount, SourcePos)
    mbalance = CsvRules
    -> [CsvAmountString]
    -> CsvAmountString
    -> CsvFieldIndex
    -> Maybe (Amount, SourcePos)
    getBalance CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    currency CsvFieldIndex
    n
             ,Just (CsvAmountString
    acct,Bool
    isfinal) <- [CsvRules
    -> [CsvAmountString]
    -> Maybe MixedAmount
    -> Maybe (Amount, SourcePos)
    -> CsvFieldIndex
    -> Maybe (CsvAmountString, Bool)
    getAccount CsvRules
    rules [CsvAmountString]
    record Maybe MixedAmount
    mamount Maybe (Amount, SourcePos)
    mbalance CsvFieldIndex
    n]  -- skips Nothings
             ,let acct' :: CsvAmountString
    acct' | Bool -> Bool
    not Bool
    isfinal Bool -> Bool -> Bool
    && CsvAmountString
    acctCsvAmountString -> CsvAmountString -> Bool
    forall a. Eq a => a -> a -> Bool
    ==CsvAmountString
    unknownExpenseAccount Bool -> Bool -> Bool
    &&
                          Bool -> Maybe Bool -> Bool
    forall a. a -> Maybe a -> a
    fromMaybe Bool
    False (Maybe MixedAmount
    mamount Maybe MixedAmount -> (MixedAmount -> Maybe Bool) -> Maybe Bool
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= MixedAmount -> Maybe Bool
    isNegativeMixedAmount) = CsvAmountString
    unknownIncomeAccount
                        | Bool
    otherwise = CsvAmountString
    acct
             ,let p :: Posting
    p = Posting
    nullposting{paccount          = accountNameWithoutPostingType acct'
                                 ,pamount           = fromMaybe missingmixedamt mamount
                                 ,ptransaction      = Just t
                                 ,pbalanceassertion = mkBalanceAssertion rules record <$> mbalance
                                 ,pcomment          = cmt
                                 ,ptags             = ptags
                                 ,ptype             = accountNamePostingType acct
                                 }
             ]

        ----------------------------------------------------------------------
        -- 4. Build the transaction (and name it, so the postings can reference it).

        t :: Transaction
    t = Transaction
    nulltransaction{
               tsourcepos        = (sourcepos, sourcepos)  -- the CSV line number
              ,tdate             = date'
              ,tdate2            = mdate2'
              ,tstatus           = status
              ,tcode             = code
              ,tdescription      = description
              ,tcomment          = comment
              ,ttags             = ttags
              ,tprecedingcomment = precomment
              ,tpostings         = ps
              }

    -- | Parse the date string using the specified date-format, or if unspecified
    -- the "simple date" formats (YYYY/MM/DD, YYYY-MM-DD, YYYY.MM.DD, leading
    -- zeroes optional). If a timezone is provided, we assume the DateFormat
    -- produces a zoned time and we localise that to the given timezone.
    parseDateWithCustomOrDefaultFormats :: Bool -> Maybe TimeZone -> TimeZone -> Maybe DateFormat -> Text -> Maybe Day
    parseDateWithCustomOrDefaultFormats :: Bool
    -> Maybe TimeZone
    -> TimeZone
    -> Maybe CsvAmountString
    -> CsvAmountString
    -> Maybe Day
    parseDateWithCustomOrDefaultFormats Bool
    timesarezoned Maybe TimeZone
    mtzin TimeZone
    tzout Maybe CsvAmountString
    mformat CsvAmountString
    s = UTCTime -> Day
    localdate (UTCTime -> Day) -> Maybe UTCTime -> Maybe Day
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Maybe UTCTime
    mutctime
      -- this time code can probably be simpler, I'm just happy to get out alive
      where
        UTCTime -> Day
    localdate :: UTCTime -> Day =
          LocalTime -> Day
    localDay (LocalTime -> Day) -> (UTCTime -> LocalTime) -> UTCTime -> Day
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
          [Char] -> LocalTime -> LocalTime
    forall a. Show a => [Char] -> a -> a
    dbg7 ([Char]
    "time in output timezone "[Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++TimeZone -> [Char]
    forall a. Show a => a -> [Char]
    show TimeZone
    tzout) (LocalTime -> LocalTime)
    -> (UTCTime -> LocalTime) -> UTCTime -> LocalTime
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
          TimeZone -> UTCTime -> LocalTime
    utcToLocalTime TimeZone
    tzout
        Maybe UTCTime
    mutctime :: Maybe UTCTime = [Maybe UTCTime] -> Maybe UTCTime
    forall (f :: * -> *) (m :: * -> *) a.
    (Foldable f, Alternative m) =>
    f (m a) -> m a
    asum ([Maybe UTCTime] -> Maybe UTCTime)
    -> [Maybe UTCTime] -> Maybe UTCTime
    forall a b. (a -> b) -> a -> b
    $ ([Char] -> Maybe UTCTime) -> [[Char]] -> [Maybe UTCTime]
    forall a b. (a -> b) -> [a] -> [b]
    map [Char] -> Maybe UTCTime
    parseWithFormat [[Char]]
    formats

        parseWithFormat :: String -> Maybe UTCTime
        parseWithFormat :: [Char] -> Maybe UTCTime
    parseWithFormat [Char]
    fmt =
          if Bool
    timesarezoned
          then
            [Char] -> Maybe UTCTime -> Maybe UTCTime
    forall a. Show a => [Char] -> a -> a
    dbg7 [Char]
    "zoned CSV time, expressed as UTC" (Maybe UTCTime -> Maybe UTCTime) -> Maybe UTCTime -> Maybe UTCTime
    forall a b. (a -> b) -> a -> b
    $
            Bool -> TimeLocale -> [Char] -> [Char] -> Maybe UTCTime
    forall (m :: * -> *) t.
    (MonadFail m, ParseTime t) =>
    Bool -> TimeLocale -> [Char] -> [Char] -> m t
    parseTimeM Bool
    True TimeLocale
    defaultTimeLocale [Char]
    fmt ([Char] -> Maybe UTCTime) -> [Char] -> Maybe UTCTime
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> [Char]
    T.unpack CsvAmountString
    s :: Maybe UTCTime
          else
            -- parse as a local day and time; then if an input timezone is provided,
            -- assume it's in that, otherwise assume it's in the output timezone;
            -- then convert to UTC like the above
            let
              mlocaltime :: Maybe LocalTime
    mlocaltime =
                (LocalTime -> LocalTime) -> Maybe LocalTime -> Maybe LocalTime
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ([Char] -> LocalTime -> LocalTime
    forall a. Show a => [Char] -> a -> a
    dbg7 [Char]
    "unzoned CSV time") (Maybe LocalTime -> Maybe LocalTime)
    -> Maybe LocalTime -> Maybe LocalTime
    forall a b. (a -> b) -> a -> b
    $
                Bool -> TimeLocale -> [Char] -> [Char] -> Maybe LocalTime
    forall (m :: * -> *) t.
    (MonadFail m, ParseTime t) =>
    Bool -> TimeLocale -> [Char] -> [Char] -> m t
    parseTimeM Bool
    True TimeLocale
    defaultTimeLocale [Char]
    fmt ([Char] -> Maybe LocalTime) -> [Char] -> Maybe LocalTime
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> [Char]
    T.unpack CsvAmountString
    s :: Maybe LocalTime
              localTimeAsZonedTime :: TimeZone -> LocalTime -> ZonedTime
    localTimeAsZonedTime TimeZone
    tz LocalTime
    lt =  LocalTime -> TimeZone -> ZonedTime
    ZonedTime LocalTime
    lt TimeZone
    tz
            in
              case Maybe TimeZone
    mtzin of
                Just TimeZone
    tzin ->
                  ([Char] -> UTCTime -> UTCTime
    forall a. Show a => [Char] -> a -> a
    dbg7 ([Char]
    "unzoned CSV time, declared as "[Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++TimeZone -> [Char]
    forall a. Show a => a -> [Char]
    show TimeZone
    tzin[Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [Char]
    ", expressed as UTC") (UTCTime -> UTCTime)
    -> (LocalTime -> UTCTime) -> LocalTime -> UTCTime
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
                  TimeZone -> LocalTime -> UTCTime
    localTimeToUTC TimeZone
    tzin)
                  (LocalTime -> UTCTime) -> Maybe LocalTime -> Maybe UTCTime
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Maybe LocalTime
    mlocaltime
                Maybe TimeZone
    Nothing ->
                  ([Char] -> UTCTime -> UTCTime
    forall a. Show a => [Char] -> a -> a
    dbg7 ([Char]
    "unzoned CSV time, treated as "[Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++TimeZone -> [Char]
    forall a. Show a => a -> [Char]
    show TimeZone
    tzout[Char] -> [Char] -> [Char]
    forall a. [a] -> [a] -> [a]
    ++ [Char]
    ", expressed as UTC") (UTCTime -> UTCTime)
    -> (LocalTime -> UTCTime) -> LocalTime -> UTCTime
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
                    ZonedTime -> UTCTime
    zonedTimeToUTC (ZonedTime -> UTCTime)
    -> (LocalTime -> ZonedTime) -> LocalTime -> UTCTime
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
                    TimeZone -> LocalTime -> ZonedTime
    localTimeAsZonedTime TimeZone
    tzout)
                  (LocalTime -> UTCTime) -> Maybe LocalTime -> Maybe UTCTime
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Maybe LocalTime
    mlocaltime

        formats :: [[Char]]
    formats = (CsvAmountString -> [Char]) -> [CsvAmountString] -> [[Char]]
    forall a b. (a -> b) -> [a] -> [b]
    map CsvAmountString -> [Char]
    T.unpack ([CsvAmountString] -> [[Char]]) -> [CsvAmountString] -> [[Char]]
    forall a b. (a -> b) -> a -> b
    $ [CsvAmountString]
    -> (CsvAmountString -> [CsvAmountString])
    -> Maybe CsvAmountString
    -> [CsvAmountString]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe
                   [CsvAmountString
    "%Y/%-m/%-d"
                   ,CsvAmountString
    "%Y-%-m-%-d"
                   ,CsvAmountString
    "%Y.%-m.%-d"
                   -- ,"%-m/%-d/%Y"
                    -- ,parseTimeM TruedefaultTimeLocale "%Y/%m/%e" (take 5 s ++ "0" ++ drop 5 s)
                    -- ,parseTimeM TruedefaultTimeLocale "%Y-%m-%e" (take 5 s ++ "0" ++ drop 5 s)
                    -- ,parseTimeM TruedefaultTimeLocale "%m/%e/%Y" ('0':s)
                    -- ,parseTimeM TruedefaultTimeLocale "%m-%e-%Y" ('0':s)
                   ]
                   (CsvAmountString -> [CsvAmountString] -> [CsvAmountString]
    forall a. a -> [a] -> [a]
    :[])
                    Maybe CsvAmountString
    mformat

    -- | Figure out the amount specified for posting N, if any.
    -- A currency symbol to prepend to the amount, if any, is provided,
    -- and whether posting 1 requires balancing or not.
    -- This looks for a non-empty amount value assigned to "amountN", "amountN-in", or "amountN-out".
    -- For postings 1 or 2 it also looks at "amount", "amount-in", "amount-out".
    -- If more than one of these has a value, it looks for one that is non-zero.
    -- If there's multiple non-zeros, or no non-zeros but multiple zeros, it throws an error.
    getAmount :: CsvRules -> CsvRecord -> Text -> Bool -> Int -> Maybe MixedAmount
    getAmount :: CsvRules
    -> [CsvAmountString]
    -> CsvAmountString
    -> Bool
    -> CsvFieldIndex
    -> Maybe MixedAmount
    getAmount CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    currency Bool
    p1IsVirtual CsvFieldIndex
    n =
      -- Warning! Many tricky corner cases here.
      -- Keep synced with:
      -- hledger_csv.m4.md -> CSV FORMAT -> "amount", "Setting amounts",
      -- hledger/test/csv.test -> 13, 31-34
      let
        unnumberedfieldnames :: [CsvAmountString]
    unnumberedfieldnames = [CsvAmountString
    "amount",CsvAmountString
    "amount-in",CsvAmountString
    "amount-out"]

        -- amount field names which can affect this posting
        fieldnames :: [CsvAmountString]
    fieldnames = (CsvAmountString -> CsvAmountString)
    -> [CsvAmountString] -> [CsvAmountString]
    forall a b. (a -> b) -> [a] -> [b]
    map ((CsvAmountString
    "amount"CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> [Char] -> CsvAmountString
    T.pack (CsvFieldIndex -> [Char]
    forall a. Show a => a -> [Char]
    show CsvFieldIndex
    n))CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>) [CsvAmountString
    "",CsvAmountString
    "-in",CsvAmountString
    "-out"]
                     -- For posting 1, also recognise the old amount/amount-in/amount-out names.
                     -- For posting 2, the same but only if posting 1 needs balancing.
                     [CsvAmountString] -> [CsvAmountString] -> [CsvAmountString]
    forall a. [a] -> [a] -> [a]
    ++ if CsvFieldIndex
    nCsvFieldIndex -> CsvFieldIndex -> Bool
    forall a. Eq a => a -> a -> Bool
    ==CsvFieldIndex
    1 Bool -> Bool -> Bool
    || CsvFieldIndex
    nCsvFieldIndex -> CsvFieldIndex -> Bool
    forall a. Eq a => a -> a -> Bool
    ==CsvFieldIndex
    2 Bool -> Bool -> Bool
    && Bool -> Bool
    not Bool
    p1IsVirtual then [CsvAmountString]
    unnumberedfieldnames else []

        -- assignments to any of these field names with non-empty values
        assignments :: [(CsvAmountString, MixedAmount)]
    assignments = [(CsvAmountString
    f,MixedAmount
    a') | CsvAmountString
    f <- [CsvAmountString]
    fieldnames
                              , Just CsvAmountString
    v <- [CsvAmountString -> CsvAmountString
    T.strip (CsvAmountString -> CsvAmountString)
    -> (CsvAmountString -> CsvAmountString)
    -> CsvAmountString
    -> CsvAmountString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvRules
    -> [CsvAmountString]
    -> CsvAmountString
    -> CsvAmountString
    -> CsvAmountString
    renderTemplate CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    f (CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString -> Maybe CsvAmountString
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    hledgerField CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    f]
                              , Bool -> Bool
    not (Bool -> Bool) -> Bool -> Bool
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> Bool
    T.null CsvAmountString
    v
                              -- XXX maybe ignore rule-generated values like "", "-", "$", "-$", "$-" ? cf CSV FORMAT -> "amount", "Setting amounts",
                              , let a :: MixedAmount
    a = CsvRules
    -> [CsvAmountString]
    -> CsvAmountString
    -> CsvAmountString
    -> MixedAmount
    parseAmount CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    currency CsvAmountString
    v
                              -- With amount/amount-in/amount-out, in posting 2,
                              -- flip the sign and convert to cost, as they did before 1.17
                              , let a' :: MixedAmount
    a' = if CsvAmountString
    f CsvAmountString -> [CsvAmountString] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [CsvAmountString]
    unnumberedfieldnames Bool -> Bool -> Bool
    && CsvFieldIndex
    nCsvFieldIndex -> CsvFieldIndex -> Bool
    forall a. Eq a => a -> a -> Bool
    ==CsvFieldIndex
    2 then MixedAmount -> MixedAmount
    mixedAmountCost (MixedAmount -> MixedAmount
    maNegate MixedAmount
    a) else MixedAmount
    a
                              ]

        -- if any of the numbered field names are present, discard all the unnumbered ones
        discardUnnumbered :: [(CsvAmountString, b)] -> [(CsvAmountString, b)]
    discardUnnumbered [(CsvAmountString, b)]
    xs = if [(CsvAmountString, b)] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [(CsvAmountString, b)]
    numbered then [(CsvAmountString, b)]
    xs else [(CsvAmountString, b)]
    numbered
          where
            numbered :: [(CsvAmountString, b)]
    numbered = ((CsvAmountString, b) -> Bool)
    -> [(CsvAmountString, b)] -> [(CsvAmountString, b)]
    forall a. (a -> Bool) -> [a] -> [a]
    filter ((Char -> Bool) -> CsvAmountString -> Bool
    T.any Char -> Bool
    isDigit (CsvAmountString -> Bool)
    -> ((CsvAmountString, b) -> CsvAmountString)
    -> (CsvAmountString, b)
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (CsvAmountString, b) -> CsvAmountString
    forall a b. (a, b) -> a
    fst) [(CsvAmountString, b)]
    xs

        -- discard all zero amounts, unless all amounts are zero, in which case discard all but the first
        discardExcessZeros :: [(a, MixedAmount)] -> [(a, MixedAmount)]
    discardExcessZeros [(a, MixedAmount)]
    xs = if [(a, MixedAmount)] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [(a, MixedAmount)]
    nonzeros then CsvFieldIndex -> [(a, MixedAmount)] -> [(a, MixedAmount)]
    forall a. CsvFieldIndex -> [a] -> [a]
    take CsvFieldIndex
    1 [(a, MixedAmount)]
    xs else [(a, MixedAmount)]
    nonzeros
          where
            nonzeros :: [(a, MixedAmount)]
    nonzeros = ((a, MixedAmount) -> Bool)
    -> [(a, MixedAmount)] -> [(a, MixedAmount)]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (Bool -> Bool
    not (Bool -> Bool)
    -> ((a, MixedAmount) -> Bool) -> (a, MixedAmount) -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . MixedAmount -> Bool
    mixedAmountLooksZero (MixedAmount -> Bool)
    -> ((a, MixedAmount) -> MixedAmount) -> (a, MixedAmount) -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (a, MixedAmount) -> MixedAmount
    forall a b. (a, b) -> b
    snd) [(a, MixedAmount)]
    xs

        -- for -out fields, flip the sign  XXX unless it's already negative ? back compat issues / too confusing ?
        negateIfOut :: CsvAmountString -> MixedAmount -> MixedAmount
    negateIfOut CsvAmountString
    f = if CsvAmountString
    "-out" CsvAmountString -> CsvAmountString -> Bool
    `T.isSuffixOf` CsvAmountString
    f then MixedAmount -> MixedAmount
    maNegate else MixedAmount -> MixedAmount
    forall a. a -> a
    id

      in case [(CsvAmountString, MixedAmount)]
    -> [(CsvAmountString, MixedAmount)]
    forall {a}. [(a, MixedAmount)] -> [(a, MixedAmount)]
    discardExcessZeros ([(CsvAmountString, MixedAmount)]
     -> [(CsvAmountString, MixedAmount)])
    -> [(CsvAmountString, MixedAmount)]
    -> [(CsvAmountString, MixedAmount)]
    forall a b. (a -> b) -> a -> b
    $ [(CsvAmountString, MixedAmount)]
    -> [(CsvAmountString, MixedAmount)]
    forall {b}. [(CsvAmountString, b)] -> [(CsvAmountString, b)]
    discardUnnumbered [(CsvAmountString, MixedAmount)]
    assignments of
          []      -> Maybe MixedAmount
    forall a. Maybe a
    Nothing
          [(CsvAmountString
    f,MixedAmount
    a)] -> MixedAmount -> Maybe MixedAmount
    forall a. a -> Maybe a
    Just (MixedAmount -> Maybe MixedAmount)
    -> MixedAmount -> Maybe MixedAmount
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> MixedAmount -> MixedAmount
    negateIfOut CsvAmountString
    f MixedAmount
    a
          [(CsvAmountString, MixedAmount)]
    fs      -> [Char] -> Maybe MixedAmount
    forall a. [Char] -> a
    error' ([Char] -> Maybe MixedAmount)
    -> ([CsvAmountString] -> [Char])
    -> [CsvAmountString]
    -> Maybe MixedAmount
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString -> [Char]
    T.unpack (CsvAmountString -> [Char])
    -> ([CsvAmountString] -> CsvAmountString)
    -> [CsvAmountString]
    -> [Char]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString -> CsvAmountString
    textChomp (CsvAmountString -> CsvAmountString)
    -> ([CsvAmountString] -> CsvAmountString)
    -> [CsvAmountString]
    -> CsvAmountString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [CsvAmountString] -> CsvAmountString
    T.unlines ([CsvAmountString] -> Maybe MixedAmount)
    -> [CsvAmountString] -> Maybe MixedAmount
    forall a b. (a -> b) -> a -> b
    $  -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
              -- PARTIAL:
            [CsvAmountString
    "in CSV rules:"
            ,CsvAmountString
    "While processing " CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> [CsvAmountString] -> CsvAmountString
    showRecord [CsvAmountString]
    record
            ,CsvAmountString
    "while calculating amount for posting " CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> [Char] -> CsvAmountString
    T.pack (CsvFieldIndex -> [Char]
    forall a. Show a => a -> [Char]
    show CsvFieldIndex
    n)
            ] [CsvAmountString] -> [CsvAmountString] -> [CsvAmountString]
    forall a. [a] -> [a] -> [a]
    ++
            [CsvAmountString
    "rule \"" CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    f CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    " " CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>
              CsvAmountString -> Maybe CsvAmountString -> CsvAmountString
    forall a. a -> Maybe a -> a
    fromMaybe CsvAmountString
    "" (CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    hledgerField CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    f) CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>
              CsvAmountString
    "\" assigned value \"" CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> WideBuilder -> CsvAmountString
    wbToText (AmountDisplayOpts -> MixedAmount -> WideBuilder
    showMixedAmountB AmountDisplayOpts
    noColour MixedAmount
    a) CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    "\"" -- XXX not sure this is showing all the right info
              | (CsvAmountString
    f,MixedAmount
    a) <- [(CsvAmountString, MixedAmount)]
    fs
            ] [CsvAmountString] -> [CsvAmountString] -> [CsvAmountString]
    forall a. [a] -> [a] -> [a]
    ++
            [CsvAmountString
    ""
            ,CsvAmountString
    "Multiple non-zero amounts were assigned for an amount field."
            ,CsvAmountString
    "Please ensure just one non-zero amount is assigned, perhaps with an if rule."
            ,CsvAmountString
    "See also: https://hledger.org/hledger.html#setting-amounts"
            ,CsvAmountString
    "(hledger manual -> CSV format -> Tips -> Setting amounts)"
            ]
    -- | Figure out the expected balance (assertion or assignment) specified for posting N,
    -- if any (and its parse position).
    getBalance :: CsvRules -> CsvRecord -> Text -> Int -> Maybe (Amount, SourcePos)
    getBalance :: CsvRules
    -> [CsvAmountString]
    -> CsvAmountString
    -> CsvFieldIndex
    -> Maybe (Amount, SourcePos)
    getBalance CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    currency CsvFieldIndex
    n = do
      CsvAmountString
    v <- (CsvAmountString -> Maybe CsvAmountString
    fieldval (CsvAmountString
    "balance"CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> [Char] -> CsvAmountString
    T.pack (CsvFieldIndex -> [Char]
    forall a. Show a => a -> [Char]
    show CsvFieldIndex
    n))
            -- for posting 1, also recognise the old field name
            Maybe CsvAmountString
    -> Maybe CsvAmountString -> Maybe CsvAmountString
    forall a. Maybe a -> Maybe a -> Maybe a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> if CsvFieldIndex
    nCsvFieldIndex -> CsvFieldIndex -> Bool
    forall a. Eq a => a -> a -> Bool
    ==CsvFieldIndex
    1 then CsvAmountString -> Maybe CsvAmountString
    fieldval CsvAmountString
    "balance" else Maybe CsvAmountString
    forall a. Maybe a
    Nothing)
      case CsvAmountString
    v of
        CsvAmountString
    "" -> Maybe (Amount, SourcePos)
    forall a. Maybe a
    Nothing
        CsvAmountString
    s  -> (Amount, SourcePos) -> Maybe (Amount, SourcePos)
    forall a. a -> Maybe a
    Just (
                CsvRules
    -> [CsvAmountString]
    -> CsvAmountString
    -> CsvFieldIndex
    -> CsvAmountString
    -> Amount
    parseBalanceAmount CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    currency CsvFieldIndex
    n CsvAmountString
    s
               ,[Char] -> SourcePos
    initialPos [Char]
    ""  -- parse position to show when assertion fails,
               )               -- XXX the csv record's line number would be good
      where
        fieldval :: CsvAmountString -> Maybe CsvAmountString
    fieldval = (CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString -> Maybe CsvAmountString
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap CsvAmountString -> CsvAmountString
    T.strip (Maybe CsvAmountString -> Maybe CsvAmountString)
    -> (CsvAmountString -> Maybe CsvAmountString)
    -> CsvAmountString
    -> Maybe CsvAmountString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    hledgerFieldValue CsvRules
    rules [CsvAmountString]
    record :: HledgerFieldName -> Maybe Text

    -- | Given a non-empty amount string (from CSV) to parse, along with a
    -- possibly non-empty currency symbol to prepend,
    -- parse as a hledger MixedAmount (as in journal format), or raise an error.
    -- The whole CSV record is provided for the error message.
    parseAmount :: CsvRules -> CsvRecord -> Text -> Text -> MixedAmount
    parseAmount :: CsvRules
    -> [CsvAmountString]
    -> CsvAmountString
    -> CsvAmountString
    -> MixedAmount
    parseAmount CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    currency CsvAmountString
    s =
        (ParseErrorBundle CsvAmountString HledgerParseErrorData
     -> MixedAmount)
    -> (Amount -> MixedAmount)
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Amount
    -> MixedAmount
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either ParseErrorBundle CsvAmountString HledgerParseErrorData
    -> MixedAmount
    forall {c}.
    ParseErrorBundle CsvAmountString HledgerParseErrorData -> c
    mkerror Amount -> MixedAmount
    mixedAmount (Either
       (ParseErrorBundle CsvAmountString HledgerParseErrorData) Amount
     -> MixedAmount)
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Amount
    -> MixedAmount
    forall a b. (a -> b) -> a -> b
    $  -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
          -- PARTIAL:
        Parsec HledgerParseErrorData CsvAmountString Amount
    -> [Char]
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Amount
    forall e s a.
    Parsec e s a -> [Char] -> s -> Either (ParseErrorBundle s e) a
    runParser (StateT
      Journal
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Amount
    -> Journal -> Parsec HledgerParseErrorData CsvAmountString Amount
    forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
    evalStateT (StateT
      Journal
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Amount
    forall (m :: * -> *). JournalParser m Amount
    amountp StateT
      Journal
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Amount
    -> StateT
         Journal (ParsecT HledgerParseErrorData CsvAmountString Identity) ()
    -> StateT
         Journal
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Amount
    forall a b.
    StateT
      Journal (ParsecT HledgerParseErrorData CsvAmountString Identity) a
    -> StateT
         Journal (ParsecT HledgerParseErrorData CsvAmountString Identity) b
    -> StateT
         Journal (ParsecT HledgerParseErrorData CsvAmountString Identity) a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* StateT
      Journal (ParsecT HledgerParseErrorData CsvAmountString Identity) ()
    forall e s (m :: * -> *). MonadParsec e s m => m ()
    eof) Journal
    journalparsestate) [Char]
    "" (CsvAmountString
     -> Either
          (ParseErrorBundle CsvAmountString HledgerParseErrorData) Amount)
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Amount
    forall a b. (a -> b) -> a -> b
    $
        CsvAmountString
    currency CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString -> CsvAmountString
    simplifySign CsvAmountString
    s
      where
        journalparsestate :: Journal
    journalparsestate = Journal
    nulljournal{jparsedecimalmark=parseDecimalMark rules}
        mkerror :: ParseErrorBundle CsvAmountString HledgerParseErrorData -> c
    mkerror ParseErrorBundle CsvAmountString HledgerParseErrorData
    e = [Char] -> c
    forall a. [Char] -> a
    error' ([Char] -> c)
    -> (CsvAmountString -> [Char]) -> CsvAmountString -> c
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString -> [Char]
    T.unpack (CsvAmountString -> c) -> CsvAmountString -> c
    forall a b. (a -> b) -> a -> b
    $ [CsvAmountString] -> CsvAmountString
    T.unlines
          [CsvAmountString
    "error: could not parse \"" CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    s CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    "\" as an amount"
          ,[CsvAmountString] -> CsvAmountString
    showRecord [CsvAmountString]
    record
          ,CsvRules -> [CsvAmountString] -> CsvAmountString
    showRules CsvRules
    rules [CsvAmountString]
    record
          -- ,"the default-currency is: "++fromMaybe "unspecified" (getDirective "default-currency" rules)
          ,CsvAmountString
    "the parse error is:      " CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> [Char] -> CsvAmountString
    T.pack (ParseErrorBundle CsvAmountString HledgerParseErrorData -> [Char]
    customErrorBundlePretty ParseErrorBundle CsvAmountString HledgerParseErrorData
    e)
          ,CsvAmountString
    "you may need to \
            \change your amount*, balance*, or currency* rules, \
            \or add or change your skip rule"
          ]

    -- | Show the values assigned to each journal field.
    showRules :: CsvRules -> [CsvAmountString] -> CsvAmountString
    showRules CsvRules
    rules [CsvAmountString]
    record = [CsvAmountString] -> CsvAmountString
    T.unlines ([CsvAmountString] -> CsvAmountString)
    -> [CsvAmountString] -> CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ [Maybe CsvAmountString] -> [CsvAmountString]
    forall a. [Maybe a] -> [a]
    catMaybes
      [ ((CsvAmountString
    "the "CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    fldCsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    " rule is: ")CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>) (CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString -> Maybe CsvAmountString
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$>
        CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    getEffectiveAssignment CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    fld | CsvAmountString
    fld <- [CsvAmountString]
    journalfieldnames ]

    -- | Show a (approximate) recreation of the original CSV record.
    showRecord :: CsvRecord -> Text
    showRecord :: [CsvAmountString] -> CsvAmountString
    showRecord [CsvAmountString]
    r = CsvAmountString
    "CSV record: "CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString -> [CsvAmountString] -> CsvAmountString
    T.intercalate CsvAmountString
    "," ((CsvAmountString -> CsvAmountString)
    -> [CsvAmountString] -> [CsvAmountString]
    forall a b. (a -> b) -> [a] -> [b]
    map (CsvAmountString
    -> CsvAmountString -> CsvAmountString -> CsvAmountString
    wrap CsvAmountString
    "\"" CsvAmountString
    "\"") [CsvAmountString]
    r)

    -- XXX unify these ^v

    -- | Almost but not quite the same as parseAmount.
    -- Given a non-empty amount string (from CSV) to parse, along with a
    -- possibly non-empty currency symbol to prepend,
    -- parse as a hledger Amount (as in journal format), or raise an error.
    -- The CSV record and the field's numeric suffix are provided for the error message.
    parseBalanceAmount :: CsvRules -> CsvRecord -> Text -> Int -> Text -> Amount
    parseBalanceAmount :: CsvRules
    -> [CsvAmountString]
    -> CsvAmountString
    -> CsvFieldIndex
    -> CsvAmountString
    -> Amount
    parseBalanceAmount CsvRules
    rules [CsvAmountString]
    record CsvAmountString
    currency CsvFieldIndex
    n CsvAmountString
    s =
      (ParseErrorBundle CsvAmountString HledgerParseErrorData -> Amount)
    -> (Amount -> Amount)
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Amount
    -> Amount
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either (CsvFieldIndex
    -> CsvAmountString
    -> ParseErrorBundle CsvAmountString HledgerParseErrorData
    -> Amount
    forall {a} {c}.
    Show a =>
    a
    -> CsvAmountString
    -> ParseErrorBundle CsvAmountString HledgerParseErrorData
    -> c
    mkerror CsvFieldIndex
    n CsvAmountString
    s) Amount -> Amount
    forall a. a -> a
    id (Either
       (ParseErrorBundle CsvAmountString HledgerParseErrorData) Amount
     -> Amount)
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Amount
    -> Amount
    forall a b. (a -> b) -> a -> b
    $
        Parsec HledgerParseErrorData CsvAmountString Amount
    -> [Char]
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Amount
    forall e s a.
    Parsec e s a -> [Char] -> s -> Either (ParseErrorBundle s e) a
    runParser (StateT
      Journal
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Amount
    -> Journal -> Parsec HledgerParseErrorData CsvAmountString Amount
    forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
    evalStateT (StateT
      Journal
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Amount
    forall (m :: * -> *). JournalParser m Amount
    amountp StateT
      Journal
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Amount
    -> StateT
         Journal (ParsecT HledgerParseErrorData CsvAmountString Identity) ()
    -> StateT
         Journal
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Amount
    forall a b.
    StateT
      Journal (ParsecT HledgerParseErrorData CsvAmountString Identity) a
    -> StateT
         Journal (ParsecT HledgerParseErrorData CsvAmountString Identity) b
    -> StateT
         Journal (ParsecT HledgerParseErrorData CsvAmountString Identity) a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* StateT
      Journal (ParsecT HledgerParseErrorData CsvAmountString Identity) ()
    forall e s (m :: * -> *). MonadParsec e s m => m ()
    eof) Journal
    journalparsestate) [Char]
    "" (CsvAmountString
     -> Either
          (ParseErrorBundle CsvAmountString HledgerParseErrorData) Amount)
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Amount
    forall a b. (a -> b) -> a -> b
    $
        CsvAmountString
    currency CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString -> CsvAmountString
    simplifySign CsvAmountString
    s
                      -- the csv record's line number would be good
      where
        journalparsestate :: Journal
    journalparsestate = Journal
    nulljournal{jparsedecimalmark=parseDecimalMark rules}
        mkerror :: a
    -> CsvAmountString
    -> ParseErrorBundle CsvAmountString HledgerParseErrorData
    -> c
    mkerror a
    n' CsvAmountString
    s' ParseErrorBundle CsvAmountString HledgerParseErrorData
    e = [Char] -> c
    forall a. [Char] -> a
    error' ([Char] -> c)
    -> (CsvAmountString -> [Char]) -> CsvAmountString -> c
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString -> [Char]
    T.unpack (CsvAmountString -> c) -> CsvAmountString -> c
    forall a b. (a -> b) -> a -> b
    $ [CsvAmountString] -> CsvAmountString
    T.unlines
          [CsvAmountString
    "error: could not parse \"" CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    s' CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    "\" as balance"CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> [Char] -> CsvAmountString
    T.pack (a -> [Char]
    forall a. Show a => a -> [Char]
    show a
    n') CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    " amount"
          ,[CsvAmountString] -> CsvAmountString
    showRecord [CsvAmountString]
    record
          ,CsvRules -> [CsvAmountString] -> CsvAmountString
    showRules CsvRules
    rules [CsvAmountString]
    record
          -- ,"the default-currency is: "++fromMaybe "unspecified" mdefaultcurrency
          ,CsvAmountString
    "the parse error is:      "CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> [Char] -> CsvAmountString
    T.pack (ParseErrorBundle CsvAmountString HledgerParseErrorData -> [Char]
    customErrorBundlePretty ParseErrorBundle CsvAmountString HledgerParseErrorData
    e)
          ]

    -- Read a valid decimal mark from the decimal-mark rule, if any.
    -- If the rule is present with an invalid argument, raise an error.
    parseDecimalMark :: CsvRules -> Maybe DecimalMark
    parseDecimalMark :: CsvRules -> Maybe Char
    parseDecimalMark CsvRules
    rules = do
        CsvAmountString
    s <- CsvRules
    rules CsvRules -> CsvAmountString -> Maybe CsvAmountString
    `csvRule` CsvAmountString
    "decimal-mark"
        case CsvAmountString -> Maybe (Char, CsvAmountString)
    T.uncons CsvAmountString
    s of
            Just (Char
    c, CsvAmountString
    rest) | CsvAmountString -> Bool
    T.null CsvAmountString
    rest Bool -> Bool -> Bool
    && Char -> Bool
    isDecimalMark Char
    c -> Char -> Maybe Char
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Char
    c
            Maybe (Char, CsvAmountString)
    _ -> [Char] -> Maybe Char
    forall a. [Char] -> a
    error' ([Char] -> Maybe Char)
    -> (CsvAmountString -> [Char]) -> CsvAmountString -> Maybe Char
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString -> [Char]
    T.unpack (CsvAmountString -> Maybe Char) -> CsvAmountString -> Maybe Char
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString
    "decimal-mark's argument should be \".\" or \",\" (not \""CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    sCsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    "\")"

    -- | Make a balance assertion for the given amount, with the given parse
    -- position (to be shown in assertion failures), with the assertion type
    -- possibly set by a balance-type rule.
    -- The CSV rules and current record are also provided, to be shown in case
    -- balance-type's argument is bad (XXX refactor).
    mkBalanceAssertion :: CsvRules -> CsvRecord -> (Amount, SourcePos) -> BalanceAssertion
    mkBalanceAssertion :: CsvRules
    -> [CsvAmountString] -> (Amount, SourcePos) -> BalanceAssertion
    mkBalanceAssertion CsvRules
    rules [CsvAmountString]
    record (Amount
    amt, SourcePos
    pos) = BalanceAssertion
    assrt{baamount=amt, baposition=pos}
      where
        assrt :: BalanceAssertion
    assrt =
          case CsvAmountString -> CsvRules -> Maybe CsvAmountString
    getDirective CsvAmountString
    "balance-type" CsvRules
    rules of
            Maybe CsvAmountString
    Nothing    -> BalanceAssertion
    nullassertion
            Just CsvAmountString
    "="   -> BalanceAssertion
    nullassertion
            Just CsvAmountString
    "=="  -> BalanceAssertion
    nullassertion{batotal=True}
            Just CsvAmountString
    "=*"  -> BalanceAssertion
    nullassertion{bainclusive=True}
            Just CsvAmountString
    "==*" -> BalanceAssertion
    nullassertion{batotal=True, bainclusive=True}
            Just CsvAmountString
    x     -> [Char] -> BalanceAssertion
    forall a. [Char] -> a
    error' ([Char] -> BalanceAssertion)
    -> (CsvAmountString -> [Char])
    -> CsvAmountString
    -> BalanceAssertion
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . CsvAmountString -> [Char]
    T.unpack (CsvAmountString -> BalanceAssertion)
    -> CsvAmountString -> BalanceAssertion
    forall a b. (a -> b) -> a -> b
    $ [CsvAmountString] -> CsvAmountString
    T.unlines  -- PARTIAL:
              [ CsvAmountString
    "balance-type \"" CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> CsvAmountString
    x CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <>CsvAmountString
    "\" is invalid. Use =, ==, =* or ==*."
              , [CsvAmountString] -> CsvAmountString
    showRecord [CsvAmountString]
    record
              , CsvRules -> [CsvAmountString] -> CsvAmountString
    showRules CsvRules
    rules [CsvAmountString]
    record
              ]

    -- | Figure out the account name specified for posting N, if any.
    -- And whether it is the default unknown account (which may be
    -- improved later) or an explicitly set account (which may not).
    getAccount :: CsvRules -> CsvRecord -> Maybe MixedAmount -> Maybe (Amount, SourcePos) -> Int -> Maybe (AccountName, Bool)
    getAccount :: CsvRules
    -> [CsvAmountString]
    -> Maybe MixedAmount
    -> Maybe (Amount, SourcePos)
    -> CsvFieldIndex
    -> Maybe (CsvAmountString, Bool)
    getAccount CsvRules
    rules [CsvAmountString]
    record Maybe MixedAmount
    mamount Maybe (Amount, SourcePos)
    mbalance CsvFieldIndex
    n =
      let
        fieldval :: CsvAmountString -> Maybe CsvAmountString
    fieldval = CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    hledgerFieldValue CsvRules
    rules [CsvAmountString]
    record :: HledgerFieldName -> Maybe Text
        maccount :: Maybe CsvAmountString
    maccount = CsvAmountString -> CsvAmountString
    T.strip (CsvAmountString -> CsvAmountString)
    -> Maybe CsvAmountString -> Maybe CsvAmountString
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CsvAmountString -> Maybe CsvAmountString
    fieldval (CsvAmountString
    "account"CsvAmountString -> CsvAmountString -> CsvAmountString
    forall a. Semigroup a => a -> a -> a
    <> [Char] -> CsvAmountString
    T.pack (CsvFieldIndex -> [Char]
    forall a. Show a => a -> [Char]
    show CsvFieldIndex
    n))
      in case Maybe CsvAmountString
    maccount of
        -- accountN is set to the empty string - no posting will be generated
        Just CsvAmountString
    "" -> Maybe (CsvAmountString, Bool)
    forall a. Maybe a
    Nothing
        -- accountN is set (possibly to "expenses:unknown"! #1192) - mark it final
        Just CsvAmountString
    a  ->
          -- Check it and reject if invalid.. sometimes people try
          -- to set an amount or comment along with the account name.
          case SimpleTextParser ()
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) ()
    forall e a.
    Parsec e CsvAmountString a
    -> CsvAmountString -> Either (ParseErrorBundle CsvAmountString e) a
    parsewith (ParsecT
      HledgerParseErrorData CsvAmountString Identity CsvAmountString
    forall (m :: * -> *). TextParser m CsvAmountString
    accountnamep ParsecT
      HledgerParseErrorData CsvAmountString Identity CsvAmountString
    -> SimpleTextParser () -> SimpleTextParser ()
    forall a b.
    ParsecT HledgerParseErrorData CsvAmountString Identity a
    -> ParsecT HledgerParseErrorData CsvAmountString Identity b
    -> ParsecT HledgerParseErrorData CsvAmountString Identity b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> SimpleTextParser ()
    forall e s (m :: * -> *). MonadParsec e s m => m ()
    eof) CsvAmountString
    a of
            Left ParseErrorBundle CsvAmountString HledgerParseErrorData
    e  -> [Char] -> Maybe (CsvAmountString, Bool)
    forall a. [Char] -> a
    usageError ([Char] -> Maybe (CsvAmountString, Bool))
    -> [Char] -> Maybe (CsvAmountString, Bool)
    forall a b. (a -> b) -> a -> b
    $ ParseErrorBundle CsvAmountString HledgerParseErrorData -> [Char]
    forall s e.
    (VisualStream s, TraversableStream s, ShowErrorComponent e) =>
    ParseErrorBundle s e -> [Char]
    errorBundlePretty ParseErrorBundle CsvAmountString HledgerParseErrorData
    e
            Right ()
    _ -> (CsvAmountString, Bool) -> Maybe (CsvAmountString, Bool)
    forall a. a -> Maybe a
    Just (CsvAmountString
    a, Bool
    True)
        -- accountN is unset
        Maybe CsvAmountString
    Nothing ->
          case (Maybe MixedAmount
    mamount, Maybe (Amount, SourcePos)
    mbalance) of
            -- amountN is set, or implied by balanceN - set accountN to
            -- the default unknown account ("expenses:unknown") and
            -- allow it to be improved later
            (Just MixedAmount
    _, Maybe (Amount, SourcePos)
    _) -> (CsvAmountString, Bool) -> Maybe (CsvAmountString, Bool)
    forall a. a -> Maybe a
    Just (CsvAmountString
    unknownExpenseAccount, Bool
    False)
            (Maybe MixedAmount
    _, Just (Amount, SourcePos)
    _) -> (CsvAmountString, Bool) -> Maybe (CsvAmountString, Bool)
    forall a. a -> Maybe a
    Just (CsvAmountString
    unknownExpenseAccount, Bool
    False)
            -- amountN is also unset - no posting will be generated
            (Maybe MixedAmount
    Nothing, Maybe (Amount, SourcePos)
    Nothing) -> Maybe (CsvAmountString, Bool)
    forall a. Maybe a
    Nothing

    -- | Default account names to use when needed.
    unknownExpenseAccount :: CsvAmountString
    unknownExpenseAccount = CsvAmountString
    "expenses:unknown"
    unknownIncomeAccount :: CsvAmountString
    unknownIncomeAccount  = CsvAmountString
    "income:unknown"

    type CsvAmountString = Text

    -- | Canonicalise the sign in a CSV amount string.
    -- Such strings can have a minus sign, parentheses (equivalent to minus),
    -- or any two of these (which cancel out),
    -- or a plus sign (which is removed),
    -- or any sign by itself with no following number (which is removed).
    -- See hledger > CSV FORMAT > Tips > Setting amounts.
    --
    -- These are supported (note, not every possibile combination):
    --
    -- >>> simplifySign "1"
    -- "1"
    -- >>> simplifySign "+1"
    -- "1"
    -- >>> simplifySign "-1"
    -- "-1"
    -- >>> simplifySign "(1)"
    -- "-1"
    -- >>> simplifySign "--1"
    -- "1"
    -- >>> simplifySign "-(1)"
    -- "1"
    -- >>> simplifySign "-+1"
    -- "-1"
    -- >>> simplifySign "(-1)"
    -- "1"
    -- >>> simplifySign "((1))"
    -- "1"
    -- >>> simplifySign "-"
    -- ""
    -- >>> simplifySign "()"
    -- ""
    -- >>> simplifySign "+"
    -- ""
    simplifySign :: CsvAmountString -> CsvAmountString
    simplifySign :: CsvAmountString -> CsvAmountString
    simplifySign CsvAmountString
    amtstr
      | Just (Char
    ' ',CsvAmountString
    t) <- CsvAmountString -> Maybe (Char, CsvAmountString)
    T.uncons CsvAmountString
    amtstr = CsvAmountString -> CsvAmountString
    simplifySign CsvAmountString
    t
      | Just (CsvAmountString
    t,Char
    ' ') <- CsvAmountString -> Maybe (CsvAmountString, Char)
    T.unsnoc CsvAmountString
    amtstr = CsvAmountString -> CsvAmountString
    simplifySign CsvAmountString
    t
      | Just (Char
    '(',CsvAmountString
    t) <- CsvAmountString -> Maybe (Char, CsvAmountString)
    T.uncons CsvAmountString
    amtstr, Just (CsvAmountString
    amt,Char
    ')') <- CsvAmountString -> Maybe (CsvAmountString, Char)
    T.unsnoc CsvAmountString
    t = CsvAmountString -> CsvAmountString
    simplifySign (CsvAmountString -> CsvAmountString)
    -> CsvAmountString -> CsvAmountString
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> CsvAmountString
    negateStr CsvAmountString
    amt
      | Just (Char
    '-',CsvAmountString
    b) <- CsvAmountString -> Maybe (Char, CsvAmountString)
    T.uncons CsvAmountString
    amtstr, Just (Char
    '(',CsvAmountString
    t) <- CsvAmountString -> Maybe (Char, CsvAmountString)
    T.uncons CsvAmountString
    b, Just (CsvAmountString
    amt,Char
    ')') <- CsvAmountString -> Maybe (CsvAmountString, Char)
    T.unsnoc CsvAmountString
    t = CsvAmountString -> CsvAmountString
    simplifySign CsvAmountString
    amt
      | Just (Char
    '-',CsvAmountString
    m) <- CsvAmountString -> Maybe (Char, CsvAmountString)
    T.uncons CsvAmountString
    amtstr, Just (Char
    '-',CsvAmountString
    amt) <- CsvAmountString -> Maybe (Char, CsvAmountString)
    T.uncons CsvAmountString
    m = CsvAmountString
    amt
      | Just (Char
    '-',CsvAmountString
    m) <- CsvAmountString -> Maybe (Char, CsvAmountString)
    T.uncons CsvAmountString
    amtstr, Just (Char
    '+',CsvAmountString
    amt) <- CsvAmountString -> Maybe (Char, CsvAmountString)
    T.uncons CsvAmountString
    m = CsvAmountString -> CsvAmountString
    negateStr CsvAmountString
    amt
      | CsvAmountString
    amtstr CsvAmountString -> [CsvAmountString] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [CsvAmountString
    "-",CsvAmountString
    "+",CsvAmountString
    "()"] = CsvAmountString
    ""
      | Just (Char
    '+',CsvAmountString
    amt) <- CsvAmountString -> Maybe (Char, CsvAmountString)
    T.uncons CsvAmountString
    amtstr = CsvAmountString -> CsvAmountString
    simplifySign CsvAmountString
    amt
      | Bool
    otherwise = CsvAmountString
    amtstr

    negateStr :: Text -> Text
    negateStr :: CsvAmountString -> CsvAmountString
    negateStr CsvAmountString
    amtstr = case CsvAmountString -> Maybe (Char, CsvAmountString)
    T.uncons CsvAmountString
    amtstr of
        Just (Char
    '-',CsvAmountString
    s) -> CsvAmountString
    s
        Maybe (Char, CsvAmountString)
    _            -> Char -> CsvAmountString -> CsvAmountString
    T.cons Char
    '-' CsvAmountString
    amtstr

    --- ** tests
    _TESTS__________________________________________ :: a
    _TESTS__________________________________________ = a
    forall a. HasCallStack => a
    undefined

    tests_RulesReader :: TestTree
    tests_RulesReader = [Char] -> [TestTree] -> TestTree
    testGroup [Char]
    "RulesReader" [
       [Char] -> [TestTree] -> TestTree
    testGroup [Char]
    "parseCsvRules" [
         [Char] -> IO () -> TestTree
    testCase [Char]
    "empty file" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $
          [Char]
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    parseCsvRules [Char]
    "unknown" CsvAmountString
    "" Either
      (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= CsvRules
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    forall a b. b -> Either a b
    Right (CsvRulesParsed -> CsvRules
    mkrules CsvRulesParsed
    defrules)
       ]
      ,[Char] -> [TestTree] -> TestTree
    testGroup [Char]
    "rulesp" [
         [Char] -> IO () -> TestTree
    testCase [Char]
    "trailing comments" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $
          CsvRulesParsed
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvRules
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    forall s st e a.
    Stream s =>
    st
    -> StateT st (ParsecT e s Identity) a
    -> s
    -> Either (ParseErrorBundle s e) a
    parseWithState' CsvRulesParsed
    defrules StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvRules
    rulesp CsvAmountString
    "skip\n# \n#\n" Either
      (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= CsvRules
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    forall a b. b -> Either a b
    Right (CsvRulesParsed -> CsvRules
    mkrules (CsvRulesParsed -> CsvRules) -> CsvRulesParsed -> CsvRules
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed
    defrules{rdirectives = [("skip","")]})

        ,[Char] -> IO () -> TestTree
    testCase [Char]
    "trailing blank lines" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $
          CsvRulesParsed
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvRules
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    forall s st e a.
    Stream s =>
    st
    -> StateT st (ParsecT e s Identity) a
    -> s
    -> Either (ParseErrorBundle s e) a
    parseWithState' CsvRulesParsed
    defrules StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvRules
    rulesp CsvAmountString
    "skip\n\n  \n" Either
      (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (CsvRules
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    forall a b. b -> Either a b
    Right (CsvRulesParsed -> CsvRules
    mkrules (CsvRulesParsed -> CsvRules) -> CsvRulesParsed -> CsvRules
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed
    defrules{rdirectives = [("skip","")]}))

        ,[Char] -> IO () -> TestTree
    testCase [Char]
    "no final newline" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $
          CsvRulesParsed
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvRules
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    forall s st e a.
    Stream s =>
    st
    -> StateT st (ParsecT e s Identity) a
    -> s
    -> Either (ParseErrorBundle s e) a
    parseWithState' CsvRulesParsed
    defrules StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvRules
    rulesp CsvAmountString
    "skip" Either
      (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (CsvRules
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    forall a b. b -> Either a b
    Right (CsvRulesParsed -> CsvRules
    mkrules (CsvRulesParsed -> CsvRules) -> CsvRulesParsed -> CsvRules
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed
    defrules{rdirectives=[("skip","")]}))

        ,[Char] -> IO () -> TestTree
    testCase [Char]
    "assignment with empty value" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $
          CsvRulesParsed
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvRules
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    forall s st e a.
    Stream s =>
    st
    -> StateT st (ParsecT e s Identity) a
    -> s
    -> Either (ParseErrorBundle s e) a
    parseWithState' CsvRulesParsed
    defrules StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvRules
    rulesp CsvAmountString
    "account1 \nif foo\n  account2 foo\n" Either
      (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?=
            (CsvRules
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) CsvRules
    forall a b. b -> Either a b
    Right (CsvRulesParsed -> CsvRules
    mkrules (CsvRulesParsed -> CsvRules) -> CsvRulesParsed -> CsvRules
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed
    defrules{rassignments = [("account1","")], rconditionalblocks = [CB{cbMatchers=[RecordMatcher None (toRegex' "foo")],cbAssignments=[("account2","foo")]}]}))
       ]
      ,[Char] -> [TestTree] -> TestTree
    testGroup [Char]
    "conditionalblockp" [
        [Char] -> IO () -> TestTree
    testCase [Char]
    "space after conditional" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $ -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
           -- #1120
          CsvRulesParsed
    -> CsvRulesParser ConditionalBlock
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         ConditionalBlock
    forall s st e a.
    Stream s =>
    st
    -> StateT st (ParsecT e s Identity) a
    -> s
    -> Either (ParseErrorBundle s e) a
    parseWithState' CsvRulesParsed
    defrules CsvRulesParser ConditionalBlock
    conditionalblockp CsvAmountString
    "if a\n account2 b\n \n" Either
      (ParseErrorBundle CsvAmountString HledgerParseErrorData)
      ConditionalBlock
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         ConditionalBlock
    -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?=
            (ConditionalBlock
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         ConditionalBlock
    forall a b. b -> Either a b
    Right (ConditionalBlock
     -> Either
          (ParseErrorBundle CsvAmountString HledgerParseErrorData)
          ConditionalBlock)
    -> ConditionalBlock
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         ConditionalBlock
    forall a b. (a -> b) -> a -> b
    $ CB{cbMatchers :: [Matcher]
    cbMatchers=[MatcherPrefix -> Regexp -> Matcher
    RecordMatcher MatcherPrefix
    None (Regexp -> Matcher) -> Regexp -> Matcher
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> Regexp
    toRegexCI' CsvAmountString
    "a"],cbAssignments :: [(CsvAmountString, CsvAmountString)]
    cbAssignments=[(CsvAmountString
    "account2",CsvAmountString
    "b")]})

      ],

      [Char] -> [TestTree] -> TestTree
    testGroup [Char]
    "csvfieldreferencep" [
        [Char] -> IO () -> TestTree
    testCase [Char]
    "number" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         CsvAmountString
    forall s st e a.
    Stream s =>
    st
    -> StateT st (ParsecT e s Identity) a
    -> s
    -> Either (ParseErrorBundle s e) a
    parseWithState' CsvRulesParsed
    defrules StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    csvfieldreferencep CsvAmountString
    "%1" Either
      (ParseErrorBundle CsvAmountString HledgerParseErrorData)
      CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         CsvAmountString
    -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         CsvAmountString
    forall a b. b -> Either a b
    Right CsvAmountString
    "%1")
       ,[Char] -> IO () -> TestTree
    testCase [Char]
    "name" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         CsvAmountString
    forall s st e a.
    Stream s =>
    st
    -> StateT st (ParsecT e s Identity) a
    -> s
    -> Either (ParseErrorBundle s e) a
    parseWithState' CsvRulesParsed
    defrules StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    csvfieldreferencep CsvAmountString
    "%date" Either
      (ParseErrorBundle CsvAmountString HledgerParseErrorData)
      CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         CsvAmountString
    -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         CsvAmountString
    forall a b. b -> Either a b
    Right CsvAmountString
    "%date")
       ,[Char] -> IO () -> TestTree
    testCase [Char]
    "quoted name" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         CsvAmountString
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         CsvAmountString
    forall s st e a.
    Stream s =>
    st
    -> StateT st (ParsecT e s Identity) a
    -> s
    -> Either (ParseErrorBundle s e) a
    parseWithState' CsvRulesParsed
    defrules StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      CsvAmountString
    csvfieldreferencep CsvAmountString
    "%\"csv date\"" Either
      (ParseErrorBundle CsvAmountString HledgerParseErrorData)
      CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         CsvAmountString
    -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData)
         CsvAmountString
    forall a b. b -> Either a b
    Right CsvAmountString
    "%\"csv date\"")
       ]

      ,[Char] -> [TestTree] -> TestTree
    testGroup [Char]
    "matcherp" [

        [Char] -> IO () -> TestTree
    testCase [Char]
    "recordmatcherp" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $
          CsvRulesParsed
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    forall s st e a.
    Stream s =>
    st
    -> StateT st (ParsecT e s Identity) a
    -> s
    -> Either (ParseErrorBundle s e) a
    parseWithState' CsvRulesParsed
    defrules StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Matcher
    matcherp CsvAmountString
    "A A\n" Either
      (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (Matcher
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    forall a b. b -> Either a b
    Right (Matcher
     -> Either
          (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher)
    -> Matcher
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    forall a b. (a -> b) -> a -> b
    $ MatcherPrefix -> Regexp -> Matcher
    RecordMatcher MatcherPrefix
    None (Regexp -> Matcher) -> Regexp -> Matcher
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> Regexp
    toRegexCI' CsvAmountString
    "A A")

       ,[Char] -> IO () -> TestTree
    testCase [Char]
    "recordmatcherp.starts-with-&" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $
          CsvRulesParsed
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    forall s st e a.
    Stream s =>
    st
    -> StateT st (ParsecT e s Identity) a
    -> s
    -> Either (ParseErrorBundle s e) a
    parseWithState' CsvRulesParsed
    defrules StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Matcher
    matcherp CsvAmountString
    "& A A\n" Either
      (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (Matcher
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    forall a b. b -> Either a b
    Right (Matcher
     -> Either
          (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher)
    -> Matcher
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    forall a b. (a -> b) -> a -> b
    $ MatcherPrefix -> Regexp -> Matcher
    RecordMatcher MatcherPrefix
    And (Regexp -> Matcher) -> Regexp -> Matcher
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> Regexp
    toRegexCI' CsvAmountString
    "A A")

       ,[Char] -> IO () -> TestTree
    testCase [Char]
    "fieldmatcherp.starts-with-%" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $
          CsvRulesParsed
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    forall s st e a.
    Stream s =>
    st
    -> StateT st (ParsecT e s Identity) a
    -> s
    -> Either (ParseErrorBundle s e) a
    parseWithState' CsvRulesParsed
    defrules StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Matcher
    matcherp CsvAmountString
    "description A A\n" Either
      (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (Matcher
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    forall a b. b -> Either a b
    Right (Matcher
     -> Either
          (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher)
    -> Matcher
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    forall a b. (a -> b) -> a -> b
    $ MatcherPrefix -> Regexp -> Matcher
    RecordMatcher MatcherPrefix
    None (Regexp -> Matcher) -> Regexp -> Matcher
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> Regexp
    toRegexCI' CsvAmountString
    "description A A")

       ,[Char] -> IO () -> TestTree
    testCase [Char]
    "fieldmatcherp" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $
          CsvRulesParsed
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    forall s st e a.
    Stream s =>
    st
    -> StateT st (ParsecT e s Identity) a
    -> s
    -> Either (ParseErrorBundle s e) a
    parseWithState' CsvRulesParsed
    defrules StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Matcher
    matcherp CsvAmountString
    "%description A A\n" Either
      (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (Matcher
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    forall a b. b -> Either a b
    Right (Matcher
     -> Either
          (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher)
    -> Matcher
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    forall a b. (a -> b) -> a -> b
    $ MatcherPrefix -> CsvAmountString -> Regexp -> Matcher
    FieldMatcher MatcherPrefix
    None CsvAmountString
    "%description" (Regexp -> Matcher) -> Regexp -> Matcher
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> Regexp
    toRegexCI' CsvAmountString
    "A A")

       ,[Char] -> IO () -> TestTree
    testCase [Char]
    "fieldmatcherp.starts-with-&" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $
          CsvRulesParsed
    -> StateT
         CsvRulesParsed
         (ParsecT HledgerParseErrorData CsvAmountString Identity)
         Matcher
    -> CsvAmountString
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    forall s st e a.
    Stream s =>
    st
    -> StateT st (ParsecT e s Identity) a
    -> s
    -> Either (ParseErrorBundle s e) a
    parseWithState' CsvRulesParsed
    defrules StateT
      CsvRulesParsed
      (ParsecT HledgerParseErrorData CsvAmountString Identity)
      Matcher
    matcherp CsvAmountString
    "& %description A A\n" Either
      (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (Matcher
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    forall a b. b -> Either a b
    Right (Matcher
     -> Either
          (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher)
    -> Matcher
    -> Either
         (ParseErrorBundle CsvAmountString HledgerParseErrorData) Matcher
    forall a b. (a -> b) -> a -> b
    $ MatcherPrefix -> CsvAmountString -> Regexp -> Matcher
    FieldMatcher MatcherPrefix
    And CsvAmountString
    "%description" (Regexp -> Matcher) -> Regexp -> Matcher
    forall a b. (a -> b) -> a -> b
    $ CsvAmountString -> Regexp
    toRegexCI' CsvAmountString
    "A A")

       -- ,testCase "fieldmatcherp with operator" $
       --    parseWithState' defrules matcherp "%description ~ A A\n" @?= (Right $ FieldMatcher "%description" "A A")

       ]

     ,[Char] -> [TestTree] -> TestTree
    testGroup [Char]
    "getEffectiveAssignment" [
        let rules :: CsvRules
    rules = CsvRulesParsed -> CsvRules
    mkrules (CsvRulesParsed -> CsvRules) -> CsvRulesParsed -> CsvRules
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed
    defrules {rcsvfieldindexes=[("csvdate",1)],rassignments=[("date","%csvdate")]}

        in [Char] -> IO () -> TestTree
    testCase [Char]
    "toplevel" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $ CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    getEffectiveAssignment CsvRules
    rules [CsvAmountString
    "a",CsvAmountString
    "b"] CsvAmountString
    "date" Maybe CsvAmountString -> Maybe CsvAmountString -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (CsvAmountString -> Maybe CsvAmountString
    forall a. a -> Maybe a
    Just CsvAmountString
    "%csvdate")

       ,let rules :: CsvRules
    rules = CsvRulesParsed -> CsvRules
    mkrules (CsvRulesParsed -> CsvRules) -> CsvRulesParsed -> CsvRules
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed
    defrules{rcsvfieldindexes=[("csvdate",1)], rconditionalblocks=[CB [FieldMatcher None "%csvdate" $ toRegex' "a"] [("date","%csvdate")]]}
        in [Char] -> IO () -> TestTree
    testCase [Char]
    "conditional" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $ CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    getEffectiveAssignment CsvRules
    rules [CsvAmountString
    "a",CsvAmountString
    "b"] CsvAmountString
    "date" Maybe CsvAmountString -> Maybe CsvAmountString -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (CsvAmountString -> Maybe CsvAmountString
    forall a. a -> Maybe a
    Just CsvAmountString
    "%csvdate")

       ,let rules :: CsvRules
    rules = CsvRulesParsed -> CsvRules
    mkrules (CsvRulesParsed -> CsvRules) -> CsvRulesParsed -> CsvRules
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed
    defrules{rcsvfieldindexes=[("csvdate",1)], rconditionalblocks=[CB [FieldMatcher Not "%csvdate" $ toRegex' "a"] [("date","%csvdate")]]}
        in [Char] -> IO () -> TestTree
    testCase [Char]
    "negated-conditional-false" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $ CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    getEffectiveAssignment CsvRules
    rules [CsvAmountString
    "a",CsvAmountString
    "b"] CsvAmountString
    "date" Maybe CsvAmountString -> Maybe CsvAmountString -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (Maybe CsvAmountString
    forall a. Maybe a
    Nothing)

       ,let rules :: CsvRules
    rules = CsvRulesParsed -> CsvRules
    mkrules (CsvRulesParsed -> CsvRules) -> CsvRulesParsed -> CsvRules
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed
    defrules{rcsvfieldindexes=[("csvdate",1)], rconditionalblocks=[CB [FieldMatcher Not "%csvdate" $ toRegex' "b"] [("date","%csvdate")]]}
        in [Char] -> IO () -> TestTree
    testCase [Char]
    "negated-conditional-true" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $ CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    getEffectiveAssignment CsvRules
    rules [CsvAmountString
    "a",CsvAmountString
    "b"] CsvAmountString
    "date" Maybe CsvAmountString -> Maybe CsvAmountString -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (CsvAmountString -> Maybe CsvAmountString
    forall a. a -> Maybe a
    Just CsvAmountString
    "%csvdate")

       ,let rules :: CsvRules
    rules = CsvRulesParsed -> CsvRules
    mkrules (CsvRulesParsed -> CsvRules) -> CsvRulesParsed -> CsvRules
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed
    defrules{rcsvfieldindexes=[("csvdate",1),("description",2)], rconditionalblocks=[CB [FieldMatcher None "%csvdate" $ toRegex' "a", FieldMatcher None "%description" $ toRegex' "b"] [("date","%csvdate")]]}
        in [Char] -> IO () -> TestTree
    testCase [Char]
    "conditional-with-or-a" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $ CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    getEffectiveAssignment CsvRules
    rules [CsvAmountString
    "a"] CsvAmountString
    "date" Maybe CsvAmountString -> Maybe CsvAmountString -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (CsvAmountString -> Maybe CsvAmountString
    forall a. a -> Maybe a
    Just CsvAmountString
    "%csvdate")

       ,let rules :: CsvRules
    rules = CsvRulesParsed -> CsvRules
    mkrules (CsvRulesParsed -> CsvRules) -> CsvRulesParsed -> CsvRules
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed
    defrules{rcsvfieldindexes=[("csvdate",1),("description",2)], rconditionalblocks=[CB [FieldMatcher None "%csvdate" $ toRegex' "a", FieldMatcher None "%description" $ toRegex' "b"] [("date","%csvdate")]]}
        in [Char] -> IO () -> TestTree
    testCase [Char]
    "conditional-with-or-b" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $ CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    getEffectiveAssignment CsvRules
    rules [CsvAmountString
    "_", CsvAmountString
    "b"] CsvAmountString
    "date" Maybe CsvAmountString -> Maybe CsvAmountString -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (CsvAmountString -> Maybe CsvAmountString
    forall a. a -> Maybe a
    Just CsvAmountString
    "%csvdate")

       ,let rules :: CsvRules
    rules = CsvRulesParsed -> CsvRules
    mkrules (CsvRulesParsed -> CsvRules) -> CsvRulesParsed -> CsvRules
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed
    defrules{rcsvfieldindexes=[("csvdate",1),("description",2)], rconditionalblocks=[CB [FieldMatcher None "%csvdate" $ toRegex' "a", FieldMatcher And "%description" $ toRegex' "b"] [("date","%csvdate")]]}
        in [Char] -> IO () -> TestTree
    testCase [Char]
    "conditional.with-and" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $ CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    getEffectiveAssignment CsvRules
    rules [CsvAmountString
    "a", CsvAmountString
    "b"] CsvAmountString
    "date" Maybe CsvAmountString -> Maybe CsvAmountString -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (CsvAmountString -> Maybe CsvAmountString
    forall a. a -> Maybe a
    Just CsvAmountString
    "%csvdate")

       ,let rules :: CsvRules
    rules = CsvRulesParsed -> CsvRules
    mkrules (CsvRulesParsed -> CsvRules) -> CsvRulesParsed -> CsvRules
    forall a b. (a -> b) -> a -> b
    $ CsvRulesParsed
    defrules{rcsvfieldindexes=[("csvdate",1),("description",2)], rconditionalblocks=[CB [FieldMatcher None "%csvdate" $ toRegex' "a", FieldMatcher And "%description" $ toRegex' "b", FieldMatcher None "%description" $ toRegex' "c"] [("date","%csvdate")]]}
        in [Char] -> IO () -> TestTree
    testCase [Char]
    "conditional.with-and-or" (IO () -> TestTree) -> IO () -> TestTree
    forall a b. (a -> b) -> a -> b
    $ CsvRules
    -> [CsvAmountString] -> CsvAmountString -> Maybe CsvAmountString
    getEffectiveAssignment CsvRules
    rules [CsvAmountString
    "_", CsvAmountString
    "c"] CsvAmountString
    "date" Maybe CsvAmountString -> Maybe CsvAmountString -> IO ()
    forall a. (Eq a, Show a, HasCallStack) => a -> a -> IO ()
    @?= (CsvAmountString -> Maybe CsvAmountString
    forall a. a -> Maybe a
    Just CsvAmountString
    "%csvdate")

       ]

     ]