mirror of
https://github.com/simonmichael/hledger.git
synced 2024-11-07 21:15:19 +03:00
imp: timedot: make one multi-posting transaction per date line (#1754)
Descriptions and comments are now more straightforward and similar to journal format.
This commit is contained in:
parent
50349f81f7
commit
bbecd611f1
@ -1,22 +1,16 @@
|
||||
2016/2/1
|
||||
fos:haskell ....
|
||||
biz:research .
|
||||
inc:client1 .... .... .... .... .... ....
|
||||
# sample.timedot
|
||||
# This is a comment line
|
||||
; Also a comment line
|
||||
* Org headings before the first date are also comment lines
|
||||
|
||||
2016/2/2
|
||||
biz:research .
|
||||
inc:client1 .... .... ..
|
||||
2023-01-01 transaction description
|
||||
biz:research ....
|
||||
inc:client1 .... ..
|
||||
|
||||
2016/2/3
|
||||
biz:research .
|
||||
fos:hledger .... .... ...
|
||||
biz:it .... ..
|
||||
inc:client1 .... .... .... .... ....
|
||||
|
||||
2016/2/4
|
||||
biz:research .... ..
|
||||
fos:hledger .... .... ....
|
||||
fos:ledger 0.25
|
||||
fos:haskell .5
|
||||
inc:client1 2
|
||||
2023-01-01 different transaction, same day ; with a comment and transaction-tag:
|
||||
; more transaction comment lines ? currently ignored
|
||||
fos:haskell .... ; a posting comment and posting-tag:
|
||||
; more posting comment lines ? currently ignored
|
||||
per:admin ....
|
||||
|
||||
** 2023-01-02 ; dates are allowed to be org headings
|
||||
|
@ -43,7 +43,6 @@ import Control.Monad
|
||||
import Control.Monad.Except (ExceptT, liftEither)
|
||||
import Control.Monad.State.Strict
|
||||
import Data.Char (isSpace)
|
||||
import Data.List (foldl')
|
||||
import Data.Text (Text)
|
||||
import qualified Data.Text as T
|
||||
import Data.Time (Day)
|
||||
@ -113,7 +112,7 @@ preamblep = do
|
||||
many $ notFollowedBy datelinep >> (lift $ emptyorcommentlinep "#;*")
|
||||
lift $ traceparse' "preamblep"
|
||||
|
||||
-- | Parse timedot day entries to zero or more time transactions for that day.
|
||||
-- | Parse timedot day entries to multi-posting time transactions for that day.
|
||||
-- @
|
||||
-- 2020/2/1 optional day description
|
||||
-- fos.haskell .... ..
|
||||
@ -123,14 +122,22 @@ preamblep = do
|
||||
dayp :: JournalParser m ()
|
||||
dayp = label "timedot day entry" $ do
|
||||
lift $ traceparse "dayp"
|
||||
pos <- getSourcePos
|
||||
(date,desc,comment,tags) <- datelinep
|
||||
commentlinesp
|
||||
ts <- many $ entryp <* commentlinesp
|
||||
modify' $ addTransactions $ map (\t -> t{tdate=date, tdescription=desc, tcomment=comment, ttags=tags}) ts
|
||||
lift $ traceparse' "dayp"
|
||||
where
|
||||
addTransactions :: [Transaction] -> Journal -> Journal
|
||||
addTransactions ts j = foldl' (flip ($)) j (map addTransaction ts)
|
||||
ps <- many $ timedotentryp <* commentlinesp
|
||||
endpos <- getSourcePos
|
||||
-- lift $ traceparse' "dayp end"
|
||||
let t = txnTieKnot $ nulltransaction{
|
||||
tsourcepos = (pos, endpos),
|
||||
tdate = date,
|
||||
tstatus = Cleared,
|
||||
tdescription = desc,
|
||||
tcomment = comment,
|
||||
ttags = tags,
|
||||
tpostings = ps
|
||||
}
|
||||
modify' $ addTransaction t
|
||||
|
||||
datelinep :: JournalParser m (Day,Text,Text,[Tag])
|
||||
datelinep = do
|
||||
@ -139,7 +146,7 @@ datelinep = do
|
||||
date <- datep
|
||||
desc <- T.strip <$> lift descriptionp
|
||||
(comment, tags) <- lift transactioncommentp
|
||||
lift $ traceparse' "datelinep"
|
||||
-- lift $ traceparse' "datelinep end"
|
||||
return (date, desc, comment, tags)
|
||||
|
||||
-- | Zero or more empty lines or hash/semicolon comment lines
|
||||
@ -165,10 +172,9 @@ orgheadingprefixp = do
|
||||
-- @
|
||||
-- fos.haskell .... ..
|
||||
-- @
|
||||
entryp :: JournalParser m Transaction
|
||||
entryp = do
|
||||
lift $ traceparse "entryp"
|
||||
pos <- getSourcePos
|
||||
timedotentryp :: JournalParser m Posting
|
||||
timedotentryp = do
|
||||
lift $ traceparse "timedotentryp"
|
||||
notFollowedBy datelinep
|
||||
lift $ optional $ choice [orgheadingprefixp, skipNonNewlineSpaces1]
|
||||
a <- modifiedaccountnamep
|
||||
@ -188,21 +194,13 @@ entryp = do
|
||||
(c,s) = case mcs of
|
||||
Just (defc,defs) -> (defc, defs{asprecision=max (asprecision defs) (Precision 2)})
|
||||
_ -> ("", amountstyle{asprecision=Precision 2})
|
||||
t = nulltransaction{
|
||||
tsourcepos = (pos, pos),
|
||||
tstatus = Cleared,
|
||||
tpostings = [
|
||||
nullposting{paccount=a
|
||||
-- lift $ traceparse' "timedotentryp end"
|
||||
return $ nullposting{paccount=a
|
||||
,pamount=mixedAmount $ nullamt{acommodity=c, aquantity=hours, astyle=s}
|
||||
,ptype=VirtualPosting
|
||||
,pcomment=comment
|
||||
,ptags=tags
|
||||
,ptransaction=Just t
|
||||
}
|
||||
]
|
||||
}
|
||||
lift $ traceparse' "entryp"
|
||||
return t
|
||||
|
||||
type Hours = Quantity
|
||||
|
||||
|
@ -4174,63 +4174,55 @@ Compared to [`timeclock` format](#timeclock), it is
|
||||
A timedot file contains a series of day entries, which might look like this:
|
||||
|
||||
```timedot
|
||||
2021-08-04
|
||||
hom:errands .... ....
|
||||
fos:hledger:timedot .. ; docs
|
||||
per:admin:finance
|
||||
2023-05-01
|
||||
hom:errands .... .... ; two hours
|
||||
fos:hledger:timedot .. ; half an hour
|
||||
per:admin:finance
|
||||
```
|
||||
|
||||
hledger reads this as three time transactions on this day,
|
||||
with each dot representing a quarter-hour spent:
|
||||
hledger reads this as a transaction on this day with three (unbalanced) postings,
|
||||
where each dot represents "0.25". No commodity is assumed, but normally we interpret
|
||||
it as hours, with each dot representing a quarter-hour. It's convenient, though
|
||||
not required, to group the dots in fours for easy reading.
|
||||
|
||||
```shell
|
||||
$ hledger -f a.timedot print # .timedot file extension activates the timedot reader
|
||||
2021-08-04 *
|
||||
(hom:errands) 2.00
|
||||
|
||||
2021-08-04 *
|
||||
(fos:hledger:timedot) 0.50 ; docs
|
||||
|
||||
2021-08-04 *
|
||||
(per:admin:finance) 0
|
||||
$ hledger -f a.timedot print # .timedot file extension (or timedot: prefix) is required
|
||||
2023-05-01 *
|
||||
(hom:errands) 2.00 ; two hours
|
||||
(fos:hledger:timedot) 0.50 ; half an hour
|
||||
(per:admin:finance) 0
|
||||
```
|
||||
|
||||
A day entry begins with a date line:
|
||||
A transaction begins with a non-indented **[simple date](#simple-dates)** (Y-M-D, Y/M/D, or Y.M.D).
|
||||
It can optionally be preceded by one or more stars and a space, for Emacs org mode compatibility.
|
||||
It can optionally be followed on the same line by a transaction description,
|
||||
and/or a transaction comment following a semicolon.
|
||||
|
||||
- a non-indented **[simple date](#simple-dates)** (Y-M-D, Y/M/D, or Y.M.D).
|
||||
After the date line are zero or more time postings, consisting of:
|
||||
|
||||
Optionally this can be followed on the same line by
|
||||
|
||||
- a **common description** for this day's transactions.
|
||||
- a **common comment** for this day's transactions, following a semicolon (`;`).
|
||||
|
||||
After the date line are zero or more optionally-indented time transactions, consisting of:
|
||||
|
||||
- an **account name** - any word or phrase, usually a hledger-style [account name](#account-names).
|
||||
- an **account name** - any hledger-style [account name](#account-names), optionally hierarchical, optionally indented.
|
||||
- **two or more spaces** - a field separator, required if there is an amount (as in journal format).
|
||||
- a **timedot amount** - dots representing quarter hours, or a number representing hours, optionally with a unit suffix.
|
||||
- an **posting comment** for this transaction, following with semicolon.
|
||||
- an optional **timedot amount** - dots representing quarter hours, or a number representing hours, optionally with a unit suffix.
|
||||
- an optional **posting comment** following a semicolon.
|
||||
|
||||
In more detail, timedot amounts can be:
|
||||
Timedot amounts can be:
|
||||
|
||||
- **dots**: zero or more period characters, each representing one quarter-hour.
|
||||
- **dots**: zero or more period characters (`.`), each representing 0.25.
|
||||
Spaces are ignored and can be used for grouping.
|
||||
Eg: `.... ..`
|
||||
|
||||
- a **number**, representing hours. Eg: `1.5`
|
||||
- or a **number**. Eg: `1.5`
|
||||
|
||||
- a **number immediately followed by a unit symbol**
|
||||
`s`, `m`, `h`, `d`, `w`, `mo`, or `y`,
|
||||
representing seconds, minutes, hours, days weeks, months or years.
|
||||
Eg `1.5h` or `90m`.
|
||||
The following equivalencies are assumed:\
|
||||
`60s` = `1m`,
|
||||
`60m` = `1h`,
|
||||
`24h` = `1d`,
|
||||
`7d` = `1w`,
|
||||
`30d` = `1mo`,
|
||||
- or a **number immediately followed by a unit symbol**
|
||||
`s`, `m`, `h`, `d`, `w`, `mo`, or `y`.
|
||||
These are interpreted as seconds, minutes, hours, days weeks, months or years, and converted to hours, assuming:\
|
||||
`60s` = `1m`,
|
||||
`60m` = `1h`,
|
||||
`24h` = `1d`,
|
||||
`7d` = `1w`,
|
||||
`30d` = `1mo`,
|
||||
`365d` = `1y`.
|
||||
(This unit will not be visible in the generated transaction amount, which is always in hours.)
|
||||
Eg `90m` is parsed as `1.5`.
|
||||
|
||||
There is some added flexibility to help with keeping time log data
|
||||
in the same file as your notes, todo lists, etc.:
|
||||
@ -4238,14 +4230,14 @@ in the same file as your notes, todo lists, etc.:
|
||||
- Blank lines and lines beginning with `#` or `;` are ignored.
|
||||
|
||||
- Before the first date line, lines beginning with `*` are ignored.
|
||||
From the first date line onward, a sequence of `*`'s followed by a space
|
||||
|
||||
- From the first date line onward, one or more `*`'s followed by a space
|
||||
at beginning of lines (ie, the headline prefix used by Emacs Org mode) is ignored.
|
||||
This means the time log can be kept under an Org headline,
|
||||
and date lines or time transaction lines can be Org headlines.
|
||||
|
||||
- Lines not ending with a double-space and amount are
|
||||
parsed as transactions with zero amount.
|
||||
(Most hledger reports hide these by default; add -E to see them.)
|
||||
- Lines not ending with a double-space and amount are parsed as postings with zero amount.
|
||||
Note hledger's register reports hide these by default (add -E to see them).
|
||||
|
||||
More examples:
|
||||
|
||||
|
@ -1,58 +1,44 @@
|
||||
# 1. basic timedot entry
|
||||
# timedot format
|
||||
|
||||
<
|
||||
# file comment
|
||||
; another file comment
|
||||
# sample.timedot
|
||||
# This is a comment line
|
||||
; Also a comment line
|
||||
* Org headings before the first date are also comment lines
|
||||
|
||||
2020-01-01
|
||||
a:aa 1
|
||||
b:bb 2
|
||||
2023-01-01 transaction description
|
||||
biz:research ....
|
||||
inc:client1 .... ..
|
||||
|
||||
2023-01-01 different transaction, same day ; with a comment and transaction-tag:
|
||||
; more transaction comment lines ? currently ignored
|
||||
fos:haskell .... ; a posting comment and posting-tag:
|
||||
; more posting comment lines ? currently ignored
|
||||
per:admin ....
|
||||
|
||||
** 2023-01-02 ; dates are allowed to be org headings
|
||||
|
||||
# 1. The above timedot is converted to these transactions.
|
||||
$ hledger -ftimedot:- print
|
||||
2020-01-01 *
|
||||
(a:aa) 1.00
|
||||
2023-01-01 * transaction description
|
||||
(biz:research) 1.00
|
||||
(inc:client1) 1.50
|
||||
|
||||
2020-01-01 *
|
||||
(b:bb) 2.00
|
||||
2023-01-01 * different transaction, same day ; with a comment and transaction-tag:
|
||||
(fos:haskell) 1.00 ; a posting comment and posting-tag:
|
||||
(per:admin) 1.00
|
||||
|
||||
>=0
|
||||
|
||||
# 2. Org mode headline prefixes are ignored.
|
||||
<
|
||||
* 2020-01-01
|
||||
** a:aa 1
|
||||
|
||||
$ hledger -ftimedot:- print
|
||||
2020-01-01 *
|
||||
(a:aa) 1.00
|
||||
|
||||
>=0
|
||||
|
||||
# 3. Command-line account aliases are applied.
|
||||
$ hledger -ftimedot:- print --alias a=b
|
||||
2020-01-01 *
|
||||
(b:aa) 1.00
|
||||
|
||||
>=0
|
||||
|
||||
# 4. A common day description and comment, and posting comments are supported.
|
||||
<
|
||||
2023-01-01 day description ; day comment, day-tag:
|
||||
a ....
|
||||
b .... ; posting comment, posting-tag:
|
||||
|
||||
$ hledger -ftimedot:- print
|
||||
2023-01-01 * day description ; day comment, day-tag:
|
||||
(a) 1.00
|
||||
|
||||
2023-01-01 * day description ; day comment, day-tag:
|
||||
(b) 1.00 ; posting comment, posting-tag:
|
||||
2023-01-02 * ; dates are allowed to be org headings
|
||||
|
||||
>=
|
||||
|
||||
# 5. Transaction descriptions, comments and tags are parsed properly.
|
||||
$ hledger -ftimedot:- descriptions tag:day-tag
|
||||
day description
|
||||
# 2. And this register.
|
||||
$ hledger -ftimedot:- reg
|
||||
2023-01-01 transaction descr.. (biz:research) 1.00 1.00
|
||||
(inc:client1) 1.50 2.50
|
||||
2023-01-01 different transac.. (fos:haskell) 1.00 3.50
|
||||
(per:admin) 1.00 4.50
|
||||
|
||||
# 6. Posting comments and tags are parsed properly.
|
||||
$ hledger -ftimedot:- reg tag:posting-tag
|
||||
2023-01-01 day description (b) 1.00 1.00
|
||||
# 3. Tags are recognised. Account aliases are applied.
|
||||
$ hledger -ftimedot:- reg tag:posting-tag --alias fos:haskell=λ
|
||||
2023-01-01 different transac.. (λ) 1.00 1.00
|
||||
|
Loading…
Reference in New Issue
Block a user