Merged
Conversation
Doc was previously pulling double-duty as the data structure constructed
by clients using the smart constructor/combinator functions (or
directly) and as the elements of the flattened structure rendered by
renderList. While this saved on duplication (FlatDoc looks a lot like
Doc!), it meant that renderList had to account for Doc constructors that
weren't meant to occur after calling unfoldD by throwing a runtime
error. The situation became more complicated with the introduction of
ANSI styling: we neglected at first to account for Styled and Linked
docs with inner Concats in unfoldD, which ultimately broke line-breaking
in some situations when styled text appeared at the end of the line.
Unfolding one Styled Concat into many Styled documents in the result was
somewhat plausible, but unaesthetic and seemed like it would be hard to
make correct.
Now we have FlatDoc, which is in effect an "intermediate representation"
for the Doc "interpreter". The general design is that any Doc can be
turned into a list of FlatDocs that carry equivalent information. Doc
constructors without an "inner" Doc that they modify have more or less
direct equivalents. There's no FlatDoc Empty or Concat constructors,
because these things are going to live in a list. The equivalents to the
constructors that have inner Docs instead have a NonEmpty of FlatDocs.
So really these FlatDocs aren't completely flat, they're just flat
enough for our purposes.
The main _actual_ point of doing this is to replace the nested Styled
and Linked Docs, which form a more complicated tree structure than
previously existed in DocLayout, with FStyleOpen/FStyleClose and
FLinkOpen/FLinkClose pairs, surrounding their flattened inner contents.
This makes it much simpler to measure the next printable non-space span
that follows a breaking space when that span happens to be styled.
Since FlatDocs aren't completely flat, just mostly flat, there's still
some contrived situations that can be measured incorrectly, which have
always existed, for example:
ghci> let p = "hi" <+> (prefixed "x" "mom")
ghci> render (Just 2) p
"hi\nxmom"
ghci> render (Just 3) p
"hi mom"
This is an arbitrary outcome, and the rendering of Docs that don't
really make sense is not a design goal of the library. Thus FlatDoc
doesn't completely unfold Prefixed, BeforeNonBlank, or Flush docs using
a tag-like idea, so we can keep refactoring of the rendering
implementation to a minimum and because it's not necessary to get the
fix we need for styled text.
Owner
|
Looks good to me! |
Contributor
Author
|
sweet. One thing I didn't explicitly note here is that now |
Owner
|
Deprecating |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I don't know if my commit message or documentation comments for this change are useful enough so feedback on that is welcome as well as on the code.
Fixes #30, the added test fails before and succeeds after.
doclayout and relevant pandoc benchmarks do not seem to have regressed.
Introduce FlatDocs and use them for rendering
Doc was previously pulling double-duty as the data structure constructed by clients using the smart constructor/combinator functions (or directly) and as the elements of the flattened structure rendered by renderList. While this saved on duplication (FlatDoc looks a lot like Doc!), it meant that renderList had to account for Doc constructors that weren’t meant to occur after calling unfoldD by throwing a runtime error. The situation became more complicated with the introduction of ANSI styling: we neglected at first to account for Styled and Linked docs with inner Concats in unfoldD, which ultimately broke line-breaking in some situations when styled text appeared at the end of the line. Unfolding one Styled Concat into many Styled documents in the result was somewhat plausible, but unaesthetic and seemed like it would be hard to make correct.
Now we have FlatDoc, which is in effect an “intermediate representation” for the Doc “interpreter”. The general design is that any Doc can be turned into a list of FlatDocs that carry equivalent information. Doc constructors without an “inner” Doc that they modify have more or less direct equivalents. There’s no FlatDoc Empty or Concat constructors, because these things are going to live in a list. The equivalents to the constructors that have inner Docs instead have a NonEmpty of FlatDocs. So really these FlatDocs aren’t completely flat, they’re just flat enough for our purposes.
The main actual point of doing this is to replace the nested Styled and Linked Docs, which form a more complicated tree structure than previously existed in DocLayout, with FStyleOpen/FStyleClose and FLinkOpen/FLinkClose pairs, surrounding their flattened inner contents. This makes it much simpler to measure the next printable non-space span that follows a breaking space when that span happens to be styled.
Since FlatDocs aren’t completely flat, just mostly flat, there’s still some contrived situations that can be measured incorrectly, which have always existed, for example:
This is an arbitrary outcome, and the rendering of Docs that don’t really make sense is not a design goal of the library. Thus FlatDoc doesn’t completely unfold Prefixed, BeforeNonBlank, or Flush docs using a tag-like idea, so we can keep refactoring of the rendering implementation to a minimum and because it’s not necessary to get the fix we need for styled text.