diff --git a/hledger-lib/Hledger/Read/Common.hs b/hledger-lib/Hledger/Read/Common.hs index e4d5fa7e8..996bd5013 100644 --- a/hledger-lib/Hledger/Read/Common.hs +++ b/hledger-lib/Hledger/Read/Common.hs @@ -137,6 +137,7 @@ import Text.Megaparsec import Text.Megaparsec.Char import Text.Megaparsec.Char.Lexer (decimal) import Text.Megaparsec.Custom +import Control.Applicative.Permutations import Hledger.Data import Hledger.Utils @@ -610,11 +611,11 @@ spaceandamountormissingp = amountp :: JournalParser m Amount amountp = label "amount" $ do let spaces = lift $ skipMany spacenonewline - amount <- amountwithoutpricep - spaces - _elotprice <- optional $ lotpricep <* spaces - mprice <- optional $ priceamountp <* spaces - _elotprice <- optional $ lotpricep + amount <- amountwithoutpricep <* spaces + (mprice, _elotprice, _elotdate) <- runPermutation $ + (,,) <$> toPermutationWithDefault Nothing (Just <$> priceamountp <* spaces) + <*> toPermutationWithDefault Nothing (Just <$> lotpricep <* spaces) + <*> toPermutationWithDefault Nothing (Just <$> lotdatep <* spaces) pure $ amount { aprice = mprice } -- XXX Just like amountp but don't allow lot prices. Needed for balanceassertionp. @@ -761,21 +762,33 @@ balanceassertionp = do , baposition = sourcepos } --- Parse a Ledger-style fixed {=PRICE} or non-fixed {PRICE} lot price, --- as a Left or Right Amount respectively. +-- Parse a Ledger-style fixed {=UNITPRICE} or non-fixed {UNITPRICE} +-- or fixed {{=TOTALPRICE}} or non-fixed {{TOTALPRICE}} lot price, +-- and ignore it. -- https://www.ledger-cli.org/3.0/doc/ledger3.html#Fixing-Lot-Prices . -lotpricep :: JournalParser m (Either Amount Amount) -lotpricep = (do +lotpricep :: JournalParser m () +lotpricep = label "ledger-style lot price" $ do char '{' doublebrace <- option False $ char '{' >> pure True - fixed <- fmap isJust $ optional $ lift (skipMany spacenonewline) >> char '=' + _fixed <- fmap isJust $ optional $ lift (skipMany spacenonewline) >> char '=' lift (skipMany spacenonewline) - a <- amountwithoutpricep + _a <- amountwithoutpricep lift (skipMany spacenonewline) char '}' when (doublebrace) $ void $ char '}' - return $ (if fixed then Left else Right) a - ) "ledger-style lot price or fixed lot price" + return () + +-- Parse a Ledger-style lot date [DATE], and ignore it. +-- https://www.ledger-cli.org/3.0/doc/ledger3.html#Fixing-Lot-Prices . +lotdatep :: JournalParser m () +lotdatep = (do + char '[' + lift (skipMany spacenonewline) + _d <- datep + lift (skipMany spacenonewline) + char ']' + return () + ) "ledger-style lot date" -- | Parse a string representation of a number for its value and display -- attributes. diff --git a/hledger-lib/Hledger/Read/JournalReader.hs b/hledger-lib/Hledger/Read/JournalReader.hs index ca0b3113d..c04044096 100644 --- a/hledger-lib/Hledger/Read/JournalReader.hs +++ b/hledger-lib/Hledger/Read/JournalReader.hs @@ -862,6 +862,9 @@ tests_JournalReader = tests "JournalReader" [ ,test "lot price before transaction price" $ assertParse (postingp Nothing) " a 1A {1B} @ 1B\n" ,test "lot price after transaction price" $ assertParse (postingp Nothing) " a 1A @ 1B {1B}\n" ,test "lot price after balance assertion not allowed" $ assertParseError (postingp Nothing) " a 1A @ 1B = 1A {1B}\n" "unexpected '{'" + ,test "only lot date" $ assertParse (postingp Nothing) " a 1A [2000-01-01]\n" + ,test "transaction price, lot price, lot date" $ assertParse (postingp Nothing) " a 1A @ 1B {1B} [2000-01-01]\n" + ,test "lot date, lot price, transaction price" $ assertParse (postingp Nothing) " a 1A [2000-01-01] {1B} @ 1B\n" ,test "balance assertion over entire contents of account" $ assertParse (postingp Nothing) " a $1 == $1\n" ] diff --git a/hledger-lib/hledger_journal.m4.md b/hledger-lib/hledger_journal.m4.md index 1ae895a5d..04039a731 100644 --- a/hledger-lib/hledger_journal.m4.md +++ b/hledger-lib/hledger_journal.m4.md @@ -579,18 +579,16 @@ $ hledger bal -N --flat -B €100 assets:euros ``` -## Lot Prices +## Lot Prices and Lot Dates Ledger allows another kind of price, -[lot price](http://ledger-cli.org/3.0/doc/ledger3.html#Fixing-Lot-Prices), -to be specified in curly braces -(three variants: `{UNITPRICE}`, `{{TOTALPRICE}}`, `{=FIXEDUNITPRICE}`). -This is normally used to select a lot when selling investments. -hledger will parse these, for compatibility with Ledger journals, but -currently ignores them. -They may appear after the posting amount, before or after the -[transaction price](#transaction-prices) if any, and before the -balance assertion if any. +[lot price](http://ledger-cli.org/3.0/doc/ledger3.html#Fixing-Lot-Prices) +(four variants: `{UNITPRICE}`, `{{TOTALPRICE}}`, `{=FIXEDUNITPRICE}`, `{{=FIXEDTOTALPRICE}}`), +and/or a lot date (`[DATE]`) to be specified. +These are normally used to select a lot when selling investments. +hledger will parse these, for compatibility with Ledger journals, but currently ignores them. +A [transaction price](#transaction-prices), lot price and/or lot date may appear in any order, +after the posting amount and before the balance assertion if any. ## Balance Assertions