dev:csv: clarify renderTemplate [#2134]

This commit is contained in:
Simon Michael 2023-12-23 07:18:20 -10:00
parent 8f6b7b202e
commit 20c299684b

View File

@ -297,6 +297,9 @@ type HledgerFieldName = Text
-- containing csv field references to be interpolated. -- containing csv field references to be interpolated.
type FieldTemplate = Text 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. -- | A strptime date parsing pattern, as supported by Data.Time.Format.
type DateFormat = Text type DateFormat = Text
@ -773,23 +776,27 @@ isBlockActive rules record CB{..} = any (all matcherMatches) $ groupedMatchers c
matcherPrefix (FieldMatcher prefix _ _) = prefix matcherPrefix (FieldMatcher prefix _ _) = prefix
-- | Render a field assignment's template, possibly interpolating referenced -- | 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 :: CsvRules -> CsvRecord -> HledgerFieldName -> FieldTemplate -> Text
renderTemplate rules record f t = maybe t mconcat $ parseMaybe renderTemplate rules record f t =
(many $ takeWhile1P Nothing isNotEscapeChar maybe t mconcat $ parseMaybe
<|> replaceRegexGroupReference rules record f <$> matchp (many
<|> replaceCsvFieldReference rules record <$> referencep) ( literaltextp
<|> (matchrefp <&> replaceRegexGroupReference rules record f)
<|> (fieldrefp <&> replaceCsvFieldReference rules record)
)
)
t t
where where
-- XXX: can we return a parsed Int here? literaltextp = takeWhile1P Nothing isNotEscapeChar
matchp = liftA2 T.cons (char '\\') (takeWhile1P (Just "matchref") isDigit) :: Parsec HledgerParseErrorData Text Text matchrefp = liftA2 T.cons (char '\\') (takeWhile1P (Just "matchref") isDigit) :: Parsec HledgerParseErrorData Text Text -- XXX: can we return a parsed Int here?
referencep = liftA2 T.cons (char '%') (takeWhile1P (Just "reference") isFieldNameChar) :: Parsec HledgerParseErrorData Text Text fieldrefp = liftA2 T.cons (char '%') (takeWhile1P (Just "reference") isFieldNameChar) :: Parsec HledgerParseErrorData Text Text
isFieldNameChar c = isAlphaNum c || c == '_' || c == '-' isFieldNameChar c = isAlphaNum c || c == '_' || c == '-'
isNotEscapeChar c = c /='%' && c /= '\\' isNotEscapeChar c = c /='%' && c /= '\\'
-- | Replace something that looks like a Regex match group reference with the -- | Replace something that looks like a Regex match group reference with the
-- resulting match group value after applying the Regex. -- 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 replaceRegexGroupReference rules record f s = case T.uncons s of
Just ('\\', group) -> fromMaybe "" $ regexMatchValue rules record f group Just ('\\', group) -> fromMaybe "" $ regexMatchValue rules record f group
_ -> s _ -> s