fix:csv: fix %FIELD interpolation in assignments using \n [#2134]

In field assignment values we now parse %FIELD references, \MATCHGROUP references
and "\n" newline markers more carefully, so all can coexist.
Parsing these values might be slower than before, but hopefully not noticeably so.
This commit is contained in:
Simon Michael 2023-12-23 07:17:29 -10:00
parent 20c299684b
commit 8b45d4ba8c
2 changed files with 23 additions and 5 deletions

View File

@ -69,7 +69,7 @@ import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BL
import Data.Foldable (asum, toList)
import Text.Megaparsec hiding (match, parse)
import Text.Megaparsec.Char (char, newline, string)
import Text.Megaparsec.Char (char, newline, string, digitChar)
import Text.Megaparsec.Custom (parseErrorAt)
import Text.Printf (printf)
@ -788,11 +788,15 @@ renderTemplate rules record f t =
)
t
where
literaltextp = takeWhile1P Nothing isNotEscapeChar
matchrefp = liftA2 T.cons (char '\\') (takeWhile1P (Just "matchref") isDigit) :: Parsec HledgerParseErrorData Text Text -- XXX: can we return a parsed Int here?
fieldrefp = liftA2 T.cons (char '%') (takeWhile1P (Just "reference") isFieldNameChar) :: Parsec HledgerParseErrorData Text Text
literaltextp :: SimpleTextParser Text
literaltextp = some (nonBackslashOrPercent <|> nonRefBackslash <|> nonRefPercent) <&> T.pack
where
nonBackslashOrPercent = noneOf ['\\', '%'] <?> "character other than backslash or percent"
nonRefBackslash = try (char '\\' <* notFollowedBy digitChar) <?> "backslash that does not begin a match group reference"
nonRefPercent = try (char '%' <* notFollowedBy (satisfy isFieldNameChar)) <?> "percent that does not begin a field reference"
matchrefp = liftA2 T.cons (char '\\') (takeWhile1P (Just "matchref") isDigit)
fieldrefp = liftA2 T.cons (char '%') (takeWhile1P (Just "reference") isFieldNameChar)
isFieldNameChar c = isAlphaNum c || c == '_' || c == '-'
isNotEscapeChar c = c /='%' && c /= '\\'
-- | Replace something that looks like a Regex match group reference with the
-- resulting match group value after applying the Regex.

View File

@ -1117,6 +1117,20 @@ $ ./csvtest.sh tag:ttag
>=
# ** 58. handle newlines in an assignment value, without breaking interpolations (#2134)
<
2023-01-01,1
RULES
fields date, amount
account1 (a)
comment \n %amount
$ ./csvtest.sh
2023-01-01
; 1
(a) 1
>=
# ** .
#<
#$ ./csvtest.sh