From c21b6661300eec672e5e34c3b13bf366b1e79c24 Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Thu, 7 Jan 2021 10:06:38 -0800 Subject: [PATCH] csv: handle more sign variations, eg a sign by itself simplifySign now covers a few more sign combinations that might arise. And in particular, it strips a standalone sign with no number, which simplifies sign flipping with amount-in/amount-out. --- hledger-lib/Hledger/Read/CsvReader.hs | 22 ++++++++++++++++++++-- hledger/hledger.m4.md | 16 +++++++++------- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/hledger-lib/Hledger/Read/CsvReader.hs b/hledger-lib/Hledger/Read/CsvReader.hs index 36d419a99..258c52eaa 100644 --- a/hledger-lib/Hledger/Read/CsvReader.hs +++ b/hledger-lib/Hledger/Read/CsvReader.hs @@ -1149,11 +1149,18 @@ unknownIncomeAccount = "income:unknown" type CsvAmountString = Text -- | Canonicalise the sign in a CSV amount string. --- Such strings can have a minus sign, negating parentheses, --- or any two of these (which cancels out). +-- 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)" @@ -1162,15 +1169,26 @@ type CsvAmountString = Text -- "1" -- >>> simplifySign "-(1)" -- "1" +-- >>> simplifySign "-+1" +-- "-1" -- >>> simplifySign "(-1)" -- "1" -- >>> simplifySign "((1))" -- "1" +-- >>> simplifySign "-" +-- "" +-- >>> simplifySign "()" +-- "" +-- >>> simplifySign "+" +-- "" simplifySign :: CsvAmountString -> CsvAmountString simplifySign amtstr | Just ('(',t) <- T.uncons amtstr, Just (amt,')') <- T.unsnoc t = simplifySign $ negateStr amt | Just ('-',b) <- T.uncons amtstr, Just ('(',t) <- T.uncons b, Just (amt,')') <- T.unsnoc t = simplifySign amt | Just ('-',m) <- T.uncons amtstr, Just ('-',amt) <- T.uncons m = amt + | Just ('-',m) <- T.uncons amtstr, Just ('+',amt) <- T.uncons m = negateStr amt + | amtstr `elem` ["-","+","()"] = "" + | Just ('+',amt) <- T.uncons amtstr = simplifySign amt | otherwise = amtstr negateStr :: Text -> Text diff --git a/hledger/hledger.m4.md b/hledger/hledger.m4.md index 0c6ab51dc..d589970e9 100644 --- a/hledger/hledger.m4.md +++ b/hledger/hledger.m4.md @@ -3936,12 +3936,11 @@ Here are the ways to set a posting's amount: guessing an appropriate sign. - **If hledger guesses the wrong sign:**\ - You can prepend a minus sign to flip it. But, do this only for non-empty values (see below). Eg: + You can prepend a minus sign to flip it. Eg: ```rules - # flip amount-out's sign, if it is non-empty: - if %amount-out . - amount-out -%amount-out + fields date, description, amount-in, amount-out + amount-out -%amount-out ``` - **If both fields contain a non-zero value:**\ @@ -3984,7 +3983,7 @@ Here are the ways to set a posting's amount: account1 assets:checking ``` -There is some automatic special handling for an amount's sign, for convenience: +There is some special handling for an amount's sign, to simplify parsing and sign-flipping: - **If an amount value begins with a plus sign:**\ that will be removed: `+AMT` becomes `AMT` @@ -3992,8 +3991,11 @@ There is some automatic special handling for an amount's sign, for convenience: - **If an amount value is parenthesised:**\ it will be de-parenthesised and sign-flipped: `(AMT)` becomes `-AMT` -- **If an amount value begins with two minus signs:**\ - they cancel out and will be removed: `--AMT` becomes `AMT` +- **If an amount value has two minus signs (or two sets of parentheses, or a minus sign and parentheses):**\ + they cancel out and will be removed: `--AMT` or `-(AMT)` becomes `AMT` + +- **If an amount value contains just a sign (or just a set of parentheses):**\ + that is removed, making it an empty value. `"+"` or `"-"` or `"()"` becomes `""`. ### Setting currency/commodity