lib: followingcomment: parse no comment as "", not "\n"
Same-line & next-line comments of transactions, postings, etc. are now parsed a bit more precisely. Previously parsing no comment gave the same result as an empty comment (a single newline); now it gives an empty string. Also, and perhaps as a consequence of the above, when there's no same-line comment but there is a next-line comment, we'll insert an empty first line, otherwise next-line comments would get moved up to the same line when rendered. Some doctests have been added.
This commit is contained in:
parent
46d6971da7
commit
e88a9c4a5f
@ -122,6 +122,9 @@ import Text.Megaparsec.Custom
|
|||||||
import Hledger.Data
|
import Hledger.Data
|
||||||
import Hledger.Utils
|
import Hledger.Utils
|
||||||
|
|
||||||
|
-- $setup
|
||||||
|
-- >>> :set -XOverloadedStrings
|
||||||
|
|
||||||
-- | A hledger journal reader is a triple of storage format name, a
|
-- | A hledger journal reader is a triple of storage format name, a
|
||||||
-- detector of that format, and a parser from that format to Journal.
|
-- detector of that format, and a parser from that format to Journal.
|
||||||
data Reader = Reader {
|
data Reader = Reader {
|
||||||
@ -977,26 +980,46 @@ emptyorcommentlinep = do
|
|||||||
-- until the next newline. This parser should extract the "content" from
|
-- until the next newline. This parser should extract the "content" from
|
||||||
-- comments. The resulting parser returns this content plus the raw text
|
-- comments. The resulting parser returns this content plus the raw text
|
||||||
-- of the comment itself.
|
-- of the comment itself.
|
||||||
followingcommentp' :: (Monoid a) => TextParser m a -> TextParser m (Text, a)
|
--
|
||||||
|
-- See followingcommentp for tests.
|
||||||
|
--
|
||||||
|
followingcommentp' :: (Monoid a, Show a) => TextParser m a -> TextParser m (Text, a)
|
||||||
followingcommentp' contentp = do
|
followingcommentp' contentp = do
|
||||||
skipMany spacenonewline
|
skipMany spacenonewline
|
||||||
sameLine <- try headerp *> match' contentp <|> pure ("", mempty)
|
-- there can be 0 or 1 sameLine
|
||||||
|
sameLine <- try headerp *> ((:[]) <$> match' contentp) <|> pure []
|
||||||
_ <- eolof
|
_ <- eolof
|
||||||
lowerLines <- many $
|
-- there can be 0 or more nextLines
|
||||||
|
nextLines <- many $
|
||||||
try (skipSome spacenonewline *> headerp) *> match' contentp <* eolof
|
try (skipSome spacenonewline *> headerp) *> match' contentp <* eolof
|
||||||
|
let
|
||||||
let (textLines, results) = unzip $ sameLine : lowerLines
|
-- if there's just a next-line comment, insert an empty same-line comment
|
||||||
strippedCommentText = T.unlines $ map T.strip textLines
|
-- so the next-line comment doesn't get rendered as a same-line comment.
|
||||||
result = mconcat results
|
sameLine' | null sameLine && not (null nextLines) = [("",mempty)]
|
||||||
pure (strippedCommentText, result)
|
| otherwise = sameLine
|
||||||
|
(texts, contents) = unzip $ sameLine' ++ nextLines
|
||||||
|
strippedCommentText = T.unlines $ map T.strip texts
|
||||||
|
commentContent = mconcat contents
|
||||||
|
pure (strippedCommentText, commentContent)
|
||||||
|
|
||||||
where
|
where
|
||||||
headerp = char ';' *> skipMany spacenonewline
|
headerp = char ';' *> skipMany spacenonewline
|
||||||
|
|
||||||
{-# INLINABLE followingcommentp' #-}
|
{-# INLINABLE followingcommentp' #-}
|
||||||
|
|
||||||
-- | Parse the text of a (possibly multiline) comment following a journal
|
-- | Parse the text of a (possibly multiline) comment following a journal item.
|
||||||
-- item.
|
--
|
||||||
|
-- >>> rtp followingcommentp "" -- no comment
|
||||||
|
-- Right ""
|
||||||
|
-- >>> rtp followingcommentp ";" -- just a (empty) same-line comment. newline is added
|
||||||
|
-- Right "\n"
|
||||||
|
-- >>> rtp followingcommentp "; \n"
|
||||||
|
-- Right "\n"
|
||||||
|
-- >>> rtp followingcommentp ";\n ;\n" -- a same-line and a next-line comment
|
||||||
|
-- Right "\n\n"
|
||||||
|
-- >>> rtp followingcommentp "\n ;\n" -- just a next-line comment. Insert an empty same-line comment so the next-line comment doesn't become a same-line comment.
|
||||||
|
-- Right "\n\n"
|
||||||
|
--
|
||||||
followingcommentp :: TextParser m Text
|
followingcommentp :: TextParser m Text
|
||||||
followingcommentp =
|
followingcommentp =
|
||||||
fst <$> followingcommentp' (void $ takeWhileP Nothing (/= '\n'))
|
fst <$> followingcommentp' (void $ takeWhileP Nothing (/= '\n'))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user