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.
This commit is contained in:
Simon Michael 2021-01-07 10:06:38 -08:00
parent 6035cdf1e0
commit c21b666130
2 changed files with 29 additions and 9 deletions

View File

@ -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

View File

@ -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