{-# LANGUAGE OverloadedStrings #-}
module Hledger.Read.TimeclockReader (
reader,
timeclockfilep,
)
where
import Control.Monad
import Control.Monad.Except (ExceptT, liftEither)
import Control.Monad.State.Strict
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import Text.Megaparsec hiding (parse)
import Hledger.Data
import Hledger.Read.Common
import Hledger.Utils
import Data.Text as T (strip)
reader :: MonadIO m => Reader m
reader :: forall (m :: * -> *). MonadIO m => Reader m
reader = Reader
{rFormat :: StorageFormat
rFormat = StorageFormat
Timeclock
,rExtensions :: [String]
rExtensions = [String
"timeclock"]
,rReadFn :: InputOpts -> String -> Text -> ExceptT String IO Journal
rReadFn = InputOpts -> String -> Text -> ExceptT String IO Journal
parse
,rParser :: MonadIO m => ErroringJournalParser m Journal
rParser = ErroringJournalParser m Journal
MonadIO m => ErroringJournalParser m Journal
forall (m :: * -> *). MonadIO m => JournalParser m Journal
timeclockfilep
}
parse :: InputOpts -> FilePath -> Text -> ExceptT String IO Journal
parse :: InputOpts -> String -> Text -> ExceptT String IO Journal
parse InputOpts
iopts String
fp Text
t = ErroringJournalParser IO Journal
-> InputOpts -> String -> Text -> ExceptT String IO Journal
initialiseAndParseJournal ErroringJournalParser IO Journal
forall (m :: * -> *). MonadIO m => JournalParser m Journal
timeclockfilep InputOpts
iopts String
fp Text
t
ExceptT String IO Journal
-> (Journal -> ExceptT String IO Journal)
-> ExceptT String IO Journal
forall a b.
ExceptT String IO a
-> (a -> ExceptT String IO b) -> ExceptT String IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Either String Journal -> ExceptT String IO Journal
forall e (m :: * -> *) a. MonadError e m => Either e a -> m a
liftEither (Either String Journal -> ExceptT String IO Journal)
-> (Journal -> Either String Journal)
-> Journal
-> ExceptT String IO Journal
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [AccountAlias] -> Journal -> Either String Journal
journalApplyAliases (InputOpts -> [AccountAlias]
aliasesFromOpts InputOpts
iopts)
ExceptT String IO Journal
-> (Journal -> ExceptT String IO Journal)
-> ExceptT String IO Journal
forall a b.
ExceptT String IO a
-> (a -> ExceptT String IO b) -> ExceptT String IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= InputOpts -> String -> Text -> Journal -> ExceptT String IO Journal
journalFinalise InputOpts
iopts String
fp Text
t
timeclockfilep :: MonadIO m => JournalParser m ParsedJournal
timeclockfilep :: forall (m :: * -> *). MonadIO m => JournalParser m Journal
timeclockfilep = do StateT Journal (ParsecT HledgerParseErrorData Text m) ()
-> StateT Journal (ParsecT HledgerParseErrorData Text m) [()]
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many StateT Journal (ParsecT HledgerParseErrorData Text m) ()
forall {m :: * -> *}.
StateT Journal (ParsecT HledgerParseErrorData Text m) ()
timeclockitemp
StateT Journal (ParsecT HledgerParseErrorData Text m) ()
forall e s (m :: * -> *). MonadParsec e s m => m ()
eof
j :: Journal
j@Journal{jparsetimeclockentries :: Journal -> [TimeclockEntry]
jparsetimeclockentries=[TimeclockEntry]
es} <- JournalParser m Journal
forall s (m :: * -> *). MonadState s m => m s
get
LocalTime
now <- IO LocalTime
-> StateT Journal (ParsecT HledgerParseErrorData Text m) LocalTime
forall a.
IO a -> StateT Journal (ParsecT HledgerParseErrorData Text m) a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO LocalTime
getCurrentLocalTime
let j' :: Journal
j' = Journal
j{jtxns = reverse $ timeclockEntriesToTransactions now $ reverse es, jparsetimeclockentries = []}
Journal -> JournalParser m Journal
forall a.
a -> StateT Journal (ParsecT HledgerParseErrorData Text m) a
forall (m :: * -> *) a. Monad m => a -> m a
return Journal
j'
where
timeclockitemp :: StateT Journal (ParsecT HledgerParseErrorData Text m) ()
timeclockitemp = [StateT Journal (ParsecT HledgerParseErrorData Text m) ()]
-> StateT Journal (ParsecT HledgerParseErrorData Text m) ()
forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, Alternative m) =>
f (m a) -> m a
choice [
StateT Journal (ParsecT HledgerParseErrorData Text m) ()
-> StateT Journal (ParsecT HledgerParseErrorData Text m) ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ParsecT HledgerParseErrorData Text m ()
-> StateT Journal (ParsecT HledgerParseErrorData Text m) ()
forall (m :: * -> *) a. Monad m => m a -> StateT Journal m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift ParsecT HledgerParseErrorData Text m ()
forall (m :: * -> *). TextParser m ()
emptyorcommentlinep)
, JournalParser m TimeclockEntry
forall (m :: * -> *). JournalParser m TimeclockEntry
timeclockentryp JournalParser m TimeclockEntry
-> (TimeclockEntry
-> StateT Journal (ParsecT HledgerParseErrorData Text m) ())
-> StateT Journal (ParsecT HledgerParseErrorData Text m) ()
forall a b.
StateT Journal (ParsecT HledgerParseErrorData Text m) a
-> (a -> StateT Journal (ParsecT HledgerParseErrorData Text m) b)
-> StateT Journal (ParsecT HledgerParseErrorData Text m) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \TimeclockEntry
e -> (Journal -> Journal)
-> StateT Journal (ParsecT HledgerParseErrorData Text m) ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify' (\Journal
j -> Journal
j{jparsetimeclockentries = e : jparsetimeclockentries j})
] StateT Journal (ParsecT HledgerParseErrorData Text m) ()
-> String
-> StateT Journal (ParsecT HledgerParseErrorData Text m) ()
forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> String -> m a
<?> String
"timeclock entry, comment line, or empty line"
timeclockentryp :: JournalParser m TimeclockEntry
timeclockentryp :: forall (m :: * -> *). JournalParser m TimeclockEntry
timeclockentryp = do
SourcePos
pos <- StateT Journal (ParsecT HledgerParseErrorData Text m) SourcePos
forall s e (m :: * -> *).
(TraversableStream s, MonadParsec e s m) =>
m SourcePos
getSourcePos
Char
code <- [Token Text]
-> StateT
Journal (ParsecT HledgerParseErrorData Text m) (Token Text)
forall (f :: * -> *) e s (m :: * -> *).
(Foldable f, MonadParsec e s m) =>
f (Token s) -> m (Token s)
oneOf (String
"bhioO" :: [Char])
ParsecT HledgerParseErrorData Text m ()
-> StateT Journal (ParsecT HledgerParseErrorData Text m) ()
forall (m :: * -> *) a. Monad m => m a -> StateT Journal m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift ParsecT HledgerParseErrorData Text m ()
forall s (m :: * -> *).
(Stream s, Token s ~ Char) =>
ParsecT HledgerParseErrorData s m ()
skipNonNewlineSpaces1
LocalTime
datetime <- JournalParser m LocalTime
forall (m :: * -> *). JournalParser m LocalTime
datetimep
Text
account <- (Maybe Text -> Text)
-> StateT
Journal (ParsecT HledgerParseErrorData Text m) (Maybe Text)
-> StateT Journal (ParsecT HledgerParseErrorData Text m) Text
forall a b.
(a -> b)
-> StateT Journal (ParsecT HledgerParseErrorData Text m) a
-> StateT Journal (ParsecT HledgerParseErrorData Text m) b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
"") (StateT Journal (ParsecT HledgerParseErrorData Text m) (Maybe Text)
-> StateT Journal (ParsecT HledgerParseErrorData Text m) Text)
-> StateT
Journal (ParsecT HledgerParseErrorData Text m) (Maybe Text)
-> StateT Journal (ParsecT HledgerParseErrorData Text m) Text
forall a b. (a -> b) -> a -> b
$ StateT Journal (ParsecT HledgerParseErrorData Text m) Text
-> StateT
Journal (ParsecT HledgerParseErrorData Text m) (Maybe Text)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (StateT Journal (ParsecT HledgerParseErrorData Text m) Text
-> StateT
Journal (ParsecT HledgerParseErrorData Text m) (Maybe Text))
-> StateT Journal (ParsecT HledgerParseErrorData Text m) Text
-> StateT
Journal (ParsecT HledgerParseErrorData Text m) (Maybe Text)
forall a b. (a -> b) -> a -> b
$ ParsecT HledgerParseErrorData Text m ()
-> StateT Journal (ParsecT HledgerParseErrorData Text m) ()
forall (m :: * -> *) a. Monad m => m a -> StateT Journal m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift ParsecT HledgerParseErrorData Text m ()
forall s (m :: * -> *).
(Stream s, Token s ~ Char) =>
ParsecT HledgerParseErrorData s m ()
skipNonNewlineSpaces1 StateT Journal (ParsecT HledgerParseErrorData Text m) ()
-> StateT Journal (ParsecT HledgerParseErrorData Text m) Text
-> StateT Journal (ParsecT HledgerParseErrorData Text m) Text
forall a b.
StateT Journal (ParsecT HledgerParseErrorData Text m) a
-> StateT Journal (ParsecT HledgerParseErrorData Text m) b
-> StateT Journal (ParsecT HledgerParseErrorData Text m) b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> StateT Journal (ParsecT HledgerParseErrorData Text m) Text
forall (m :: * -> *). JournalParser m Text
modifiedaccountnamep
Text
description <- (Maybe Text -> Text)
-> StateT
Journal (ParsecT HledgerParseErrorData Text m) (Maybe Text)
-> StateT Journal (ParsecT HledgerParseErrorData Text m) Text
forall a b.
(a -> b)
-> StateT Journal (ParsecT HledgerParseErrorData Text m) a
-> StateT Journal (ParsecT HledgerParseErrorData Text m) b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Text -> (Text -> Text) -> Maybe Text -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" Text -> Text
T.strip) (StateT Journal (ParsecT HledgerParseErrorData Text m) (Maybe Text)
-> StateT Journal (ParsecT HledgerParseErrorData Text m) Text)
-> StateT
Journal (ParsecT HledgerParseErrorData Text m) (Maybe Text)
-> StateT Journal (ParsecT HledgerParseErrorData Text m) Text
forall a b. (a -> b) -> a -> b
$ StateT Journal (ParsecT HledgerParseErrorData Text m) Text
-> StateT
Journal (ParsecT HledgerParseErrorData Text m) (Maybe Text)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (StateT Journal (ParsecT HledgerParseErrorData Text m) Text
-> StateT
Journal (ParsecT HledgerParseErrorData Text m) (Maybe Text))
-> StateT Journal (ParsecT HledgerParseErrorData Text m) Text
-> StateT
Journal (ParsecT HledgerParseErrorData Text m) (Maybe Text)
forall a b. (a -> b) -> a -> b
$ ParsecT HledgerParseErrorData Text m Text
-> StateT Journal (ParsecT HledgerParseErrorData Text m) Text
forall (m :: * -> *) a. Monad m => m a -> StateT Journal m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (ParsecT HledgerParseErrorData Text m Text
-> StateT Journal (ParsecT HledgerParseErrorData Text m) Text)
-> ParsecT HledgerParseErrorData Text m Text
-> StateT Journal (ParsecT HledgerParseErrorData Text m) Text
forall a b. (a -> b) -> a -> b
$ ParsecT HledgerParseErrorData Text m ()
forall s (m :: * -> *).
(Stream s, Token s ~ Char) =>
ParsecT HledgerParseErrorData s m ()
skipNonNewlineSpaces1 ParsecT HledgerParseErrorData Text m ()
-> ParsecT HledgerParseErrorData Text m Text
-> ParsecT HledgerParseErrorData Text m Text
forall a b.
ParsecT HledgerParseErrorData Text m a
-> ParsecT HledgerParseErrorData Text m b
-> ParsecT HledgerParseErrorData Text m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ParsecT HledgerParseErrorData Text m Text
forall (m :: * -> *). TextParser m Text
descriptionp
(Text
comment, [Tag]
tags) <- ParsecT HledgerParseErrorData Text m (Text, [Tag])
-> StateT
Journal (ParsecT HledgerParseErrorData Text m) (Text, [Tag])
forall (m :: * -> *) a. Monad m => m a -> StateT Journal m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift ParsecT HledgerParseErrorData Text m (Text, [Tag])
forall (m :: * -> *). TextParser m (Text, [Tag])
transactioncommentp
TimeclockEntry -> JournalParser m TimeclockEntry
forall a.
a -> StateT Journal (ParsecT HledgerParseErrorData Text m) a
forall (m :: * -> *) a. Monad m => a -> m a
return (TimeclockEntry -> JournalParser m TimeclockEntry)
-> TimeclockEntry -> JournalParser m TimeclockEntry
forall a b. (a -> b) -> a -> b
$ SourcePos
-> TimeclockCode
-> LocalTime
-> Text
-> Text
-> Text
-> [Tag]
-> TimeclockEntry
TimeclockEntry SourcePos
pos (String -> TimeclockCode
forall a. Read a => String -> a
read [Char
code]) LocalTime
datetime Text
account Text
description Text
comment [Tag]
tags