From 20c299684b01c68b45eaa7c4aa86bd6be3c5688c Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Sat, 23 Dec 2023 07:18:20 -1000 Subject: [PATCH] dev:csv: clarify renderTemplate [#2134] --- hledger-lib/Hledger/Read/RulesReader.hs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/hledger-lib/Hledger/Read/RulesReader.hs b/hledger-lib/Hledger/Read/RulesReader.hs index c0c5c703a..c6ffb2724 100644 --- a/hledger-lib/Hledger/Read/RulesReader.hs +++ b/hledger-lib/Hledger/Read/RulesReader.hs @@ -297,6 +297,9 @@ type HledgerFieldName = Text -- containing csv field references to be interpolated. type FieldTemplate = Text +-- | A reference to a regular expression match group. Eg \1. +type MatchGroupReference = Text + -- | A strptime date parsing pattern, as supported by Data.Time.Format. type DateFormat = Text @@ -773,23 +776,27 @@ isBlockActive rules record CB{..} = any (all matcherMatches) $ groupedMatchers c matcherPrefix (FieldMatcher prefix _ _) = prefix -- | Render a field assignment's template, possibly interpolating referenced --- CSV field values. Outer whitespace is removed from interpolated values. +-- CSV field values or match groups. Outer whitespace is removed from interpolated values. renderTemplate :: CsvRules -> CsvRecord -> HledgerFieldName -> FieldTemplate -> Text -renderTemplate rules record f t = maybe t mconcat $ parseMaybe - (many $ takeWhile1P Nothing isNotEscapeChar - <|> replaceRegexGroupReference rules record f <$> matchp - <|> replaceCsvFieldReference rules record <$> referencep) +renderTemplate rules record f t = + maybe t mconcat $ parseMaybe + (many + ( literaltextp + <|> (matchrefp <&> replaceRegexGroupReference rules record f) + <|> (fieldrefp <&> replaceCsvFieldReference rules record) + ) + ) t where - -- XXX: can we return a parsed Int here? - matchp = liftA2 T.cons (char '\\') (takeWhile1P (Just "matchref") isDigit) :: Parsec HledgerParseErrorData Text Text - referencep = liftA2 T.cons (char '%') (takeWhile1P (Just "reference") isFieldNameChar) :: Parsec HledgerParseErrorData Text Text + 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 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. -replaceRegexGroupReference :: CsvRules -> CsvRecord -> HledgerFieldName -> FieldTemplate -> Text +replaceRegexGroupReference :: CsvRules -> CsvRecord -> HledgerFieldName -> MatchGroupReference -> Text replaceRegexGroupReference rules record f s = case T.uncons s of Just ('\\', group) -> fromMaybe "" $ regexMatchValue rules record f group _ -> s