From 190233b57697bb73a9cc7c00d616916e9565a45d Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Fri, 28 Feb 2020 01:03:27 -0800 Subject: [PATCH] timedot: more org support: dates/entries can be org headlines Org headline prefixes (stars and space at beginning of line) are ignored. --- hledger-lib/Hledger/Read/TimedotReader.hs | 28 +++++++----- hledger-lib/hledger_timedot.m4.md | 56 +++++++++++++++++++---- tests/timedot.test | 11 +++++ 3 files changed, 74 insertions(+), 21 deletions(-) diff --git a/hledger-lib/Hledger/Read/TimedotReader.hs b/hledger-lib/Hledger/Read/TimedotReader.hs index 51221340e..d7c12dcf5 100644 --- a/hledger-lib/Hledger/Read/TimedotReader.hs +++ b/hledger-lib/Hledger/Read/TimedotReader.hs @@ -87,21 +87,26 @@ timedotfilep :: JournalParser m ParsedJournal timedotfilep = do many timedotfileitemp eof get - where - timedotfileitemp :: JournalParser m () - timedotfileitemp = do - traceparse "timedotfileitemp" - choice [ - void $ lift emptyorcommentlinep - ,timedotdayp >>= \ts -> modify' (addTransactions ts) - ] "timedot day entry, or default year or comment line or blank line" + +timedotfileitemp :: JournalParser m () +timedotfileitemp = do + traceparse "timedotfileitemp" + choice [ + try $ void $ lift emptyorcommentlinep' + ,try timedotdayp >>= \ts -> modify' (addTransactions ts) + ,lift $ skipSome anySingle >> eolof -- an initial line not beginning with a date, ignore + ] "timedot day entry, or default year or comment line or blank line" addTransactions :: [Transaction] -> Journal -> Journal addTransactions ts j = foldl' (flip ($)) j (map addTransaction ts) +emptyorcommentlinep' = optional orgheadingprefixp >> emptyorcommentlinep + +orgheadingprefixp = skipSome (char '*') >> skipSome spacenonewline + -- | Parse timedot day entries to zero or more time transactions for that day. -- @ --- 2/1 +-- 2020/2/1 optional day description -- fos.haskell .... .. -- biz.research . -- inc.client1 .... .... .... .... .... .... @@ -109,8 +114,9 @@ addTransactions ts j = foldl' (flip ($)) j (map addTransaction ts) timedotdayp :: JournalParser m [Transaction] timedotdayp = do traceparse " timedotdayp" + lift $ optional orgheadingprefixp d <- datep <* lift eolof - es <- catMaybes <$> many (const Nothing <$> try (lift emptyorcommentlinep) <|> + es <- catMaybes <$> many (const Nothing <$> try (lift emptyorcommentlinep') <|> Just <$> (notFollowedBy datep >> timedotentryp)) return $ map (\t -> t{tdate=d}) es -- <$> many timedotentryp @@ -122,7 +128,7 @@ timedotentryp :: JournalParser m Transaction timedotentryp = do traceparse " timedotentryp" pos <- genericSourcePos <$> getSourcePos - lift (skipMany spacenonewline) + lift $ optional $ choice [orgheadingprefixp, skipSome spacenonewline] a <- modifiedaccountnamep lift (skipMany spacenonewline) hours <- diff --git a/hledger-lib/hledger_timedot.m4.md b/hledger-lib/hledger_timedot.m4.md index 3c7fc3a8b..fff56bf44 100644 --- a/hledger-lib/hledger_timedot.m4.md +++ b/hledger-lib/hledger_timedot.m4.md @@ -22,15 +22,16 @@ so it could be used to represent dated quantities other than time. In the docs below we'll assume it's time. A timedot file contains a series of day entries. -A day entry begins with a date, and is followed by category/quantity pairs, one per line. -Dates are hledger-style [simple dates](journal.html#simple-dates) (see hledger_journal(5)). -Categories are hledger-style account names, optionally indented. -As in a hledger journal, there must be at least two spaces between the category (account name) and the quantity. +A day entry begins with a non-indented hledger-style [simple date](journal.html#simple-dates) (see hledger_journal(5)). + +This is followed by optionally-indented timelog items for that day, one per line. +Each timelog item is a note, usually a hledger:style:account:name representing a time category, +followed by two or more spaces, and a quantity. Quantities can be written as: -- a sequence of dots (.) representing quarter hours. - Spaces may optionally be used for grouping and readability. +- time dots: a sequence of dots (.) representing quarter hours. + Spaces may optionally be used for grouping. Eg: .... .. - an integral or decimal number, representing hours. @@ -43,8 +44,21 @@ Quantities can be written as: The following equivalencies are assumed, currently: 1m = 60s, 1h = 60m, 1d = 24h, 1w = 7d, 1mo = 30d, 1y=365d. -Blank lines and lines beginning with #, ; or * are ignored. -An example: +There is some flexibility allowing notes and todo lists to be kept +right in the time log, if needed: + +- Blank lines and lines beginning with `#` or `;` are ignored. + +- Lines not ending with a double-space and quantity are parsed as + items taking no time, which will not appear in balance reports by + default. (Add -E to see them.) + +- Org headline prefixes (stars followed by at least one space, at the + start of a line) are ignored, so a timedot file can also be an org + outline. Emacs org mode users can use these to add structure and + control which parts of the file are visible. + +Examples: ```timedot # on this day, 6h was spent on client work, 1.5h on haskell FOSS work, etc. @@ -58,8 +72,6 @@ inc:client1 .... .... biz:research . ``` -Or with numbers: - ```timedot 2016/2/3 inc:client1 4 @@ -67,6 +79,30 @@ fos:hledger 3 biz:research 1 ``` +```timedot +* Time log +** 2020-01-01 +*** adm:time . +*** adm:finance . +``` + +```timedot +** 2020-02-29 +*** DONE +0700 yoga +*** UNPLANNED +*** BEGUN +hom:chores + cleaning ... + water plants + outdoor - one full watering can + indoor - light watering +*** TODO +adm:planning: trip +*** LATER + +``` + Reporting: ```shell diff --git a/tests/timedot.test b/tests/timedot.test index 06cf4beee..5b2602129 100644 --- a/tests/timedot.test +++ b/tests/timedot.test @@ -16,3 +16,14 @@ $ hledger -f- print >=0 +# 2. Org mode headline prefixes are ignored. +< +* 2020-01-01 +** a:aa 1 + +$ hledger -f- print +2020-01-01 * + (a:aa) 1.00 + +>=0 +